| 'use strict'; |
| |
| const { |
| ReflectApply, |
| Symbol, |
| } = primordials; |
| |
| const { |
| ContextifyScript, |
| compileFunction, |
| isContext: _isContext, |
| } = internalBinding('contextify'); |
| const { |
| runInContext, |
| } = ContextifyScript.prototype; |
| const { |
| vm_dynamic_import_default_internal, |
| vm_dynamic_import_main_context_default, |
| vm_dynamic_import_no_callback, |
| vm_dynamic_import_missing_flag, |
| } = internalBinding('symbols'); |
| const { |
| validateFunction, |
| validateObject, |
| kValidateObjectAllowArray, |
| } = require('internal/validators'); |
| |
| const { |
| getOptionValue, |
| } = require('internal/options'); |
| |
| function isContext(object) { |
| validateObject(object, 'object', kValidateObjectAllowArray); |
| |
| return _isContext(object); |
| } |
| |
| function getHostDefinedOptionId(importModuleDynamically, hint) { |
| if (importModuleDynamically === vm_dynamic_import_main_context_default || |
| importModuleDynamically === vm_dynamic_import_default_internal) { |
| return importModuleDynamically; |
| } |
| |
| if (importModuleDynamically !== undefined) { |
| // Check that it's either undefined or a function before we pass |
| // it into the native constructor. |
| validateFunction(importModuleDynamically, |
| 'options.importModuleDynamically'); |
| } |
| if (importModuleDynamically === undefined) { |
| // We need a default host defined options that are the same for all |
| // scripts not needing custom module callbacks so that the isolate |
| // compilation cache can be hit. |
| return vm_dynamic_import_no_callback; |
| } |
| // We should've thrown here immediately when we introduced |
| // --experimental-vm-modules and importModuleDynamically, but since |
| // users are already using this callback to throw a similar error, |
| // we also defer the error to the time when an actual import() is called |
| // to avoid breaking them. To ensure that the isolate compilation |
| // cache can still be hit, use a constant sentinel symbol here. |
| if (!getOptionValue('--experimental-vm-modules')) { |
| return vm_dynamic_import_missing_flag; |
| } |
| |
| return Symbol(hint); |
| } |
| |
| function registerImportModuleDynamically(referrer, importModuleDynamically) { |
| // If it's undefined or certain known symbol, there's no customization so |
| // no need to register anything. |
| if (importModuleDynamically === undefined || |
| importModuleDynamically === vm_dynamic_import_main_context_default || |
| importModuleDynamically === vm_dynamic_import_default_internal) { |
| return; |
| } |
| const { importModuleDynamicallyWrap } = require('internal/vm/module'); |
| const { registerModule } = require('internal/modules/esm/utils'); |
| registerModule(referrer, { |
| __proto__: null, |
| importModuleDynamically: |
| importModuleDynamicallyWrap(importModuleDynamically), |
| }); |
| } |
| |
| function internalCompileFunction( |
| code, filename, lineOffset, columnOffset, |
| cachedData, produceCachedData, parsingContext, contextExtensions, |
| params, hostDefinedOptionId, importModuleDynamically) { |
| const result = compileFunction( |
| code, |
| filename, |
| lineOffset, |
| columnOffset, |
| cachedData, |
| produceCachedData, |
| parsingContext, |
| contextExtensions, |
| params, |
| hostDefinedOptionId, |
| ); |
| |
| if (produceCachedData) { |
| result.function.cachedDataProduced = result.cachedDataProduced; |
| } |
| |
| if (result.cachedData) { |
| result.function.cachedData = result.cachedData; |
| } |
| |
| if (typeof result.cachedDataRejected === 'boolean') { |
| result.function.cachedDataRejected = result.cachedDataRejected; |
| } |
| |
| registerImportModuleDynamically(result.function, importModuleDynamically); |
| |
| return result; |
| } |
| |
| function makeContextifyScript(code, |
| filename, |
| lineOffset, |
| columnOffset, |
| cachedData, |
| produceCachedData, |
| parsingContext, |
| hostDefinedOptionId, |
| importModuleDynamically) { |
| let script; |
| // Calling `ReThrow()` on a native TryCatch does not generate a new |
| // abort-on-uncaught-exception check. A dummy try/catch in JS land |
| // protects against that. |
| try { // eslint-disable-line no-useless-catch |
| script = new ContextifyScript(code, |
| filename, |
| lineOffset, |
| columnOffset, |
| cachedData, |
| produceCachedData, |
| parsingContext, |
| hostDefinedOptionId); |
| } catch (e) { |
| throw e; /* node-do-not-add-exception-line */ |
| } |
| |
| registerImportModuleDynamically(script, importModuleDynamically); |
| return script; |
| } |
| |
| // Internal version of vm.Script.prototype.runInThisContext() which skips |
| // argument validation. |
| function runScriptInThisContext(script, displayErrors, breakOnFirstLine) { |
| return ReflectApply( |
| runInContext, |
| script, |
| [ |
| null, // sandbox - use current context |
| -1, // timeout |
| displayErrors, // displayErrors |
| false, // breakOnSigint |
| breakOnFirstLine, // breakOnFirstLine |
| ], |
| ); |
| } |
| |
| module.exports = { |
| getHostDefinedOptionId, |
| internalCompileFunction, |
| isContext, |
| makeContextifyScript, |
| registerImportModuleDynamically, |
| runScriptInThisContext, |
| }; |