Skip to content

Function returned by vm.compileFunction can't accept arguments when cachedData is passed #48175

Closed
@RaisinTen

Description

@RaisinTen

Version

v20.2.0

Platform

Darwin Darshans-MacBook-Pro.local 22.4.0 Darwin Kernel Version 22.4.0: Mon Mar 6 21:00:17 PST 2023; root:xnu-8796.101.5~3/RELEASE_X86_64 x86_64

Subsystem

vm

What steps will reproduce the bug?

test.js

const vm = require('vm');

const code = `
const os = require('os');
console.log(os.release());
`;

const script = new vm.Script(code, {
  produceCachedData: true
});

const { cachedData } = script;

const fn = vm.compileFunction(code, ['require'], {
  cachedData
});
console.log(`fn: [${fn.toString()}]`);
fn(require);
$ node test.js
fn: [
const os = require('os');
console.log(os.release());
]
evalmachine.<anonymous>:2
const os = require('os');
           ^

ReferenceError: require is not defined
    at evalmachine.<anonymous>:2:12
    at Object.<anonymous> (/tmp/test.js:18:1)
    at Module._compile (node:internal/modules/cjs/loader:1255:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1309:10)
    at Module.load (node:internal/modules/cjs/loader:1113:32)
    at Module._load (node:internal/modules/cjs/loader:960:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12)
    at node:internal/main/run_main_module:23:47

Node.js v20.2.0

Also, note that when I print the function, it doesn't have the function (...) { and } wrappers. I have no idea how that's even possible.

However, if I comment out the part where cachedData is being passed to vm.compileFunction, it doesn't run into errors.

test.js

const vm = require('vm');

const code = `
const os = require('os');
console.log(os.release());
`;

const script = new vm.Script(code, {
  produceCachedData: true
});

const { cachedData } = script;

const fn = vm.compileFunction(code, ['require'], {
  // cachedData
});
console.log(`fn: [${fn.toString()}]`);
fn(require);
$ node test.js
fn: [function (require) {

const os = require('os');
console.log(os.release());

}]
22.4.0

How often does it reproduce? Is there a required condition?

Reproduces always consistently.

What is the expected behavior?

The returned function should have the params wrapped in.

Why is that the expected behavior?

The doc says that this would return a function with the passed params wrapped in but in this case, it doesn't seem to do so.

What do you see instead?

The returned function does not have the params wrapped in.

Additional information

AFAICT, Node.js simply passes the args to V8's ScriptCompiler::CompileFunction function in

node/src/node_contextify.cc

Lines 1248 to 1256 in e530098

MaybeLocal<Function> maybe_fn = ScriptCompiler::CompileFunction(
parsing_context,
&source,
params.size(),
params.data(),
context_extensions.size(),
context_extensions.data(),
options,
v8::ScriptCompiler::NoCacheReason::kNoCacheNoReason);
, so in case this is considered as buggy behavior, it might be a V8 bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    vmIssues and PRs related to the vm subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions