Skip to content

Commit db04624

Browse files
IdanHorwaldron
authored andcommitted
Add SerenityOS's LibJS
1 parent 92c560d commit db04624

File tree

6 files changed

+126
-13
lines changed

6 files changed

+126
-13
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ npm install eshost
2626
| graaljs | GraalJS | CLI | Any | [Download](https://github.com/graalvm/graalvm-ce-builds) | |
2727
| jsshell¹ | SpiderMonkey | CLI | Any | [Download](https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central/) | SpiderMonkey console host. |
2828
| jsc¹ | JavaScriptCore | CLI | Mac² | Build [from source](http://trac.webkit.org/wiki/JavaScriptCore)³ | |
29+
| libjs | LibJS | CLI | Any | Build [from source](https://github.com/SerenityOS/serenity) | |
2930
| nashorn | Nashorn | CLI | Any | Build [from source](https://wiki.openjdk.java.net/display/Nashorn/Building+Nashorn) | |
3031
| node | Node.js | CLI | Any | https://nodejs.org | [Active LTS versions only](https://nodejs.org/en/about/releases/) |
3132
| qjs<sup>4</sup> | QuickJS | CLI | Any | Build [from source](https://bellard.org/quickjs/) | |
@@ -84,6 +85,7 @@ Creates an instance of a host agent for a particular host type. See the table ab
8485
| GraalJS | `graaljs` |
8586
| Hermes | `hermes` |
8687
| JavaScriptCore | `javascriptcore`, `jsc` |
88+
| LibJS | `libjs` |
8789
| Nashorn | `nashorn` |
8890
| Node | `node` |
8991
| QuickJS | `qjs` <sup>1</sup> |

lib/agents/libjs.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
'use strict';
2+
3+
const fs = require('fs');
4+
const runtimePath = require('../runtime-path');
5+
const ConsoleAgent = require('../ConsoleAgent');
6+
7+
const errorRe = /^Uncaught exception:(?: \[(.+?)])?(?: (.+))?((?:\n -> .+|\n \d+? more calls)*)?\n?/gm;
8+
9+
class LibJSAgent extends ConsoleAgent {
10+
constructor(options) {
11+
super(options);
12+
13+
this.args.unshift('--disable-ansi-colors', '--no-syntax-highlight', '--disable-source-location-hints');
14+
}
15+
16+
async evalScript(code, options = {}) {
17+
if (options.module && this.args[0] !== '--as-module') {
18+
this.args.unshift('--as-module');
19+
}
20+
21+
if (!options.module && this.args[0] === '--as-module') {
22+
this.args.shift();
23+
}
24+
25+
return super.evalScript(code, options);
26+
}
27+
28+
parseError(str) {
29+
const match = errorRe.exec(str);
30+
31+
if (!match)
32+
return null;
33+
34+
const name = match[1] ? match[1].trim() : "";
35+
const message = match[2] ? match[2].trim() : "";
36+
const stack = [];
37+
if (match[3]) {
38+
const stackTrace = match[3].trim().split('\n');
39+
stackTrace.forEach(entry => {
40+
const trimmedEntry = entry.trim();
41+
if (trimmedEntry.endsWith(" more calls")) { // collapsed 5+ repeated entries
42+
const calls = parseInt(trimmedEntry.substring(0, trimmedEntry.indexOf(" more calls")));
43+
for (let i = 0; i < calls; ++i)
44+
stack.push(stack[stack.length - 1]);
45+
} else {
46+
stack.push({
47+
functionName: trimmedEntry.substring(trimmedEntry.indexOf(" -> ") + 4),
48+
lineNumber: 1
49+
});
50+
}
51+
});
52+
}
53+
54+
return {
55+
name,
56+
message,
57+
stack
58+
};
59+
}
60+
61+
normalizeResult(result) {
62+
const match = result.stdout.match(errorRe);
63+
64+
if (match) {
65+
result.stdout = result.stdout.replace(errorRe, '');
66+
result.stderr = match[0];
67+
}
68+
69+
return result;
70+
}
71+
}
72+
73+
LibJSAgent.runtime = fs.readFileSync(runtimePath.for('libjs'), 'utf8');
74+
75+
module.exports = LibJSAgent;

lib/supported-hosts.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const supportedHostsMap = Object.assign({
1919
javascriptcore: 'jsc',
2020
// jsc: 'jsc',
2121
// jsshell: 'jsshell',
22+
// libjs: 'libjs',
2223
// nashorn: 'nashorn',
2324
// node: 'node',
2425
// qjs: 'qjs',

runtimes/libjs.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
function print(...args) {
2+
console.log(...args);
3+
}
4+
var $262 = {
5+
global: globalThis,
6+
gc() {
7+
return gc();
8+
},
9+
createRealm(options) {
10+
throw new Test262Error('createRealm() not yet supported.');
11+
},
12+
evalScript(code) {
13+
throw new Test262Error('evalScript() not yet supported.');
14+
},
15+
getGlobal(name) {
16+
return this.global[name];
17+
},
18+
setGlobal(name, value) {
19+
this.global[name] = value;
20+
},
21+
destroy() { /* noop */ },
22+
IsHTMLDDA() { return {}; },
23+
source: $SOURCE,
24+
get agent() {
25+
throw new Test262Error('agent.* not yet supported.');
26+
}
27+
};

test/runify.js

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const hosts = [
3333
["hermes", { hostPath: makeHostPath("hermes") }],
3434
["jsshell", { hostPath: makeHostPath("sm") }],
3535
["jsc", { hostPath: makeHostPath("jsc") }],
36+
["libjs", { hostPath: "js" }], // Not provided by esvu
3637
["node", { hostPath: "node" }], // Not provided by esvu
3738
["qjs", { hostPath: makeHostPath("quickjs-run-test262") }],
3839
["xs", { hostPath: makeHostPath("xs") }],
@@ -125,7 +126,7 @@ hosts.forEach(function (record) {
125126
describe("Normal script evaluation", function () {
126127
describe("Code evaluation modes", () => {
127128
// As of 2021-05-04, hermes and xs fail these tests.
128-
if (["hermes", "xs"].includes(type)) {
129+
if (["hermes", "xs", "libjs"].includes(type)) {
129130
return;
130131
}
131132

@@ -283,6 +284,9 @@ hosts.forEach(function (record) {
283284
});
284285

285286
it("handles thrown custom Errors that don't have Error.prototype", async () => {
287+
if (["libjs"].includes(type)) {
288+
return;
289+
}
286290
const result = await agent.evalScript(stripIndent`
287291
function Foo2Error(msg) {
288292
this.message = msg;
@@ -355,7 +359,9 @@ hosts.forEach(function (record) {
355359
expect(values[4]).toBe("false");
356360
expect(values[5]).toBe("0");
357361
expect(values[6]).toBe("1");
358-
expect(values[7]).toBe("1.2");
362+
if (type !== "libjs") {
363+
expect(values[7]).toBe("1.2");
364+
}
359365
expect(values[8]).toBe("-1");
360366
});
361367

@@ -498,6 +504,7 @@ hosts.forEach(function (record) {
498504
"firefox",
499505
"graaljs",
500506
"hermes",
507+
"libjs",
501508
"chrome",
502509
"qjs",
503510
"remote",
@@ -559,7 +566,7 @@ hosts.forEach(function (record) {
559566

560567
describe("Realm evaluation", function () {
561568
it("can create new realms", async () => {
562-
if (["hermes"].includes(type)) {
569+
if (["hermes", "libjs"].includes(type)) {
563570
return;
564571
}
565572

@@ -584,7 +591,7 @@ hosts.forEach(function (record) {
584591
});
585592

586593
it("can eval in new realms", async () => {
587-
if (["hermes", "xs"].includes(type)) {
594+
if (["hermes", "xs", "libjs"].includes(type)) {
588595
return;
589596
}
590597

@@ -607,7 +614,7 @@ hosts.forEach(function (record) {
607614
});
608615

609616
it("can set globals in new realms", async () => {
610-
if (["hermes", "xs"].includes(type)) {
617+
if (["hermes", "xs", "libjs"].includes(type)) {
611618
return;
612619
}
613620

@@ -628,7 +635,7 @@ hosts.forEach(function (record) {
628635
});
629636

630637
it("can eval in new scripts", async () => {
631-
if (["hermes", "xs"].includes(type)) {
638+
if (["hermes", "xs", "libjs"].includes(type)) {
632639
return;
633640
}
634641

@@ -648,7 +655,7 @@ hosts.forEach(function (record) {
648655
});
649656

650657
it("returns errors from evaling in new script", async () => {
651-
if (["hermes", "engine262"].includes(type)) {
658+
if (["hermes", "engine262", "libjs"].includes(type)) {
652659
return;
653660
}
654661

@@ -663,7 +670,7 @@ hosts.forEach(function (record) {
663670
});
664671

665672
it("can eval lexical bindings in new scripts", async () => {
666-
if (["hermes"].includes(type)) {
673+
if (["hermes", "libjs"].includes(type)) {
667674
return;
668675
}
669676

@@ -683,7 +690,7 @@ hosts.forEach(function (record) {
683690
});
684691

685692
it("can set properties in new realms", async () => {
686-
if (["hermes"].includes(type)) {
693+
if (["hermes", "libjs"].includes(type)) {
687694
return;
688695
}
689696

@@ -706,7 +713,7 @@ hosts.forEach(function (record) {
706713
});
707714

708715
it("can access properties from new realms", async () => {
709-
if (["hermes"].includes(type)) {
716+
if (["hermes", "libjs"].includes(type)) {
710717
return;
711718
}
712719

@@ -752,7 +759,7 @@ hosts.forEach(function (record) {
752759
});
753760

754761
it("accepts destroy callbacks", async () => {
755-
if (["hermes", "xs"].includes(type)) {
762+
if (["hermes", "xs", "libjs"].includes(type)) {
756763
return;
757764
}
758765

@@ -771,7 +778,7 @@ hosts.forEach(function (record) {
771778
});
772779

773780
it("supports realm nesting", async () => {
774-
if (["hermes", "xs"].includes(type)) {
781+
if (["hermes", "xs", "libjs"].includes(type)) {
775782
return;
776783
}
777784

@@ -800,7 +807,7 @@ hosts.forEach(function (record) {
800807
});
801808

802809
it("observes correct cross-script interaction semantics", async () => {
803-
if (["engine262", "graaljs", "hermes", "xs"].includes(type)) {
810+
if (["engine262", "graaljs", "hermes", "libjs", "xs"].includes(type)) {
804811
return;
805812
}
806813

test/supported-hosts.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const supportedHostsMap = {
2222
javascriptcore: 'jsc',
2323
jsc: 'jsc',
2424
jsshell: 'jsshell',
25+
libjs: 'libjs',
2526
nashorn: 'nashorn',
2627
node: 'node',
2728
qjs: 'qjs',

0 commit comments

Comments
 (0)