2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
7 const util = require("util");
9 const deprecateContext = util.deprecate(() => {},
10 "Hook.context is deprecated and will be removed");
12 const CALL_DELEGATE = function(...args) {
13 this.call = this._createCall("sync");
14 return this.call(...args);
16 const CALL_ASYNC_DELEGATE = function(...args) {
17 this.callAsync = this._createCall("async");
18 return this.callAsync(...args);
20 const PROMISE_DELEGATE = function(...args) {
21 this.promise = this._createCall("promise");
22 return this.promise(...args);
26 constructor(args = [], name = undefined) {
30 this.interceptors = [];
31 this._call = CALL_DELEGATE;
32 this.call = CALL_DELEGATE;
33 this._callAsync = CALL_ASYNC_DELEGATE;
34 this.callAsync = CALL_ASYNC_DELEGATE;
35 this._promise = PROMISE_DELEGATE;
36 this.promise = PROMISE_DELEGATE;
39 this.compile = this.compile;
41 this.tapAsync = this.tapAsync;
42 this.tapPromise = this.tapPromise;
46 throw new Error("Abstract: should be overridden");
52 interceptors: this.interceptors,
58 _tap(type, options, fn) {
59 if (typeof options === "string") {
63 } else if (typeof options !== "object" || options === null) {
64 throw new Error("Invalid tap options");
66 if (typeof options.name !== "string" || options.name === "") {
67 throw new Error("Missing name for tap");
69 if (typeof options.context !== "undefined") {
72 options = Object.assign({ type, fn }, options);
73 options = this._runRegisterInterceptors(options);
74 this._insert(options);
78 this._tap("sync", options, fn);
81 tapAsync(options, fn) {
82 this._tap("async", options, fn);
85 tapPromise(options, fn) {
86 this._tap("promise", options, fn);
89 _runRegisterInterceptors(options) {
90 for (const interceptor of this.interceptors) {
91 if (interceptor.register) {
92 const newOptions = interceptor.register(options);
93 if (newOptions !== undefined) {
101 withOptions(options) {
102 const mergeOptions = opt =>
103 Object.assign({}, options, typeof opt === "string" ? { name: opt } : opt);
107 tap: (opt, fn) => this.tap(mergeOptions(opt), fn),
108 tapAsync: (opt, fn) => this.tapAsync(mergeOptions(opt), fn),
109 tapPromise: (opt, fn) => this.tapPromise(mergeOptions(opt), fn),
110 intercept: interceptor => this.intercept(interceptor),
111 isUsed: () => this.isUsed(),
112 withOptions: opt => this.withOptions(mergeOptions(opt))
117 return this.taps.length > 0 || this.interceptors.length > 0;
120 intercept(interceptor) {
121 this._resetCompilation();
122 this.interceptors.push(Object.assign({}, interceptor));
123 if (interceptor.register) {
124 for (let i = 0; i < this.taps.length; i++) {
125 this.taps[i] = interceptor.register(this.taps[i]);
130 _resetCompilation() {
131 this.call = this._call;
132 this.callAsync = this._callAsync;
133 this.promise = this._promise;
137 this._resetCompilation();
139 if (typeof item.before === "string") {
140 before = new Set([item.before]);
141 } else if (Array.isArray(item.before)) {
142 before = new Set(item.before);
145 if (typeof item.stage === "number") {
148 let i = this.taps.length;
151 const x = this.taps[i];
152 this.taps[i + 1] = x;
153 const xStage = x.stage || 0;
155 if (before.has(x.name)) {
156 before.delete(x.name);
159 if (before.size > 0) {
163 if (xStage > stage) {
173 Object.setPrototypeOf(Hook.prototype, null);
175 module.exports = Hook;