Skip to content

Commit

Permalink
fix(xsnap): Thread spawn and os into xsnap
Browse files Browse the repository at this point in the history
  • Loading branch information
kriskowal committed Jan 11, 2021
1 parent 8887cf0 commit 619a4de
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 34 deletions.
49 changes: 27 additions & 22 deletions packages/xsnap/src/xsnap.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// @ts-check
/* eslint no-await-in-loop: ["off"] */

/**
* @typedef {typeof import('child_process').spawn} Spawn
*/

/**
* @template T
* @typedef {import('./defer').Deferred<T>} Deferred
*/

import { spawn } from 'child_process';
import { type as getOsType } from 'os';
import { defer } from './defer';
import * as netstring from './netstring';
import * as node from './node-stream';
Expand All @@ -18,26 +20,6 @@ const QUERY = '?'.charCodeAt(0);

const importMetaUrl = `file://${__filename}`;

const osType = getOsType();
const platform = {
Linux: 'lin',
Darwin: 'mac',
Windows_NT: 'win',
}[osType];

if (platform === undefined) {
throw new Error(`xsnap does not support platform ${osType}`);
}

const xsnapBin = new URL(
`../build/bin/${platform}/release/xsnap`,
importMetaUrl,
).pathname;
const xsnapDebugBin = new URL(
`../build/bin/${platform}/debug/xsnap`,
importMetaUrl,
).pathname;

const encoder = new TextEncoder();
const decoder = new TextDecoder();

Expand All @@ -51,6 +33,8 @@ function echoSysCall(arg) {

/**
* @param {Object} options
* @param {string} options.os
* @param {Spawn} options.spawn
* @param {(request:Uint8Array) => Promise<Uint8Array>} [options.answerSysCall]
* @param {string=} [options.name]
* @param {boolean=} [options.debug]
Expand All @@ -60,6 +44,8 @@ function echoSysCall(arg) {
*/
export function xsnap(options) {
const {
os,
spawn,
name = '<unnamed xsnap worker>',
answerSysCall = echoSysCall,
debug = false,
Expand All @@ -68,6 +54,25 @@ export function xsnap(options) {
stderr = 'inherit',
} = options;

const platform = {
Linux: 'lin',
Darwin: 'mac',
Windows_NT: 'win',
}[os];

if (platform === undefined) {
throw new Error(`xsnap does not support platform ${os}`);
}

const xsnapBin = new URL(
`../build/bin/${platform}/release/xsnap`,
importMetaUrl,
).pathname;
const xsnapDebugBin = new URL(
`../build/bin/${platform}/debug/xsnap`,
importMetaUrl,
).pathname;

/** @type {Deferred<Error?>} */
const vatExit = defer();

Expand Down
13 changes: 10 additions & 3 deletions packages/xsnap/src/xsrepl.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@
* @template T
* @typedef {import('./defer').Deferred<T>} Deferred
*/
import * as childProcess from 'child_process';
import * as os from 'os';
import * as readline from 'readline';
import { xsnap } from './xsnap';
import { defer } from './defer';

const decoder = new TextDecoder();

async function main() {
const xsnapOptions = {
spawn: childProcess.spawn,
os: os.type(),
};

/**
* For the purposes of the REPL, the only syscall is effectively `print`.
*
Expand All @@ -25,11 +32,11 @@ async function main() {
}

const rl = readline.createInterface({
input: process.stdin,
input: /** @type {NodeJS.ReadableStream} */ (process.stdin),
output: process.stdout,
});

let vat = xsnap({ answerSysCall });
let vat = xsnap({ ...xsnapOptions, answerSysCall });

await vat.evaluate(`
const compartment = new Compartment();
Expand Down Expand Up @@ -60,7 +67,7 @@ async function main() {
} else if (answer === 'load') {
const file = await ask('file> ');
await vat.close();
vat = xsnap({ answerSysCall, snapshot: file });
vat = xsnap({ ...xsnapOptions, answerSysCall, snapshot: file });
} else if (answer === 'save') {
const file = await ask('file> ');
await vat.snapshot(file);
Expand Down
25 changes: 16 additions & 9 deletions packages/xsnap/test/test-xsnap.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import test from 'ava';
import * as childProcess from 'child_process';
import * as os from 'os';
import { xsnap } from '../src/xsnap';

const importMetaUrl = `file://${__filename}`;

const decoder = new TextDecoder();
const encoder = new TextEncoder();

const xsnapOptions = {
spawn: childProcess.spawn,
os: os.type(),
};

test('evaluate and sysCall', async t => {
const messages = [];
async function answerSysCall(message) {
messages.push(decoder.decode(message));
return new Uint8Array();
}
const vat = xsnap({ answerSysCall });
const vat = xsnap({ ...xsnapOptions, answerSysCall });
await vat.evaluate(`sysCall(ArrayBuffer.fromString("Hello, World!"));`);
await vat.close();
t.deepEqual(['Hello, World!'], messages);
Expand All @@ -24,7 +31,7 @@ test('evaluate until idle', async t => {
messages.push(decoder.decode(message));
return new Uint8Array();
}
const vat = xsnap({ answerSysCall });
const vat = xsnap({ ...xsnapOptions, answerSysCall });
await vat.evaluate(`
(async () => {
sysCall(ArrayBuffer.fromString("Hello, World!"));
Expand All @@ -40,7 +47,7 @@ test('run script until idle', async t => {
messages.push(decoder.decode(message));
return new Uint8Array();
}
const vat = xsnap({ answerSysCall });
const vat = xsnap({ ...xsnapOptions, answerSysCall });
await vat.execute(new URL('fixture-xsnap-script.js', importMetaUrl).pathname);
await vat.close();
t.deepEqual(['Hello, World!'], messages);
Expand All @@ -55,7 +62,7 @@ test('sysCall is synchronous inside, async outside', async t => {
await Promise.resolve(null);
return encoder.encode(`${number + 1}`);
}
const vat = xsnap({ answerSysCall });
const vat = xsnap({ ...xsnapOptions, answerSysCall });
await vat.evaluate(`
const response = sysCall(ArrayBuffer.fromString('0'));
const number = +String.fromArrayBuffer(response);
Expand All @@ -71,7 +78,7 @@ test('deliver a message', async t => {
messages.push(+decoder.decode(message));
return new Uint8Array();
}
const vat = xsnap({ answerSysCall });
const vat = xsnap({ ...xsnapOptions, answerSysCall });
await vat.evaluate(`
function answerSysCall(message) {
const number = +String.fromArrayBuffer(message);
Expand All @@ -91,7 +98,7 @@ test.only('receive a response', async t => {
messages.push(+decoder.decode(message));
return new Uint8Array();
}
const vat = xsnap({ answerSysCall });
const vat = xsnap({ ...xsnapOptions, answerSysCall });
await vat.evaluate(`
function answerSysCall(message) {
const number = +String.fromArrayBuffer(message);
Expand All @@ -116,7 +123,7 @@ test('serialize concurrent messages', async t => {
messages.push(+decoder.decode(message));
return new Uint8Array();
}
const vat = xsnap({ answerSysCall });
const vat = xsnap({ ...xsnapOptions, answerSysCall });
await vat.evaluate(`
globalThis.answerSysCall = message => {
const number = +String.fromArrayBuffer(message);
Expand All @@ -137,14 +144,14 @@ test('write and read snapshot', async t => {

const snapshot = new URL('fixture-snapshot.xss', importMetaUrl).pathname;

const vat0 = xsnap({ answerSysCall });
const vat0 = xsnap({ ...xsnapOptions, answerSysCall });
await vat0.evaluate(`
globalThis.hello = "Hello, World!";
`);
await vat0.snapshot(snapshot);
await vat0.close();

const vat1 = xsnap({ answerSysCall, snapshot });
const vat1 = xsnap({ ...xsnapOptions, answerSysCall, snapshot });
await vat1.evaluate(`
sysCall(ArrayBuffer.fromString(hello));
`);
Expand Down

0 comments on commit 619a4de

Please sign in to comment.