Apply module bundling
[platform/framework/web/wrtjs.git] / node_modules / tapable / lib / Hook.js
1 /*
2         MIT License http://www.opensource.org/licenses/mit-license.php
3         Author Tobias Koppers @sokra
4 */
5 "use strict";
6
7 const util = require("util");
8
9 const deprecateContext = util.deprecate(() => {},
10 "Hook.context is deprecated and will be removed");
11
12 const CALL_DELEGATE = function(...args) {
13         this.call = this._createCall("sync");
14         return this.call(...args);
15 };
16 const CALL_ASYNC_DELEGATE = function(...args) {
17         this.callAsync = this._createCall("async");
18         return this.callAsync(...args);
19 };
20 const PROMISE_DELEGATE = function(...args) {
21         this.promise = this._createCall("promise");
22         return this.promise(...args);
23 };
24
25 class Hook {
26         constructor(args = [], name = undefined) {
27                 this._args = args;
28                 this.name = name;
29                 this.taps = [];
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;
37                 this._x = undefined;
38
39                 this.compile = this.compile;
40                 this.tap = this.tap;
41                 this.tapAsync = this.tapAsync;
42                 this.tapPromise = this.tapPromise;
43         }
44
45         compile(options) {
46                 throw new Error("Abstract: should be overridden");
47         }
48
49         _createCall(type) {
50                 return this.compile({
51                         taps: this.taps,
52                         interceptors: this.interceptors,
53                         args: this._args,
54                         type: type
55                 });
56         }
57
58         _tap(type, options, fn) {
59                 if (typeof options === "string") {
60                         options = {
61                                 name: options.trim()
62                         };
63                 } else if (typeof options !== "object" || options === null) {
64                         throw new Error("Invalid tap options");
65                 }
66                 if (typeof options.name !== "string" || options.name === "") {
67                         throw new Error("Missing name for tap");
68                 }
69                 if (typeof options.context !== "undefined") {
70                         deprecateContext();
71                 }
72                 options = Object.assign({ type, fn }, options);
73                 options = this._runRegisterInterceptors(options);
74                 this._insert(options);
75         }
76
77         tap(options, fn) {
78                 this._tap("sync", options, fn);
79         }
80
81         tapAsync(options, fn) {
82                 this._tap("async", options, fn);
83         }
84
85         tapPromise(options, fn) {
86                 this._tap("promise", options, fn);
87         }
88
89         _runRegisterInterceptors(options) {
90                 for (const interceptor of this.interceptors) {
91                         if (interceptor.register) {
92                                 const newOptions = interceptor.register(options);
93                                 if (newOptions !== undefined) {
94                                         options = newOptions;
95                                 }
96                         }
97                 }
98                 return options;
99         }
100
101         withOptions(options) {
102                 const mergeOptions = opt =>
103                         Object.assign({}, options, typeof opt === "string" ? { name: opt } : opt);
104
105                 return {
106                         name: this.name,
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))
113                 };
114         }
115
116         isUsed() {
117                 return this.taps.length > 0 || this.interceptors.length > 0;
118         }
119
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]);
126                         }
127                 }
128         }
129
130         _resetCompilation() {
131                 this.call = this._call;
132                 this.callAsync = this._callAsync;
133                 this.promise = this._promise;
134         }
135
136         _insert(item) {
137                 this._resetCompilation();
138                 let before;
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);
143                 }
144                 let stage = 0;
145                 if (typeof item.stage === "number") {
146                         stage = item.stage;
147                 }
148                 let i = this.taps.length;
149                 while (i > 0) {
150                         i--;
151                         const x = this.taps[i];
152                         this.taps[i + 1] = x;
153                         const xStage = x.stage || 0;
154                         if (before) {
155                                 if (before.has(x.name)) {
156                                         before.delete(x.name);
157                                         continue;
158                                 }
159                                 if (before.size > 0) {
160                                         continue;
161                                 }
162                         }
163                         if (xStage > stage) {
164                                 continue;
165                         }
166                         i++;
167                         break;
168                 }
169                 this.taps[i] = item;
170         }
171 }
172
173 Object.setPrototypeOf(Hook.prototype, null);
174
175 module.exports = Hook;