Skip to content

Commit de79c42

Browse files
joyeecheungGeoffreyBooth
authored andcommitted
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.
1 parent 18a8187 commit de79c42

File tree

4 files changed

+45
-22
lines changed

4 files changed

+45
-22
lines changed

lib/internal/vm.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22

33
const {
44
ArrayPrototypeForEach,
5+
Symbol,
56
} = primordials;
67

78
const {
89
compileFunction,
910
isContext: _isContext,
1011
} = internalBinding('contextify');
12+
const {
13+
default_host_defined_options,
14+
} = internalBinding('symbols');
1115
const {
1216
validateArray,
1317
validateBoolean,
@@ -30,12 +34,28 @@ function isContext(object) {
3034
return _isContext(object);
3135
}
3236

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+
}
53+
3354
function internalCompileFunction(code, params, options) {
3455
validateString(code, 'code');
3556
if (params !== undefined) {
3657
validateStringArray(params, 'params');
3758
}
38-
3959
const {
4060
filename = '',
4161
columnOffset = 0,
@@ -72,6 +92,8 @@ function internalCompileFunction(code, params, options) {
7292
validateObject(extension, name, kValidateObjectAllowNullable);
7393
});
7494

95+
const hostDefinedOptionId =
96+
getHostDefinedOptionId(importModuleDynamically, filename);
7597
const result = compileFunction(
7698
code,
7799
filename,
@@ -82,6 +104,7 @@ function internalCompileFunction(code, params, options) {
82104
parsingContext,
83105
contextExtensions,
84106
params,
107+
hostDefinedOptionId,
85108
);
86109

87110
if (produceCachedData) {
@@ -115,4 +138,5 @@ function internalCompileFunction(code, params, options) {
115138
module.exports = {
116139
internalCompileFunction,
117140
isContext,
141+
getHostDefinedOptionId,
118142
};

lib/vm.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ const {
4141
const {
4242
validateBoolean,
4343
validateBuffer,
44-
validateFunction,
4544
validateInt32,
4645
validateObject,
4746
validateOneOf,
@@ -54,6 +53,7 @@ const {
5453
kVmBreakFirstLineSymbol,
5554
} = require('internal/util');
5655
const {
56+
getHostDefinedOptionId,
5757
internalCompileFunction,
5858
isContext,
5959
} = require('internal/vm');
@@ -86,12 +86,8 @@ class Script extends ContextifyScript {
8686
}
8787
validateBoolean(produceCachedData, 'options.produceCachedData');
8888

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);
9591
// Calling `ReThrow()` on a native TryCatch does not generate a new
9692
// abort-on-uncaught-exception check. A dummy try/catch in JS land
9793
// protects against that.
@@ -103,7 +99,7 @@ class Script extends ContextifyScript {
10399
cachedData,
104100
produceCachedData,
105101
parsingContext,
106-
importModuleDynamically !== undefined);
102+
hostDefinedOptionId);
107103
} catch (e) {
108104
throw e; /* node-do-not-add-exception-line */
109105
}

src/node_contextify.cc

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -771,11 +771,11 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
771771
bool produce_cached_data = false;
772772
Local<Context> parsing_context = context;
773773

774-
bool needs_custom_host_defined_options = false;
774+
Local<Symbol> id_symbol;
775775
if (argc > 2) {
776776
// new ContextifyScript(code, filename, lineOffset, columnOffset,
777777
// cachedData, produceCachedData, parsingContext,
778-
// needsCustomHostDefinedOptions)
778+
// hostDefinedOptionId)
779779
CHECK_EQ(argc, 8);
780780
CHECK(args[2]->IsNumber());
781781
line_offset = args[2].As<Int32>()->Value();
@@ -795,9 +795,8 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
795795
CHECK_NOT_NULL(sandbox);
796796
parsing_context = sandbox->context();
797797
}
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>();
801800
}
802801

803802
ContextifyScript* contextify_script =
@@ -821,12 +820,6 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
821820

822821
Local<PrimitiveArray> host_defined_options =
823822
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();
830823
host_defined_options->Set(
831824
isolate, loader::HostDefinedOptions::kID, id_symbol);
832825

@@ -1199,6 +1192,10 @@ void ContextifyContext::CompileFunction(
11991192
params_buf = args[8].As<Array>();
12001193
}
12011194

1195+
// Argument 9: host-defined option symbol
1196+
CHECK(args[9]->IsSymbol());
1197+
Local<Symbol> id_symbol = args[9].As<Symbol>();
1198+
12021199
// Read cache from cached data buffer
12031200
ScriptCompiler::CachedData* cached_data = nullptr;
12041201
if (!cached_data_buf.IsEmpty()) {
@@ -1210,7 +1207,6 @@ void ContextifyContext::CompileFunction(
12101207
// Set host_defined_options
12111208
Local<PrimitiveArray> host_defined_options =
12121209
PrimitiveArray::New(isolate, loader::HostDefinedOptions::kLength);
1213-
Local<Symbol> id_symbol = Symbol::New(isolate, filename);
12141210
host_defined_options->Set(
12151211
isolate, loader::HostDefinedOptions::kID, id_symbol);
12161212

test/parallel/test-vm-no-dynamic-import-callback.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
require('../common');
4-
const { Script } = require('vm');
4+
const { Script, compileFunction } = require('vm');
55
const assert = require('assert');
66

77
assert.rejects(async () => {
@@ -11,3 +11,10 @@ assert.rejects(async () => {
1111
}, {
1212
code: 'ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING'
1313
});
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+
});

0 commit comments

Comments
 (0)