deno/tests/unit_node/vm_test.ts
Divy Srivastava 402d59eea9
fix(ext/node): promise rejection in VM contexts (#23305)
Fixes https://github.com/denoland/deno/issues/23297

`docusaurus build` works!

```
$ deno run -A repro.js 
fish: Job 1, 'deno run -A ../../littledivy/fs…' terminated by signal SIGSEGV (Address
 boundary error)
$ denod run -A repro.js
error: Uncaught (in promise) Error: rejected
```

Depends on https://github.com/denoland/deno_core/pull/693
2024-04-13 17:02:07 +05:30

151 lines
3.5 KiB
TypeScript

// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { assertEquals, assertThrows } from "@std/assert/mod.ts";
import {
createContext,
isContext,
runInContext,
runInNewContext,
runInThisContext,
Script,
} from "node:vm";
Deno.test({
name: "vm runInNewContext",
fn() {
const two = runInNewContext("1 + 1");
assertEquals(two, 2);
},
});
Deno.test({
name: "vm new Script()",
fn() {
const script = new Script(`
function add(a, b) {
return a + b;
}
const x = add(1, 2);
x
`);
const value = script.runInThisContext();
assertEquals(value, 3);
},
});
// https://github.com/denoland/deno/issues/23186
Deno.test({
name: "vm runInNewContext sandbox",
fn() {
const sandbox = { fromAnotherRealm: false };
runInNewContext("fromAnotherRealm = {}", sandbox);
assertEquals(typeof sandbox.fromAnotherRealm, "object");
},
});
// https://github.com/denoland/deno/issues/22395
Deno.test({
name: "vm runInewContext with context object",
fn() {
const context = { a: 1, b: 2 };
const result = runInNewContext("a + b", context);
assertEquals(result, 3);
},
});
// https://github.com/denoland/deno/issues/18299
Deno.test({
name: "vm createContext and runInContext",
fn() {
// @ts-expect-error implicit any
globalThis.globalVar = 3;
const context = { globalVar: 1 };
createContext(context);
runInContext("globalVar *= 2", context);
assertEquals(context.globalVar, 2);
// @ts-expect-error implicit any
assertEquals(globalThis.globalVar, 3);
},
});
Deno.test({
name: "vm runInThisContext Error rethrow",
fn() {
assertThrows(
() => {
runInThisContext("throw new Error('error')");
},
Error,
"error",
);
assertThrows(
() => {
runInThisContext("throw new TypeError('type error')");
},
TypeError,
"type error",
);
},
});
// https://github.com/webpack/webpack/blob/87660921808566ef3b8796f8df61bd79fc026108/lib/javascript/JavascriptParser.js#L4329
Deno.test({
name: "vm runInNewContext webpack magic comments",
fn() {
const webpackCommentRegExp = new RegExp(
/(^|\W)webpack[A-Z]{1,}[A-Za-z]{1,}:/,
);
const comments = [
'webpackChunkName: "test"',
'webpackMode: "lazy"',
"webpackPrefetch: true",
"webpackPreload: true",
"webpackProvidedExports: true",
'webpackChunkLoading: "require"',
'webpackExports: ["default", "named"]',
];
for (const comment of comments) {
const result = webpackCommentRegExp.test(comment);
assertEquals(result, true);
const [[key, _value]]: [string, string][] = Object.entries(
runInNewContext(`(function(){return {${comment}};})()`),
);
const expectedKey = comment.split(":")[0].trim();
assertEquals(key, expectedKey);
}
},
});
// https://github.com/denoland/deno/issues/18315
Deno.test({
name: "vm isContext",
fn() {
// Currently we do not expose VM contexts so this is always false.
const obj = {};
assertEquals(isContext(obj), false);
assertEquals(isContext(globalThis), false);
const sandbox = runInNewContext("{}");
assertEquals(isContext(sandbox), false);
},
});
// https://github.com/denoland/deno/issues/23297
Deno.test({
name: "vm context promise rejection",
fn() {
const code = `
function reject() {
return Promise.reject(new Error('rejected'));
}
reject().catch(() => {})
`;
const script = new Script(code);
script.runInNewContext();
},
});