From 5b9187ed674a060cd70b8cc7fe584a70ec38ff65 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Fri, 27 Mar 2026 10:31:53 -0400 Subject: [PATCH] vm: `DONT_CONTEXTIFY` when no contextObject set When `contextObject` is not passed in `vm.createContext`, do not contextify by default. This reduces the chance that the script semantics are broken by the interceptors. --- lib/vm.js | 2 +- ...est-vm-function-declaration-uses-define.js | 2 +- test/parallel/test-vm-strict-define.js | 51 +++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-vm-strict-define.js diff --git a/lib/vm.js b/lib/vm.js index ae710806201893..c3c76f6d6a2700 100644 --- a/lib/vm.js +++ b/lib/vm.js @@ -222,7 +222,7 @@ function getContextOptions(options) { } let defaultContextNameIndex = 1; -function createContext(contextObject = {}, options = kEmptyObject) { +function createContext(contextObject = vm_context_no_contextify, options = kEmptyObject) { if (contextObject !== vm_context_no_contextify && isContext(contextObject)) { return contextObject; } diff --git a/test/known_issues/test-vm-function-declaration-uses-define.js b/test/known_issues/test-vm-function-declaration-uses-define.js index 1cfdd9c368e570..a7f7aa92e78d4a 100644 --- a/test/known_issues/test-vm-function-declaration-uses-define.js +++ b/test/known_issues/test-vm-function-declaration-uses-define.js @@ -9,7 +9,7 @@ const common = require('../common'); const vm = require('vm'); const assert = require('assert'); -const ctx = vm.createContext(); +const ctx = vm.createContext({}); Object.defineProperty(ctx, 'x', { enumerable: true, configurable: true, diff --git a/test/parallel/test-vm-strict-define.js b/test/parallel/test-vm-strict-define.js new file mode 100644 index 00000000000000..4c14f1f73d2f7a --- /dev/null +++ b/test/parallel/test-vm-strict-define.js @@ -0,0 +1,51 @@ +'use strict'; +require('../common'); +const assert = require('assert'); + +const vm = require('vm'); + +// Declared with `var`. +{ + const ctx = vm.createContext(); + vm.runInContext(`"use strict"; var x; x = 42;`, ctx); + assert.strictEqual(ctx.x, 42); +} + +// Define on `globalThis`. +{ + const ctx = vm.createContext(); + vm.runInContext(` + "use strict"; + Object.defineProperty(globalThis, "x", { + configurable: true, + value: 42, + }); + `, ctx); + const ret = vm.runInContext(`"use strict"; x`, ctx); + assert.strictEqual(ret, 42); + assert.strictEqual(ctx.x, 42); +} + +// Set on globalThis. +{ + const ctx = vm.createContext(); + vm.runInContext(`"use strict"; globalThis.x = 42`, ctx); + const ret = vm.runInContext(`"use strict"; x`, ctx); + assert.strictEqual(ret, 42); + assert.strictEqual(ctx.x, 42); +} + +// Set on context. +// Should throw a ReferenceError when a variable is not defined in strict-mode. +assert.throws(() => vm.runInNewContext(`"use strict"; x = 42`), + /ReferenceError: x is not defined/); + +// Known issue since V8 14.6. +// When the context is a "contextified" object, ReferenceError can not be thrown. +// TODO(legendecas): https://github.com/nodejs/node/pull/61898#issuecomment-4142811603 +// Refs: https://chromium-review.googlesource.com/c/v8/v8/+/7474608 +{ + const ctx = vm.createContext({}); + assert.throws(() => vm.runInContext(`"use strict"; x = 42`, ctx), + /ReferenceError: x is not defined/); +}