148 lines
6.6 KiB
TypeScript
148 lines
6.6 KiB
TypeScript
import { createContext } from "vm";
|
|
|
|
import { executeJavaScript, executeJavaScriptAsync } from "./helpers";
|
|
|
|
describe("Helpers", () => {
|
|
describe("executeJavaScript", () => {
|
|
it("can execute simple JavaScript", () => {
|
|
{
|
|
const context = createContext({});
|
|
expect(executeJavaScript("123", "myfile.js", context)).toEqual(123);
|
|
}
|
|
|
|
{
|
|
const context = createContext({});
|
|
expect(executeJavaScript("1+1", "myfile.js", context)).toEqual(2);
|
|
}
|
|
});
|
|
|
|
it("can execute multiple commands in one context", () => {
|
|
const context = createContext({});
|
|
expect(executeJavaScript("let a", "myfile.js", context)).toBeUndefined();
|
|
expect(executeJavaScript("a = 2", "myfile.js", context)).toEqual(2);
|
|
expect(executeJavaScript("a", "myfile.js", context)).toEqual(2);
|
|
expect(executeJavaScript("let b = 3", "myfile.js", context)).toBeUndefined();
|
|
expect(executeJavaScript("a+b", "myfile.js", context)).toEqual(5);
|
|
});
|
|
|
|
it("has no require() in sandbox context", () => {
|
|
const context = createContext({});
|
|
expect(executeJavaScript("typeof require", "myfile.js", context)).toEqual("undefined");
|
|
});
|
|
|
|
it("has no exports object in sandbox context", () => {
|
|
const context = createContext({});
|
|
expect(executeJavaScript("typeof exports", "myfile.js", context)).toEqual("undefined");
|
|
});
|
|
|
|
it("has no module object in sandbox context", () => {
|
|
const context = createContext({});
|
|
expect(executeJavaScript("typeof module", "myfile.js", context)).toEqual("undefined");
|
|
});
|
|
|
|
it("can use require when passed into sandbox context", () => {
|
|
const context = createContext({ require: require });
|
|
expect(executeJavaScript("const path = require('path')", "myfile.js", context)).toBeUndefined();
|
|
expect(executeJavaScript("path.join('.')", "myfile.js", context)).toEqual(".");
|
|
});
|
|
|
|
it("can use module when passed into sandbox context", () => {
|
|
const context = createContext({ module: module });
|
|
expect(executeJavaScript("module.exports.fooTest", "myfile.js", context)).toBeUndefined();
|
|
expect(executeJavaScript("module.exports.fooTest = 'bar'", "myfile.js", context)).toEqual("bar");
|
|
expect(executeJavaScript("module.exports.fooTest", "myfile.js", context)).toEqual("bar");
|
|
// roll back change to module.exports
|
|
module.exports.fooTest = undefined;
|
|
});
|
|
|
|
it("can use exports when passed into sandbox context", () => {
|
|
const context = createContext({ exports: {} });
|
|
expect(executeJavaScript("exports.fooTest", "myfile.js", context)).toBeUndefined();
|
|
expect(executeJavaScript("exports.fooTest = 'bar'", "myfile.js", context)).toEqual("bar");
|
|
expect(executeJavaScript("exports.fooTest", "myfile.js", context)).toEqual("bar");
|
|
});
|
|
});
|
|
|
|
describe("executeJavaScriptAsync", () => {
|
|
it("can execute top level await with brackets", async () => {
|
|
const context = createContext({});
|
|
expect(await executeJavaScriptAsync("await (1)", "myfile.js", context)).toEqual(1);
|
|
});
|
|
|
|
it("can execute top level await without brackets", async () => {
|
|
const context = createContext({});
|
|
expect(await executeJavaScriptAsync("await 1", "myfile.js", context)).toEqual(1);
|
|
});
|
|
|
|
it("can handle multiple awaits", async () => {
|
|
const context = createContext({});
|
|
expect(await executeJavaScriptAsync("await 1 + await 2", "myfile.js", context)).toEqual(3);
|
|
});
|
|
|
|
it("errors for local declaration without assignment", async () => {
|
|
// `var a` cannot be converted into an assignment because it must not override an
|
|
// existing value. Thus we cannot execute it
|
|
const context = createContext({});
|
|
await executeJavaScriptAsync("var a", "myfile.js", context)
|
|
.then(() => fail("must not resolve"))
|
|
.catch((e) => expect(e).toMatch(/SyntaxError:/));
|
|
await executeJavaScriptAsync("let b", "myfile.js", context)
|
|
.then(() => fail("must not resolve"))
|
|
.catch((e) => expect(e).toMatch(/SyntaxError:/));
|
|
await executeJavaScriptAsync("const c", "myfile.js", context)
|
|
.then(() => fail("must not resolve"))
|
|
.catch((e) => expect(e).toMatch(/SyntaxError:/));
|
|
});
|
|
|
|
it("can execute multiple commands in one context", async () => {
|
|
const context = createContext({});
|
|
expect(await executeJavaScriptAsync("let a = 2", "myfile.js", context)).toBeUndefined();
|
|
expect(await executeJavaScriptAsync("a", "myfile.js", context)).toEqual(2);
|
|
expect(await executeJavaScriptAsync("a += 1", "myfile.js", context)).toEqual(3);
|
|
expect(await executeJavaScriptAsync("a += 7", "myfile.js", context)).toEqual(10);
|
|
expect(await executeJavaScriptAsync("a", "myfile.js", context)).toEqual(10);
|
|
expect((context as any).a).toEqual(10);
|
|
});
|
|
|
|
it("local variables are available across multiple calls in one context", async () => {
|
|
const context = createContext({});
|
|
expect(await executeJavaScriptAsync("let a = 3", "myfile.js", context)).toBeUndefined();
|
|
expect(await executeJavaScriptAsync("a", "myfile.js", context)).toEqual(3);
|
|
expect((context as any).a).toEqual(3);
|
|
});
|
|
|
|
it("works with strict mode", async () => {
|
|
const context = createContext({});
|
|
expect(await executeJavaScriptAsync('"use strict"; let a = 3', "myfile.js", context)).toBeUndefined();
|
|
expect(await executeJavaScriptAsync('"use strict"; a', "myfile.js", context)).toEqual(3);
|
|
expect((context as any).a).toEqual(3);
|
|
});
|
|
|
|
it("can reassign const", async () => {
|
|
// a side-effect of local variable assignment manipulation
|
|
const context = createContext({});
|
|
expect(await executeJavaScriptAsync("const a = 3", "myfile.js", context)).toBeUndefined();
|
|
expect((context as any).a).toEqual(3);
|
|
expect(await executeJavaScriptAsync("const a = 4", "myfile.js", context)).toBeUndefined();
|
|
expect((context as any).a).toEqual(4);
|
|
});
|
|
|
|
it("can execute timeout promise code", async () => {
|
|
const context = createContext({ setTimeout: setTimeout });
|
|
const code = "await (new Promise(resolve => setTimeout(() => resolve('job done'), 5)))";
|
|
expect(await executeJavaScriptAsync(code, "myfile.js", context)).toEqual("job done");
|
|
});
|
|
|
|
it("can execute timeout code in multiple statements", async () => {
|
|
const context = createContext({ setTimeout: setTimeout });
|
|
const code = `
|
|
const promise = new Promise(resolve => {
|
|
setTimeout(() => resolve('job done'), 5);
|
|
});
|
|
await (promise);
|
|
`;
|
|
expect(await executeJavaScriptAsync(code, "myfile.js", context)).toEqual("job done");
|
|
});
|
|
});
|
|
});
|