GeezerVison is showing github.com — vm: unify host-defined option generation in vm.compileFunction · nodejs/node@56bbc30
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/internal/vm.js +24-1Lines changed: 24 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
| 2 | 2 |
| 3 | 3 | const { | 4 | 4 | ArrayPrototypeForEach, | | 5 | + Symbol, | 5 | 6 | } = primordials; | 6 | 7 |
| 7 | 8 | const { | 8 | 9 | compileFunction, | 9 | 10 | isContext: _isContext, | 10 | 11 | } = internalBinding('contextify'); | | 12 | +const { | | 13 | + default_host_defined_options, | | 14 | +} = internalBinding('symbols'); | 11 | 15 | const { | 12 | 16 | validateArray, | 13 | 17 | validateBoolean, | @@ -30,12 +34,27 @@ function isContext(object) { | 30 | 34 | return _isContext(object); | 31 | 35 | } | 32 | 36 |
| | 37 | +function getHostDefinedOptionId(importModuleDynamically, filename) { | | 38 | + if (importModuleDynamically !== undefined) { | | 39 | + // Check that it's either undefined or a function before we pass | | 40 | + // it into the native constructor. | | 41 | + validateFunction(importModuleDynamically, | | 42 | + 'options.importModuleDynamically'); | | 43 | + } | | 44 | + if (importModuleDynamically === undefined) { | | 45 | + // We need a default host defined options that are the same for all | | 46 | + // scripts not needing custom module callbacks so that the isolate | | 47 | + // compilation cache can be hit. | | 48 | + return default_host_defined_options; | | 49 | + } | | 50 | + return Symbol(filename); | | 51 | +} | | 52 | + | 33 | 53 | function internalCompileFunction(code, params, options) { | 34 | 54 | validateString(code, 'code'); | 35 | 55 | if (params !== undefined) { | 36 | 56 | validateStringArray(params, 'params'); | 37 | 57 | } | 38 | | - | 39 | 58 | const { | 40 | 59 | filename = '', | 41 | 60 | columnOffset = 0, | @@ -72,6 +91,8 @@ function internalCompileFunction(code, params, options) { | 72 | 91 | validateObject(extension, name, kValidateObjectAllowNullable); | 73 | 92 | }); | 74 | 93 |
| | 94 | + const hostDefinedOptionId = | | 95 | + getHostDefinedOptionId(importModuleDynamically, filename); | 75 | 96 | const result = compileFunction( | 76 | 97 | code, | 77 | 98 | filename, | @@ -82,6 +103,7 @@ function internalCompileFunction(code, params, options) { | 82 | 103 | parsingContext, | 83 | 104 | contextExtensions, | 84 | 105 | params, | | 106 | + hostDefinedOptionId, | 85 | 107 | ); | 86 | 108 |
| 87 | 109 | if (produceCachedData) { | @@ -113,6 +135,7 @@ function internalCompileFunction(code, params, options) { | 113 | 135 | } | 114 | 136 |
| 115 | 137 | module.exports = { | | 138 | + getHostDefinedOptionId, | 116 | 139 | internalCompileFunction, | 117 | 140 | isContext, | 118 | 141 | }; |
Collapse file Copy file name to clipboardExpand all lines: lib/vm.js +4-8Lines changed: 4 additions & 8 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -41,7 +41,6 @@ const { | 41 | 41 | const { | 42 | 42 | validateBoolean, | 43 | 43 | validateBuffer, | 44 | | - validateFunction, | 45 | 44 | validateInt32, | 46 | 45 | validateObject, | 47 | 46 | validateOneOf, | @@ -54,6 +53,7 @@ const { | 54 | 53 | kVmBreakFirstLineSymbol, | 55 | 54 | } = require('internal/util'); | 56 | 55 | const { | | 56 | + getHostDefinedOptionId, | 57 | 57 | internalCompileFunction, | 58 | 58 | isContext, | 59 | 59 | } = require('internal/vm'); | @@ -86,12 +86,8 @@ class Script extends ContextifyScript { | 86 | 86 | } | 87 | 87 | validateBoolean(produceCachedData, 'options.produceCachedData'); | 88 | 88 |
| 89 | | - if (importModuleDynamically !== undefined) { | 90 | | - // Check that it's either undefined or a function before we pass | 91 | | - // it into the native constructor. | 92 | | - validateFunction(importModuleDynamically, | 93 | | - 'options.importModuleDynamically'); | 94 | | - } | | 89 | + const hostDefinedOptionId = | | 90 | + getHostDefinedOptionId(importModuleDynamically, filename); | 95 | 91 | // Calling `ReThrow()` on a native TryCatch does not generate a new | 96 | 92 | // abort-on-uncaught-exception check. A dummy try/catch in JS land | 97 | 93 | // protects against that. | @@ -103,7 +99,7 @@ class Script extends ContextifyScript { | 103 | 99 | cachedData, | 104 | 100 | produceCachedData, | 105 | 101 | parsingContext, | 106 | | - importModuleDynamically !== undefined); | | 102 | + hostDefinedOptionId); | 107 | 103 | } catch (e) { | 108 | 104 | throw e; /* node-do-not-add-exception-line */ | 109 | 105 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/node_contextify.cc +8-12Lines changed: 8 additions & 12 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -771,11 +771,11 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) { | 771 | 771 | bool produce_cached_data = false; | 772 | 772 | Local<Context> parsing_context = context; | 773 | 773 |
| 774 | | - bool needs_custom_host_defined_options = false; | | 774 | + Local<Symbol> id_symbol; | 775 | 775 | if (argc > 2) { | 776 | 776 | // new ContextifyScript(code, filename, lineOffset, columnOffset, | 777 | 777 | // cachedData, produceCachedData, parsingContext, | 778 | | - // needsCustomHostDefinedOptions) | | 778 | + // hostDefinedOptionId) | 779 | 779 | CHECK_EQ(argc, 8); | 780 | 780 | CHECK(args[2]->IsNumber()); | 781 | 781 | line_offset = args[2].As<Int32>()->Value(); | @@ -795,9 +795,8 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) { | 795 | 795 | CHECK_NOT_NULL(sandbox); | 796 | 796 | parsing_context = sandbox->context(); | 797 | 797 | } | 798 | | - if (args[7]->IsTrue()) { | 799 | | - needs_custom_host_defined_options = true; | 800 | | - } | | 798 | + CHECK(args[7]->IsSymbol()); | | 799 | + id_symbol = args[7].As<Symbol>(); | 801 | 800 | } | 802 | 801 |
| 803 | 802 | ContextifyScript* contextify_script = | @@ -821,12 +820,6 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) { | 821 | 820 |
| 822 | 821 | Local<PrimitiveArray> host_defined_options = | 823 | 822 | PrimitiveArray::New(isolate, loader::HostDefinedOptions::kLength); | 824 | | - // We need a default host defined options that's the same for all scripts | 825 | | - // not needing custom module callbacks for so that the isolate compilation | 826 | | - // cache can be hit. | 827 | | - Local<Symbol> id_symbol = needs_custom_host_defined_options | 828 | | - ? Symbol::New(isolate, filename) | 829 | | - : env->default_host_defined_options(); | 830 | 823 | host_defined_options->Set( | 831 | 824 | isolate, loader::HostDefinedOptions::kID, id_symbol); | 832 | 825 |
| @@ -1200,6 +1193,10 @@ void ContextifyContext::CompileFunction( | 1200 | 1193 | params_buf = args[8].As<Array>(); | 1201 | 1194 | } | 1202 | 1195 |
| | 1196 | + // Argument 10: host-defined option symbol | | 1197 | + CHECK(args[9]->IsSymbol()); | | 1198 | + Local<Symbol> id_symbol = args[9].As<Symbol>(); | | 1199 | + | 1203 | 1200 | // Read cache from cached data buffer | 1204 | 1201 | ScriptCompiler::CachedData* cached_data = nullptr; | 1205 | 1202 | if (!cached_data_buf.IsEmpty()) { | @@ -1211,7 +1208,6 @@ void ContextifyContext::CompileFunction( | 1211 | 1208 | // Set host_defined_options | 1212 | 1209 | Local<PrimitiveArray> host_defined_options = | 1213 | 1210 | PrimitiveArray::New(isolate, loader::HostDefinedOptions::kLength); | 1214 | | - Local<Symbol> id_symbol = Symbol::New(isolate, filename); | 1215 | 1211 | host_defined_options->Set( | 1216 | 1212 | isolate, loader::HostDefinedOptions::kID, id_symbol); | 1217 | 1213 |
| |
Collapse file Copy file name to clipboard +10-3Lines changed: 10 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | 'use strict'; | 2 | 2 |
| 3 | | -require('../common'); | 4 | | -const { Script } = require('vm'); | | 3 | +const common = require('../common'); | | 4 | +const { Script, compileFunction } = require('vm'); | 5 | 5 | const assert = require('assert'); | 6 | 6 |
| 7 | 7 | assert.rejects(async () => { | @@ -10,4 +10,11 @@ assert.rejects(async () => { | 10 | 10 | await imported; | 11 | 11 | }, { | 12 | 12 | code: 'ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING' | 13 | | -}); | | 13 | +}).then(common.mustCall()); | | 14 | + | | 15 | +assert.rejects(async () => { | | 16 | + const imported = compileFunction('return import("fs")')(); | | 17 | + await imported; | | 18 | +}, { | | 19 | + code: 'ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING' | | 20 | +}).then(common.mustCall()); |
|