vm: unify host-defined option generation in vm.compileFunction

Set a default host-defined option for vm.compileFunction so that
it's consistent with vm.Script.

PR-URL: https://github.com/nodejs/node/pull/50137
Refs: https://github.com/nodejs/node/issues/35375
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
Joyee Cheung authored and Node.js GitHub Bot committed 2023-10-17 13:24:51 +00:00
1 parent badba8ceb6
commit f7cdac091a
4 files changed
+46 -24

No files matched your search

+24 -1
View File
@@ -2,12 +2,16 @@
const {
ArrayPrototypeForEach,
Symbol,
} = primordials;
const {
compileFunction,
isContext: _isContext,
} = internalBinding('contextify');
const {
default_host_defined_options,
} = internalBinding('symbols');
const {
validateArray,
validateBoolean,
@@ -30,12 +34,27 @@ function isContext(object) {
return _isContext(object);
}
function getHostDefinedOptionId(importModuleDynamically, filename) {
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 default_host_defined_options;
}
return Symbol(filename);
}
function internalCompileFunction(code, params, options) {
validateString(code, 'code');
if (params !== undefined) {
validateStringArray(params, 'params');
}
const {
filename = '',
columnOffset = 0,
@@ -72,6 +91,8 @@ function internalCompileFunction(code, params, options) {
validateObject(extension, name, kValidateObjectAllowNullable);
});
const hostDefinedOptionId =
getHostDefinedOptionId(importModuleDynamically, filename);
const result = compileFunction(
code,
filename,
@@ -82,6 +103,7 @@ function internalCompileFunction(code, params, options) {
parsingContext,
contextExtensions,
params,
hostDefinedOptionId,
);
if (produceCachedData) {
@@ -113,6 +135,7 @@ function internalCompileFunction(code, params, options) {
}
module.exports = {
getHostDefinedOptionId,
internalCompileFunction,
isContext,
};
+4 -8
View File
@@ -41,7 +41,6 @@ const {
const {
validateBoolean,
validateBuffer,
validateFunction,
validateInt32,
validateObject,
validateOneOf,
@@ -54,6 +53,7 @@ const {
kVmBreakFirstLineSymbol,
} = require('internal/util');
const {
getHostDefinedOptionId,
internalCompileFunction,
isContext,
} = require('internal/vm');
@@ -86,12 +86,8 @@ class Script extends ContextifyScript {
}
validateBoolean(produceCachedData, 'options.produceCachedData');
if (importModuleDynamically !== undefined) {
// Check that it's either undefined or a function before we pass
// it into the native constructor.
validateFunction(importModuleDynamically,
'options.importModuleDynamically');
}
const hostDefinedOptionId =
getHostDefinedOptionId(importModuleDynamically, filename);
// 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.
@@ -103,7 +99,7 @@ class Script extends ContextifyScript {
cachedData,
produceCachedData,
parsingContext,
importModuleDynamically !== undefined);
hostDefinedOptionId);
} catch (e) {
throw e; /* node-do-not-add-exception-line */
}
+8 -12
View File
@@ -771,11 +771,11 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
bool produce_cached_data = false;
Local<Context> parsing_context = context;
bool needs_custom_host_defined_options = false;
Local<Symbol> id_symbol;
if (argc > 2) {
// new ContextifyScript(code, filename, lineOffset, columnOffset,
// cachedData, produceCachedData, parsingContext,
// needsCustomHostDefinedOptions)
// hostDefinedOptionId)
CHECK_EQ(argc, 8);
CHECK(args[2]->IsNumber());
line_offset = args[2].As<Int32>()->Value();
@@ -795,9 +795,8 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
CHECK_NOT_NULL(sandbox);
parsing_context = sandbox->context();
}
if (args[7]->IsTrue()) {
needs_custom_host_defined_options = true;
}
CHECK(args[7]->IsSymbol());
id_symbol = args[7].As<Symbol>();
}
ContextifyScript* contextify_script =
@@ -821,12 +820,6 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
Local<PrimitiveArray> host_defined_options =
PrimitiveArray::New(isolate, loader::HostDefinedOptions::kLength);
// We need a default host defined options that's the same for all scripts
// not needing custom module callbacks for so that the isolate compilation
// cache can be hit.
Local<Symbol> id_symbol = needs_custom_host_defined_options
? Symbol::New(isolate, filename)
: env->default_host_defined_options();
host_defined_options->Set(
isolate, loader::HostDefinedOptions::kID, id_symbol);
@@ -1199,6 +1192,10 @@ void ContextifyContext::CompileFunction(
params_buf = args[8].As<Array>();
}
// Argument 10: host-defined option symbol
CHECK(args[9]->IsSymbol());
Local<Symbol> id_symbol = args[9].As<Symbol>();
// Read cache from cached data buffer
ScriptCompiler::CachedData* cached_data = nullptr;
if (!cached_data_buf.IsEmpty()) {
@@ -1210,7 +1207,6 @@ void ContextifyContext::CompileFunction(
// Set host_defined_options
Local<PrimitiveArray> host_defined_options =
PrimitiveArray::New(isolate, loader::HostDefinedOptions::kLength);
Local<Symbol> id_symbol = Symbol::New(isolate, filename);
host_defined_options->Set(
isolate, loader::HostDefinedOptions::kID, id_symbol);
@@ -1,7 +1,7 @@
'use strict';
require('../common');
const { Script } = require('vm');
const common = require('../common');
const { Script, compileFunction } = require('vm');
const assert = require('assert');
assert.rejects(async () => {
@@ -10,4 +10,11 @@ assert.rejects(async () => {
await imported;
}, {
code: 'ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING'
});
}).then(common.mustCall());
assert.rejects(async () => {
const imported = compileFunction('return import("fs")')();
await imported;
}, {
code: 'ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING'
}).then(common.mustCall());