// Copyright (c) 2025 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 import * as vm from 'node:vm'; import { doesNotThrow, notStrictEqual, strictEqual, throws } from 'node:assert'; export const vmTest = { test() { // Note: test was generated by claude with manual tweaks // Test constants strictEqual(typeof vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER, 'symbol'); strictEqual(typeof vm.constants.DONT_CONTEXTIFY, 'symbol'); // Test isContext function // Should validate object argument throws(() => vm.isContext(null), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.isContext(undefined), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.isContext('string'), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.isContext(123), { code: 'ERR_INVALID_ARG_TYPE', }); // Should work with objects and arrays (but always return false) strictEqual(vm.isContext({}), false); strictEqual(vm.isContext([]), false); strictEqual(vm.isContext(new Object()), false); // Should return true for a valid vm.Context const context = vm.createContext(); strictEqual(vm.isContext(context), true); // Basic construction should return a Script object that throws on run methods const script1 = new vm.Script('code'); strictEqual(script1 instanceof vm.Script, true); throws(() => script1.runInContext(context), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); throws(() => script1.runInNewContext(context), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); throws(() => script1.runInThisContext(), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); // Test Script constructor argument validation throws(() => new vm.Script('code', { filename: 123 }), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => new vm.Script('code', { lineOffset: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => new vm.Script('code', { columnOffset: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => new vm.Script('code', { cachedData: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => new vm.Script('code', { produceCachedData: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', }); throws( () => new vm.Script('code', { importModuleDynamically: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', } ); // Script can accept string options (should be treated as filename) doesNotThrow(() => new vm.Script('code', 'filename.js')); // Test runInContext function throws(() => vm.runInContext('this.a = 1;', {}), { message: /must be an vm.Context/, }); throws(() => vm.runInContext('code', null), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.runInContext('code', 'invalid'), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.runInNewContext('code'), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); throws(() => vm.runInNewContext('code', {}), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); // Test runInThisContext function throws(() => vm.runInThisContext('code'), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); // Test runInThisContext with string options throws(() => vm.runInThisContext('code', 'filename.js'), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); // Test createContext function with no options const context1 = vm.createContext(); strictEqual(vm.isContext(context1), true); // Test createContext function passing in a context object const context2 = vm.createContext(context1); strictEqual(context2, context1); // Test createContext function passing in a non-context object const obj = { a: 1 }; const context3 = vm.createContext(obj); strictEqual(vm.isContext(context3), true); notStrictEqual(context3, obj); // Test createContext argument validation throws(() => vm.createContext({}, { name: 123 }), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.createContext({}, { origin: 123 }), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.createContext({}, { codeGeneration: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.createContext({}, { importModuleDynamically: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.createContext({}, { microtaskMode: 'invalid' }), { code: 'ERR_INVALID_ARG_VALUE', }); // Test createScript function returns a Script that throws on run methods const script2 = vm.createScript('code'); strictEqual(script2 instanceof vm.Script, true); throws(() => script2.runInContext(context), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); throws(() => script2.runInNewContext(context), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); throws(() => script2.runInThisContext(), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); // Test compileFunction throws(() => vm.compileFunction('code'), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); // Test compileFunction argument validation throws(() => vm.compileFunction(123), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.compileFunction('code', 'invalid_params'), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.compileFunction('code', ['param'], { filename: 123 }), { code: 'ERR_INVALID_ARG_TYPE', }); throws( () => vm.compileFunction('code', ['param'], { columnOffset: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', } ); throws( () => vm.compileFunction('code', ['param'], { lineOffset: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', } ); throws( () => vm.compileFunction('code', ['param'], { cachedData: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', } ); throws( () => vm.compileFunction('code', ['param'], { produceCachedData: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', } ); throws( () => vm.compileFunction('code', ['param'], { importModuleDynamically: 'invalid', }), { code: 'ERR_INVALID_ARG_TYPE', } ); throws( () => vm.compileFunction('code', ['param'], { parsingContext: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', } ); throws( () => vm.compileFunction('code', ['param'], { contextExtensions: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', } ); // Test measureMemory throws(() => vm.measureMemory(), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); throws(() => vm.measureMemory({}), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); // Test measureMemory argument validation throws(() => vm.measureMemory({ mode: 'invalid' }), { code: 'ERR_INVALID_ARG_VALUE', }); throws(() => vm.measureMemory({ execution: 'invalid' }), { code: 'ERR_INVALID_ARG_VALUE', }); // Test edge cases with various input types throws(() => vm.runInContext(null, {}), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.runInNewContext(null), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); throws(() => vm.runInThisContext(null), { code: 'ERR_METHOD_NOT_IMPLEMENTED', }); // Test with complex nested validation throws( () => vm.createContext( {}, { codeGeneration: { strings: 'invalid', }, } ), { code: 'ERR_INVALID_ARG_TYPE', } ); throws( () => vm.createContext( {}, { codeGeneration: { wasm: 'invalid', }, } ), { code: 'ERR_INVALID_ARG_TYPE', } ); // Test compileFunction with invalid params array elements throws(() => vm.compileFunction('code', [123]), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.compileFunction('code', ['valid', null]), { code: 'ERR_INVALID_ARG_TYPE', }); // Test compileFunction with invalid contextExtensions throws( () => vm.compileFunction('code', [], { contextExtensions: ['invalid'], }), { code: 'ERR_INVALID_ARG_TYPE', } ); // Test timeout validation in runInThisContext options (must be strictly positive) throws(() => vm.runInThisContext('code', { timeout: -1 }), { code: 'ERR_OUT_OF_RANGE', }); // Test boolean validations throws(() => vm.runInThisContext('code', { breakOnSigint: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', }); throws(() => vm.runInThisContext('code', { displayErrors: 'invalid' }), { code: 'ERR_INVALID_ARG_TYPE', }); // Test that constants object is frozen throws(() => { vm.constants.NEW_PROP = 'test'; }); throws(() => { delete vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER; }); strictEqual(vm.default.Script, vm.Script); strictEqual(vm.default.createContext, vm.createContext); strictEqual(vm.default.isContext, vm.isContext); strictEqual(vm.default.constants, vm.constants); }, };