Skip to content

Commit 384122c

Browse files
implement placeholder vm.Script that throws on method invocations
1 parent cdb67ec commit 384122c

File tree

2 files changed

+38
-28
lines changed

2 files changed

+38
-28
lines changed

src/node/vm.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ import type {
5454
MemoryMeasurement,
5555
} from 'node:vm';
5656

57+
/** Validates that, if a timeout option is defined, it must be a strictly positive integer. */
58+
function validateTimeout(timeout: number | undefined): void {
59+
if (timeout !== undefined) {
60+
validateUint32(timeout, 'options.timeout', true);
61+
}
62+
}
63+
5764
export const constants = {
5865
__proto__: null,
5966
USE_MAIN_CONTEXT_DEFAULT_LOADER: Symbol(
@@ -101,8 +108,6 @@ export class Script {
101108
validateBuffer(cachedData, 'options.cachedData');
102109
}
103110
validateBoolean(produceCachedData, 'options.produceCachedData');
104-
105-
throw new ERR_METHOD_NOT_IMPLEMENTED('Script');
106111
}
107112

108113
createCachedData(): Buffer {
@@ -111,14 +116,10 @@ export class Script {
111116

112117
runInThisContext(options: RunningScriptOptions = {}): unknown {
113118
validateObject(options, 'options');
114-
const {
115-
breakOnSigint = false,
116-
displayErrors = true,
117-
timeout = 0,
118-
} = options;
119+
const { breakOnSigint = false, displayErrors = true, timeout } = options;
119120
validateBoolean(breakOnSigint, 'options.breakOnSigint');
120121
validateBoolean(displayErrors, 'options.displayErrors');
121-
validateUint32(timeout, 'options.timeout', true);
122+
validateTimeout(timeout);
122123
throw new ERR_METHOD_NOT_IMPLEMENTED('runInThisContext');
123124
}
124125

@@ -128,14 +129,10 @@ export class Script {
128129
): unknown {
129130
validateContext(contextifiedObject);
130131
validateObject(options, 'options');
131-
const {
132-
breakOnSigint = false,
133-
displayErrors = true,
134-
timeout = 0,
135-
} = options;
132+
const { breakOnSigint = false, displayErrors = true, timeout } = options;
136133
validateBoolean(breakOnSigint, 'options.breakOnSigint');
137134
validateBoolean(displayErrors, 'options.displayErrors');
138-
validateUint32(timeout, 'options.timeout', true);
135+
validateTimeout(timeout);
139136
throw new ERR_METHOD_NOT_IMPLEMENTED('runInThisContext');
140137
}
141138

src/workerd/api/node/tests/vm-test.js

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as vm from 'node:vm';
2-
import { notStrictEqual, strictEqual, throws } from 'node:assert';
2+
import { doesNotThrow, notStrictEqual, strictEqual, throws } from 'node:assert';
33

44
export const vmTest = {
55
test() {
@@ -33,10 +33,17 @@ export const vmTest = {
3333
const context = vm.createContext();
3434
strictEqual(vm.isContext(context), true);
3535

36-
// Basic construction should validate and throw NOT_IMPLEMENTED
37-
throws(() => new vm.Script('code'), {
36+
// Basic construction should return a Script object that throws on run methods
37+
const script1 = new vm.Script('code');
38+
strictEqual(script1 instanceof vm.Script, true);
39+
throws(() => script1.runInContext(context), {
40+
code: 'ERR_METHOD_NOT_IMPLEMENTED',
41+
});
42+
throws(() => script1.runInNewContext(context), {
43+
code: 'ERR_METHOD_NOT_IMPLEMENTED',
44+
});
45+
throws(() => script1.runInThisContext(), {
3846
code: 'ERR_METHOD_NOT_IMPLEMENTED',
39-
message: /Script/,
4047
});
4148

4249
// Test Script constructor argument validation
@@ -62,10 +69,8 @@ export const vmTest = {
6269
}
6370
);
6471

65-
// Test Script with string options (should be treated as filename)
66-
throws(() => new vm.Script('code', 'filename.js'), {
67-
code: 'ERR_METHOD_NOT_IMPLEMENTED',
68-
});
72+
// Script can accept string options (should be treated as filename)
73+
doesNotThrow(() => new vm.Script('code', 'filename.js'));
6974

7075
// Test runInContext function
7176
throws(() => vm.runInContext('this.a = 1;', {}), {
@@ -126,8 +131,16 @@ export const vmTest = {
126131
code: 'ERR_INVALID_ARG_VALUE',
127132
});
128133

129-
// Test createScript function
130-
throws(() => vm.createScript('code'), {
134+
// Test createScript function returns a Script that throws on run methods
135+
const script2 = vm.createScript('code');
136+
strictEqual(script2 instanceof vm.Script, true);
137+
throws(() => script2.runInContext(context), {
138+
code: 'ERR_METHOD_NOT_IMPLEMENTED',
139+
});
140+
throws(() => script2.runInNewContext(context), {
141+
code: 'ERR_METHOD_NOT_IMPLEMENTED',
142+
});
143+
throws(() => script2.runInThisContext(), {
131144
code: 'ERR_METHOD_NOT_IMPLEMENTED',
132145
});
133146

@@ -272,17 +285,17 @@ export const vmTest = {
272285
}
273286
);
274287

275-
// Test timeout validation in runInThisContext options
288+
// Test timeout validation in runInThisContext options (must be strictly positive)
276289
throws(() => vm.runInThisContext('code', { timeout: -1 }), {
277-
code: 'ERR_METHOD_NOT_IMPLEMENTED',
290+
code: 'ERR_OUT_OF_RANGE',
278291
});
279292

280293
// Test boolean validations
281294
throws(() => vm.runInThisContext('code', { breakOnSigint: 'invalid' }), {
282-
code: 'ERR_METHOD_NOT_IMPLEMENTED',
295+
code: 'ERR_INVALID_ARG_TYPE',
283296
});
284297
throws(() => vm.runInThisContext('code', { displayErrors: 'invalid' }), {
285-
code: 'ERR_METHOD_NOT_IMPLEMENTED',
298+
code: 'ERR_INVALID_ARG_TYPE',
286299
});
287300

288301
// Test that constants object is frozen

0 commit comments

Comments
 (0)