1'use strict'; 2 3const { 4 ReflectApply, 5 Symbol, 6} = primordials; 7 8const { 9 ContextifyScript, 10 compileFunction, 11 isContext: _isContext, 12} = internalBinding('contextify'); 13const { 14 runInContext, 15} = ContextifyScript.prototype; 16const { 17 default_host_defined_options, 18 vm_dynamic_import_missing_flag, 19} = internalBinding('symbols'); 20const { 21 validateFunction, 22 validateObject, 23} = require('internal/validators'); 24 25const { 26 getOptionValue, 27} = require('internal/options'); 28 29 30function isContext(object) { 31 validateObject(object, 'object', { __proto__: null, allowArray: true }); 32 33 return _isContext(object); 34} 35 36function getHostDefinedOptionId(importModuleDynamically, filename) { 37 if (importModuleDynamically !== undefined) { 38 // Check that it's either undefined or a function before we pass 39 // it into the native constructor. 40 validateFunction(importModuleDynamically, 41 'options.importModuleDynamically'); 42 } 43 if (importModuleDynamically === undefined) { 44 // We need a default host defined options that are the same for all 45 // scripts not needing custom module callbacks so that the isolate 46 // compilation cache can be hit. 47 return default_host_defined_options; 48 } 49 // We should've thrown here immediately when we introduced 50 // --experimental-vm-modules and importModuleDynamically, but since 51 // users are already using this callback to throw a similar error, 52 // we also defer the error to the time when an actual import() is called 53 // to avoid breaking them. To ensure that the isolate compilation 54 // cache can still be hit, use a constant sentinel symbol here. 55 if (!getOptionValue('--experimental-vm-modules')) { 56 return vm_dynamic_import_missing_flag; 57 } 58 59 return Symbol(filename); 60} 61 62function registerImportModuleDynamically(referrer, importModuleDynamically) { 63 const { importModuleDynamicallyWrap } = require('internal/vm/module'); 64 const { registerModule } = require('internal/modules/esm/utils'); 65 registerModule(referrer, { 66 __proto__: null, 67 importModuleDynamically: 68 importModuleDynamicallyWrap(importModuleDynamically), 69 }); 70} 71 72function internalCompileFunction( 73 code, filename, lineOffset, columnOffset, 74 cachedData, produceCachedData, parsingContext, contextExtensions, 75 params, hostDefinedOptionId, importModuleDynamically) { 76 const result = compileFunction( 77 code, 78 filename, 79 lineOffset, 80 columnOffset, 81 cachedData, 82 produceCachedData, 83 parsingContext, 84 contextExtensions, 85 params, 86 hostDefinedOptionId, 87 ); 88 89 if (produceCachedData) { 90 result.function.cachedDataProduced = result.cachedDataProduced; 91 } 92 93 if (result.cachedData) { 94 result.function.cachedData = result.cachedData; 95 } 96 97 if (typeof result.cachedDataRejected === 'boolean') { 98 result.function.cachedDataRejected = result.cachedDataRejected; 99 } 100 101 if (importModuleDynamically !== undefined) { 102 registerImportModuleDynamically(result.function, importModuleDynamically); 103 } 104 105 return result; 106} 107 108function makeContextifyScript(code, 109 filename, 110 lineOffset, 111 columnOffset, 112 cachedData, 113 produceCachedData, 114 parsingContext, 115 hostDefinedOptionId, 116 importModuleDynamically) { 117 let script; 118 // Calling `ReThrow()` on a native TryCatch does not generate a new 119 // abort-on-uncaught-exception check. A dummy try/catch in JS land 120 // protects against that. 121 try { // eslint-disable-line no-useless-catch 122 script = new ContextifyScript(code, 123 filename, 124 lineOffset, 125 columnOffset, 126 cachedData, 127 produceCachedData, 128 parsingContext, 129 hostDefinedOptionId); 130 } catch (e) { 131 throw e; /* node-do-not-add-exception-line */ 132 } 133 134 if (importModuleDynamically !== undefined) { 135 registerImportModuleDynamically(script, importModuleDynamically); 136 } 137 return script; 138} 139 140// Internal version of vm.Script.prototype.runInThisContext() which skips 141// argument validation. 142function runScriptInThisContext(script, displayErrors, breakOnFirstLine) { 143 return ReflectApply( 144 runInContext, 145 script, 146 [ 147 null, // sandbox - use current context 148 -1, // timeout 149 displayErrors, // displayErrors 150 false, // breakOnSigint 151 breakOnFirstLine, // breakOnFirstLine 152 ], 153 ); 154} 155 156module.exports = { 157 getHostDefinedOptionId, 158 internalCompileFunction, 159 isContext, 160 makeContextifyScript, 161 registerImportModuleDynamically, 162 runScriptInThisContext, 163}; 164