"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.spans = exports.webpackInvalidSpans = void 0;
var _webpack = require("next/dist/compiled/webpack/webpack");
const pluginName = 'ProfilingPlugin';
const spans = new WeakMap();
exports.spans = spans;
const webpackInvalidSpans = new WeakMap();
exports.webpackInvalidSpans = webpackInvalidSpans;
function getNormalModuleLoaderHook(compilation) {
    if (_webpack.isWebpack5) {
        // @ts-ignore TODO: Remove ignore when webpack 5 is stable
        return _webpack.webpack.NormalModule.getCompilationHooks(compilation).loader;
    }
    return compilation.hooks.normalModuleLoader;
}
class ProfilingPlugin {
    constructor({ runWebpackSpan  }){
        this.runWebpackSpan = runWebpackSpan;
    }
    apply(compiler) {
        this.traceTopLevelHooks(compiler);
        this.traceCompilationHooks(compiler);
        this.compiler = compiler;
    }
    traceHookPair(spanName, startHook, stopHook, { parentSpan , attrs , onStart , onStop  } = {
    }) {
        let span;
        startHook.tap(pluginName, (...params)=>{
            const attributes = attrs ? attrs(...params) : attrs;
            if (spanName === 'webpack-invalidated' && attributes.name === 'client') {
                debugger;
            }
            span = parentSpan ? parentSpan().traceChild(spanName, attributes) : this.runWebpackSpan.traceChild(spanName, attributes);
            if (onStart) onStart(span);
        });
        stopHook.tap(pluginName, ()=>{
            // `stopHook` may be triggered when `startHook` has not in cases
            // where `stopHook` is used as the terminating event for more
            // than one pair of hooks.
            if (!span) {
                return;
            }
            if (onStop) onStop();
            span.stop();
        });
    }
    traceTopLevelHooks(compiler) {
        this.traceHookPair('webpack-compilation', _webpack.isWebpack5 ? compiler.hooks.beforeCompile : compiler.hooks.compile, _webpack.isWebpack5 ? compiler.hooks.afterCompile : compiler.hooks.done, {
            parentSpan: ()=>webpackInvalidSpans.get(compiler) || this.runWebpackSpan
            ,
            attrs: ()=>({
                    name: compiler.name
                })
            ,
            onStart: (span)=>spans.set(compiler, span)
        });
        if (compiler.options.mode === 'development') {
            this.traceHookPair('webpack-invalidated', compiler.hooks.invalid, compiler.hooks.done, {
                onStart: (span)=>webpackInvalidSpans.set(compiler, span)
                ,
                onStop: ()=>webpackInvalidSpans.delete(compiler)
                ,
                attrs: (fileName)=>({
                        name: compiler.name,
                        trigger: fileName || 'manual'
                    })
            });
        }
    }
    traceCompilationHooks(compiler) {
        this.traceHookPair('webpack-emit', compiler.hooks.emit, compiler.hooks.afterEmit, {
            parentSpan: ()=>webpackInvalidSpans.get(compiler) || this.runWebpackSpan
        });
        compiler.hooks.compilation.tap(pluginName, (compilation)=>{
            compilation.hooks.buildModule.tap(pluginName, (module)=>{
                var ref;
                const compilerSpan = spans.get(compiler);
                if (!compilerSpan) {
                    return;
                }
                const moduleType = (()=>{
                    if (!module.userRequest) {
                        return '';
                    }
                    return module.userRequest.split('.').pop();
                })();
                const issuerModule = compilation === null || compilation === void 0 ? void 0 : (ref = compilation.moduleGraph) === null || ref === void 0 ? void 0 : ref.getIssuer(module);
                let span;
                const spanName = `build-module${moduleType ? `-${moduleType}` : ''}`;
                const issuerSpan = issuerModule && spans.get(issuerModule);
                if (issuerSpan) {
                    span = issuerSpan.traceChild(spanName);
                } else {
                    span = compilerSpan.traceChild(spanName);
                }
                span.setAttribute('name', module.userRequest);
                spans.set(module, span);
            });
            getNormalModuleLoaderHook(compilation).tap(pluginName, (loaderContext, module)=>{
                const moduleSpan = spans.get(module);
                loaderContext.currentTraceSpan = moduleSpan;
            });
            compilation.hooks.succeedModule.tap(pluginName, (module)=>{
                var ref;
                (ref = spans.get(module)) === null || ref === void 0 ? void 0 : ref.stop();
            });
            this.traceHookPair('webpack-compilation-chunk-graph', compilation.hooks.beforeChunks, compilation.hooks.afterChunks, {
                parentSpan: ()=>spans.get(compiler)
            });
            this.traceHookPair('webpack-compilation-optimize', compilation.hooks.optimize, compilation.hooks.reviveModules, {
                parentSpan: ()=>spans.get(compiler)
            });
            this.traceHookPair('webpack-compilation-optimize-modules', compilation.hooks.optimizeModules, compilation.hooks.afterOptimizeModules, {
                parentSpan: ()=>spans.get(compiler)
            });
            this.traceHookPair('webpack-compilation-optimize-chunks', compilation.hooks.optimizeChunks, compilation.hooks.afterOptimizeChunks, {
                parentSpan: ()=>spans.get(compiler)
            });
            this.traceHookPair('webpack-compilation-optimize-tree', compilation.hooks.optimizeTree, compilation.hooks.afterOptimizeTree, {
                parentSpan: ()=>spans.get(compiler)
            });
            this.traceHookPair('webpack-compilation-hash', compilation.hooks.beforeHash, compilation.hooks.afterHash, {
                parentSpan: ()=>spans.get(compiler)
            });
        });
    }
}
exports.ProfilingPlugin = ProfilingPlugin;

//# sourceMappingURL=profiling-plugin.js.map