@squiz/render-runtime-lib 1.2.1-alpha.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/lib/component-runner/component-runner.spec.d.ts +1 -0
- package/lib/component-runner/index.d.ts +19 -0
- package/lib/component-runner/worker/WorkerPool.d.ts +50 -0
- package/lib/component-runner/worker/getRuntimeModules.d.ts +1 -0
- package/lib/component-runner/worker/worker-root.d.ts +1 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.js +63783 -0
- package/lib/index.js.map +7 -0
- package/lib/render-runtime-lib.spec.d.ts +1 -0
- package/lib/test/helpers/fixtures.d.ts +6 -0
- package/lib/test/helpers/stack.d.ts +2 -0
- package/lib/utils/convertFunctionStaticFilesToFqdn.d.ts +1 -0
- package/lib/utils/log.d.ts +3 -0
- package/lib/webserver/app.d.ts +2 -0
- package/lib/webserver/controllers/core.d.ts +3 -0
- package/lib/webserver/controllers/definition.d.ts +3 -0
- package/lib/webserver/controllers/definition.spec.d.ts +1 -0
- package/lib/webserver/controllers/index.d.ts +4 -0
- package/lib/webserver/controllers/render.d.ts +3 -0
- package/lib/webserver/controllers/render.spec.d.ts +1 -0
- package/lib/webserver/controllers/static.d.ts +3 -0
- package/lib/webserver/controllers/static.spec.d.ts +1 -0
- package/lib/webserver/index.d.ts +15 -0
- package/lib/worker/bridge.js +1000 -0
- package/lib/worker/compiler.js +87 -0
- package/lib/worker/events.js +977 -0
- package/lib/worker/nodevm.js +503 -0
- package/lib/worker/resolver-compat.js +342 -0
- package/lib/worker/resolver.js +882 -0
- package/lib/worker/script.js +388 -0
- package/lib/worker/setup-node-sandbox.js +464 -0
- package/lib/worker/setup-sandbox.js +453 -0
- package/lib/worker/transformer.js +176 -0
- package/lib/worker/vm.js +539 -0
- package/lib/worker/worker-root.js +40146 -0
- package/lib/worker/worker-root.js.map +7 -0
- package/package.json +55 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Translate the old options to the new Resolver functionality.
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const pa = require('path');
|
|
7
|
+
const nmod = require('module');
|
|
8
|
+
const {EventEmitter} = require('events');
|
|
9
|
+
const util = require('util');
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
Resolver,
|
|
13
|
+
DefaultResolver
|
|
14
|
+
} = require('./resolver');
|
|
15
|
+
const {VMScript} = require('./script');
|
|
16
|
+
const {VM} = require('./vm');
|
|
17
|
+
const {VMError} = require('./bridge');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Require wrapper to be able to annotate require with webpackIgnore.
|
|
21
|
+
*
|
|
22
|
+
* @private
|
|
23
|
+
* @param {string} moduleName - Name of module to load.
|
|
24
|
+
* @return {*} Module exports.
|
|
25
|
+
*/
|
|
26
|
+
function defaultRequire(moduleName) {
|
|
27
|
+
// Set module.parser.javascript.commonjsMagicComments=true in your webpack config.
|
|
28
|
+
// eslint-disable-next-line global-require
|
|
29
|
+
return require(/* webpackIgnore: true */ moduleName);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
|
|
33
|
+
function escapeRegExp(string) {
|
|
34
|
+
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function makeExternalMatcherRegex(obj) {
|
|
38
|
+
return escapeRegExp(obj).replace(/\\\\|\//g, '[\\\\/]')
|
|
39
|
+
.replace(/\\\*\\\*/g, '.*').replace(/\\\*/g, '[^\\\\/]*').replace(/\\\?/g, '[^\\\\/]');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function makeExternalMatcher(obj) {
|
|
43
|
+
const regexString = makeExternalMatcherRegex(obj);
|
|
44
|
+
return new RegExp(`[\\\\/]node_modules[\\\\/]${regexString}(?:[\\\\/](?!(?:.*[\\\\/])?node_modules[\\\\/]).*)?$`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class LegacyResolver extends DefaultResolver {
|
|
48
|
+
|
|
49
|
+
constructor(builtinModules, checkPath, globalPaths, pathContext, customResolver, hostRequire, compiler, externals, allowTransitive) {
|
|
50
|
+
super(builtinModules, checkPath, globalPaths, pathContext, customResolver, hostRequire, compiler);
|
|
51
|
+
this.externals = externals;
|
|
52
|
+
this.currMod = undefined;
|
|
53
|
+
this.trustedMods = new WeakMap();
|
|
54
|
+
this.allowTransitive = allowTransitive;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
isPathAllowed(path) {
|
|
58
|
+
return this.isPathAllowedForModule(path, this.currMod);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
isPathAllowedForModule(path, mod) {
|
|
62
|
+
if (!super.isPathAllowed(path)) return false;
|
|
63
|
+
if (mod) {
|
|
64
|
+
if (mod.allowTransitive) return true;
|
|
65
|
+
if (path.startsWith(mod.path)) {
|
|
66
|
+
const rem = path.slice(mod.path.length);
|
|
67
|
+
if (!/(?:^|[\\\\/])node_modules(?:$|[\\\\/])/.test(rem)) return true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return this.externals.some(regex => regex.test(path));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
registerModule(mod, filename, path, parent, direct) {
|
|
74
|
+
const trustedParent = this.trustedMods.get(parent);
|
|
75
|
+
this.trustedMods.set(mod, {
|
|
76
|
+
filename,
|
|
77
|
+
path,
|
|
78
|
+
paths: this.genLookupPaths(path),
|
|
79
|
+
allowTransitive: this.allowTransitive &&
|
|
80
|
+
((direct && trustedParent && trustedParent.allowTransitive) || this.externals.some(regex => regex.test(filename)))
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
resolveFull(mod, x, options, ext, direct) {
|
|
85
|
+
this.currMod = undefined;
|
|
86
|
+
if (!direct) return super.resolveFull(mod, x, options, ext, false);
|
|
87
|
+
const trustedMod = this.trustedMods.get(mod);
|
|
88
|
+
if (!trustedMod || mod.path !== trustedMod.path) return super.resolveFull(mod, x, options, ext, false);
|
|
89
|
+
const paths = [...mod.paths];
|
|
90
|
+
if (paths.length === trustedMod.length) {
|
|
91
|
+
for (let i = 0; i < paths.length; i++) {
|
|
92
|
+
if (paths[i] !== trustedMod.paths[i]) {
|
|
93
|
+
return super.resolveFull(mod, x, options, ext, false);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const extCopy = Object.assign({__proto__: null}, ext);
|
|
98
|
+
try {
|
|
99
|
+
this.currMod = trustedMod;
|
|
100
|
+
return super.resolveFull(trustedMod, x, undefined, extCopy, true);
|
|
101
|
+
} finally {
|
|
102
|
+
this.currMod = undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
checkAccess(mod, filename) {
|
|
107
|
+
const trustedMod = this.trustedMods.get(mod);
|
|
108
|
+
if ((!trustedMod || trustedMod.filename !== filename) && !this.isPathAllowedForModule(filename, undefined)) {
|
|
109
|
+
throw new VMError(`Module '${filename}' is not allowed to be required. The path is outside the border!`, 'EDENIED');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
loadJS(vm, mod, filename) {
|
|
114
|
+
filename = this.pathResolve(filename);
|
|
115
|
+
this.checkAccess(mod, filename);
|
|
116
|
+
if (this.pathContext(filename, 'js') === 'sandbox') {
|
|
117
|
+
const trustedMod = this.trustedMods.get(mod);
|
|
118
|
+
const script = this.readScript(filename);
|
|
119
|
+
vm.run(script, {filename, strict: true, module: mod, wrapper: 'none', dirname: trustedMod ? trustedMod.path : mod.path});
|
|
120
|
+
} else {
|
|
121
|
+
const m = this.hostRequire(filename);
|
|
122
|
+
mod.exports = vm.readonly(m);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function defaultBuiltinLoader(resolver, vm, id) {
|
|
129
|
+
const mod = resolver.hostRequire(id);
|
|
130
|
+
return vm.readonly(mod);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const eventsModules = new WeakMap();
|
|
134
|
+
|
|
135
|
+
function defaultBuiltinLoaderEvents(resolver, vm, id) {
|
|
136
|
+
return eventsModules.get(vm);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let cacheBufferScript;
|
|
140
|
+
|
|
141
|
+
function defaultBuiltinLoaderBuffer(resolver, vm, id) {
|
|
142
|
+
if (!cacheBufferScript) {
|
|
143
|
+
cacheBufferScript = new VMScript('return buffer=>({Buffer: buffer});', {__proto__: null, filename: 'buffer.js'});
|
|
144
|
+
}
|
|
145
|
+
const makeBuffer = vm.run(cacheBufferScript, {__proto__: null, strict: true, wrapper: 'none'});
|
|
146
|
+
return makeBuffer(Buffer);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
let cacheUtilScript;
|
|
150
|
+
|
|
151
|
+
function defaultBuiltinLoaderUtil(resolver, vm, id) {
|
|
152
|
+
if (!cacheUtilScript) {
|
|
153
|
+
cacheUtilScript = new VMScript(`return function inherits(ctor, superCtor) {
|
|
154
|
+
ctor.super_ = superCtor;
|
|
155
|
+
Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
|
|
156
|
+
}`, {__proto__: null, filename: 'util.js'});
|
|
157
|
+
}
|
|
158
|
+
const inherits = vm.run(cacheUtilScript, {__proto__: null, strict: true, wrapper: 'none'});
|
|
159
|
+
const copy = Object.assign({}, util);
|
|
160
|
+
copy.inherits = inherits;
|
|
161
|
+
return vm.readonly(copy);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const BUILTIN_MODULES = (nmod.builtinModules || Object.getOwnPropertyNames(process.binding('natives'))).filter(s=>!s.startsWith('internal/'));
|
|
165
|
+
|
|
166
|
+
let EventEmitterReferencingAsyncResourceClass = null;
|
|
167
|
+
if (EventEmitter.EventEmitterAsyncResource) {
|
|
168
|
+
// eslint-disable-next-line global-require
|
|
169
|
+
const {AsyncResource} = require('async_hooks');
|
|
170
|
+
const kEventEmitter = Symbol('kEventEmitter');
|
|
171
|
+
class EventEmitterReferencingAsyncResource extends AsyncResource {
|
|
172
|
+
constructor(ee, type, options) {
|
|
173
|
+
super(type, options);
|
|
174
|
+
this[kEventEmitter] = ee;
|
|
175
|
+
}
|
|
176
|
+
get eventEmitter() {
|
|
177
|
+
return this[kEventEmitter];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
EventEmitterReferencingAsyncResourceClass = EventEmitterReferencingAsyncResource;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
let cacheEventsScript;
|
|
184
|
+
|
|
185
|
+
const SPECIAL_MODULES = {
|
|
186
|
+
events(vm) {
|
|
187
|
+
if (!cacheEventsScript) {
|
|
188
|
+
const eventsSource = fs.readFileSync(`${__dirname}/events.js`, 'utf8');
|
|
189
|
+
cacheEventsScript = new VMScript(`(function (fromhost) { const module = {}; module.exports={};{ ${eventsSource}
|
|
190
|
+
} return module.exports;})`, {filename: 'events.js'});
|
|
191
|
+
}
|
|
192
|
+
const closure = VM.prototype.run.call(vm, cacheEventsScript);
|
|
193
|
+
const eventsInstance = closure(vm.readonly({
|
|
194
|
+
kErrorMonitor: EventEmitter.errorMonitor,
|
|
195
|
+
once: EventEmitter.once,
|
|
196
|
+
on: EventEmitter.on,
|
|
197
|
+
getEventListeners: EventEmitter.getEventListeners,
|
|
198
|
+
EventEmitterReferencingAsyncResource: EventEmitterReferencingAsyncResourceClass
|
|
199
|
+
}));
|
|
200
|
+
eventsModules.set(vm, eventsInstance);
|
|
201
|
+
vm._addProtoMapping(EventEmitter.prototype, eventsInstance.EventEmitter.prototype);
|
|
202
|
+
return defaultBuiltinLoaderEvents;
|
|
203
|
+
},
|
|
204
|
+
buffer(vm) {
|
|
205
|
+
return defaultBuiltinLoaderBuffer;
|
|
206
|
+
},
|
|
207
|
+
util(vm) {
|
|
208
|
+
return defaultBuiltinLoaderUtil;
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
function addDefaultBuiltin(builtins, key, vm) {
|
|
213
|
+
if (builtins[key]) return;
|
|
214
|
+
const special = SPECIAL_MODULES[key];
|
|
215
|
+
builtins[key] = special ? special(vm) : defaultBuiltinLoader;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
function genBuiltinsFromOptions(vm, builtinOpt, mockOpt, override) {
|
|
220
|
+
const builtins = {__proto__: null};
|
|
221
|
+
if (mockOpt) {
|
|
222
|
+
const keys = Object.getOwnPropertyNames(mockOpt);
|
|
223
|
+
for (let i = 0; i < keys.length; i++) {
|
|
224
|
+
const key = keys[i];
|
|
225
|
+
builtins[key] = (resolver, tvm, id) => tvm.readonly(mockOpt[key]);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (override) {
|
|
229
|
+
const keys = Object.getOwnPropertyNames(override);
|
|
230
|
+
for (let i = 0; i < keys.length; i++) {
|
|
231
|
+
const key = keys[i];
|
|
232
|
+
builtins[key] = override[key];
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (Array.isArray(builtinOpt)) {
|
|
236
|
+
const def = builtinOpt.indexOf('*') >= 0;
|
|
237
|
+
if (def) {
|
|
238
|
+
for (let i = 0; i < BUILTIN_MODULES.length; i++) {
|
|
239
|
+
const name = BUILTIN_MODULES[i];
|
|
240
|
+
if (builtinOpt.indexOf(`-${name}`) === -1) {
|
|
241
|
+
addDefaultBuiltin(builtins, name, vm);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
for (let i = 0; i < BUILTIN_MODULES.length; i++) {
|
|
246
|
+
const name = BUILTIN_MODULES[i];
|
|
247
|
+
if (builtinOpt.indexOf(name) !== -1) {
|
|
248
|
+
addDefaultBuiltin(builtins, name, vm);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
} else if (builtinOpt) {
|
|
253
|
+
for (let i = 0; i < BUILTIN_MODULES.length; i++) {
|
|
254
|
+
const name = BUILTIN_MODULES[i];
|
|
255
|
+
if (builtinOpt[name]) {
|
|
256
|
+
addDefaultBuiltin(builtins, name, vm);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return builtins;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function defaultCustomResolver() {
|
|
264
|
+
return undefined;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const DENY_RESOLVER = new Resolver({__proto__: null}, [], id => {
|
|
268
|
+
throw new VMError(`Access denied to require '${id}'`, 'EDENIED');
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
function resolverFromOptions(vm, options, override, compiler) {
|
|
272
|
+
if (!options) {
|
|
273
|
+
if (!override) return DENY_RESOLVER;
|
|
274
|
+
const builtins = genBuiltinsFromOptions(vm, undefined, undefined, override);
|
|
275
|
+
return new Resolver(builtins, [], defaultRequire);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const {
|
|
279
|
+
builtin: builtinOpt,
|
|
280
|
+
mock: mockOpt,
|
|
281
|
+
external: externalOpt,
|
|
282
|
+
root: rootPaths,
|
|
283
|
+
resolve: customResolver,
|
|
284
|
+
customRequire: hostRequire = defaultRequire,
|
|
285
|
+
context = 'host'
|
|
286
|
+
} = options;
|
|
287
|
+
|
|
288
|
+
const builtins = genBuiltinsFromOptions(vm, builtinOpt, mockOpt, override);
|
|
289
|
+
|
|
290
|
+
if (!externalOpt) return new Resolver(builtins, [], hostRequire);
|
|
291
|
+
|
|
292
|
+
let checkPath;
|
|
293
|
+
if (rootPaths) {
|
|
294
|
+
const checkedRootPaths = (Array.isArray(rootPaths) ? rootPaths : [rootPaths]).map(f => pa.resolve(f));
|
|
295
|
+
checkPath = (filename) => {
|
|
296
|
+
return checkedRootPaths.some(path => {
|
|
297
|
+
if (!filename.startsWith(path)) return false;
|
|
298
|
+
const len = path.length;
|
|
299
|
+
if (filename.length === len || (len > 0 && path[len-1] === pa.sep)) return true;
|
|
300
|
+
const sep = filename[len];
|
|
301
|
+
return sep === '/' || sep === pa.sep;
|
|
302
|
+
});
|
|
303
|
+
};
|
|
304
|
+
} else {
|
|
305
|
+
checkPath = () => true;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
let newCustomResolver = defaultCustomResolver;
|
|
309
|
+
let externals = undefined;
|
|
310
|
+
let external = undefined;
|
|
311
|
+
if (customResolver) {
|
|
312
|
+
let externalCache;
|
|
313
|
+
newCustomResolver = (resolver, x, path, extList) => {
|
|
314
|
+
if (external && !(resolver.pathIsAbsolute(x) || resolver.pathIsRelative(x))) {
|
|
315
|
+
if (!externalCache) {
|
|
316
|
+
externalCache = external.map(ext => new RegExp(makeExternalMatcherRegex(ext)));
|
|
317
|
+
}
|
|
318
|
+
if (!externalCache.some(regex => regex.test(x))) return undefined;
|
|
319
|
+
}
|
|
320
|
+
const resolved = customResolver(x, path);
|
|
321
|
+
if (!resolved) return undefined;
|
|
322
|
+
if (externals) externals.push(new RegExp('^' + escapeRegExp(resolved)));
|
|
323
|
+
return resolver.loadAsFileOrDirecotry(resolved, extList);
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (typeof externalOpt !== 'object') {
|
|
328
|
+
return new DefaultResolver(builtins, checkPath, [], () => context, newCustomResolver, hostRequire, compiler);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
let transitive = false;
|
|
332
|
+
if (Array.isArray(externalOpt)) {
|
|
333
|
+
external = externalOpt;
|
|
334
|
+
} else {
|
|
335
|
+
external = externalOpt.modules;
|
|
336
|
+
transitive = context === 'sandbox' && externalOpt.transitive;
|
|
337
|
+
}
|
|
338
|
+
externals = external.map(makeExternalMatcher);
|
|
339
|
+
return new LegacyResolver(builtins, checkPath, [], () => context, newCustomResolver, hostRequire, compiler, externals, transitive);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
exports.resolverFromOptions = resolverFromOptions;
|