Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[basic-failure.test262.html]
expected: OK
[Test]
expected: FAIL
4 changes: 4 additions & 0 deletions infrastructure/metadata/infrastructure/test262/basic.js.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[basic.test262.html]
expected: OK
[Test]
expected: PASS
4 changes: 4 additions & 0 deletions infrastructure/metadata/infrastructure/test262/error.js.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[error.test262.html]
expected: OK
[Test]
expected: FAIL
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[module-error.test262-module.html]
expected: ERROR
[Test]
expected: FAIL
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[module-failure.test262-module.html]
expected: OK
[Test]
expected: FAIL
4 changes: 4 additions & 0 deletions infrastructure/metadata/infrastructure/test262/module.js.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[module.test262-module.html]
expected: OK
[Test]
expected: PASS
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[negative-error.test262.html]
expected: ERROR
[Test]
expected: FAIL
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[negative-failure.test262.html]
expected: OK
[Test]
expected: FAIL
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[negative.test262.html]
expected: OK
[Test]
expected: PASS
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[strict-error.test262.strict.html]
expected: ERROR
[Test]
expected: FAIL
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[strict-failure.test262.strict.html]
expected: OK
[Test]
expected: FAIL
4 changes: 4 additions & 0 deletions infrastructure/metadata/infrastructure/test262/strict.js.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[strict.test262.html]
expected: OK
[Test]
expected: PASS
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[unexpected-error.test262.html]
expected: ERROR
[Test]
expected: FAIL
6 changes: 6 additions & 0 deletions infrastructure/test262/basic-failure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*---
description: A basic Test262 smoketest that fails
features: [Test262]
---*/

assert.sameValue(1, 2, "One should be two");
6 changes: 6 additions & 0 deletions infrastructure/test262/basic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*---
description: A basic Test262 smoketest
features: [Test262]
---*/

assert.sameValue(1, 1, "One should be one");
5 changes: 5 additions & 0 deletions infrastructure/test262/error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*---
description: A smoketest that throws a Test262Error
---*/

throw new Test262Error("This is a deliberate test failure.");
6 changes: 6 additions & 0 deletions infrastructure/test262/module-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*---
description: A module smoketest that throws an unexpected ReferenceError.
flags: [module]
---*/
import { a } from "./support/module-helper.js";
foo.bar();
6 changes: 6 additions & 0 deletions infrastructure/test262/module-failure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*---
description: A module smoketest that fails an assertion.
flags: [module]
---*/
import { a } from "./support/module-helper.js";
assert.sameValue(a, 2, "a should be 2 in module");
5 changes: 5 additions & 0 deletions infrastructure/test262/module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*---
description: A module smoketest
flags: [module]
---*/
import { a } from "./support/module-helper.js";
8 changes: 8 additions & 0 deletions infrastructure/test262/negative-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*---
description: A negative test that throws a different error than expected.
negative:
phase: runtime
type: TypeError
---*/

throw new RangeError();
6 changes: 6 additions & 0 deletions infrastructure/test262/negative-failure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*---
description: A negative smoketest that is expected to fail because it does not throw an error.
negative:
phase: runtime
type: Test262Error
---*/
7 changes: 7 additions & 0 deletions infrastructure/test262/negative.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*---
description: A negative smoketest
negative:
phase: runtime
type: Test262Error
---*/
throw new Test262Error();
6 changes: 6 additions & 0 deletions infrastructure/test262/strict-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*---
description: A strict mode smoketest that throws an unexpected ReferenceError.
flags: [onlyStrict]
---*/
"use strict";
foo.bar();
6 changes: 6 additions & 0 deletions infrastructure/test262/strict-failure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*---
description: A strict mode smoketest that fails an assertion.
flags: [onlyStrict]
---*/
"use strict";
assert.sameValue(1, 2, "One should be two in strict mode");
8 changes: 8 additions & 0 deletions infrastructure/test262/strict.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*---
description: A strict-mode smoketest from https://github.com/tc39/test262/blob/main/INTERPRETING.md
negative:
phase: parse
type: SyntaxError
---*/
$DONOTEVALUATE();
var a\u2E2F;
1 change: 1 addition & 0 deletions infrastructure/test262/support/module-helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const a = 1;
5 changes: 5 additions & 0 deletions infrastructure/test262/unexpected-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*---
description: A smoketest that throws an unexpected ReferenceError.
---*/

foo.bar();
2 changes: 2 additions & 0 deletions lint.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -841,3 +841,5 @@ PROMISE_REJECTS: wasm/core/js/harness/testharness.js

# Legitimate use of test_driver_internal
TEST DRIVER INTERNAL: resources/testdriver.js

*: third_party/test262/*
173 changes: 173 additions & 0 deletions resources/test262/harness-adapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
function installAPI(global) {
global.$262 = {
createRealm: function() {
var iframe = global.document.createElement('iframe');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific reason to use var here and elsewhere? I think we're definitely OK with let/const these days.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just adapted to the style elsewhere. If that is not needed, even better.

iframe.style.cssText = 'display: none';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
iframe.style.cssText = 'display: none';
iframe.style.display = 'none';

perhaps, although I wonder if we really want to always default to None.

iframe.src = ''; // iframeSrc;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this line/comment for?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I have not written this part I am not fully sure. What it does is set the src to the same document as the parent page. This does not look like what we want. @jcscottiii can we try what happens if we just remove it?

if (global.document.body === null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels potentially surprising, because it means that something like

<html>
<script>
let realm = $262.createRealm();
</script>
<meta name="example" content="test">
<body>
[…]

is going to end up with the <meta> element in the . Do we actually need the capacity to handle both the cases where there is and isn't already a ` here?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We just need a place to insert the iframes. If you ensure all templates have a body that should be fine too.

global.document.body = global.document.createElement('body');
}
global.document.body.appendChild(iframe);
return installAPI(iframe.contentWindow);
},
evalScript: function(src) {
var script = global.document.createElement('script');
script.text = src;
window.__test262_evalScript_error_ = undefined;
global.document.head.appendChild(script);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific reason it has to go in the head? It's not totally clear what invariants we're trying to maintain about the DOM.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume it could go anywhere in the document.

// Errors in the above appendChild bubble up to the global error handler.
// Our testharnes-client.js stashes them in a global var for rethrowing.
if (window.__test262_evalScript_error_) {
err = window.__test262_evalScript_error_;
window.__test262_evalScript_error_ = undefined;
throw err;
}
},
detachArrayBuffer: function(buffer) {
if (typeof postMessage !== 'function') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When can this actually happen, and is it worth having a specific error message for?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This happens if the environment does not support workers. I guess on the web that should never happen (?), so we can probably remove that case.

throw new Error('No method available to detach an ArrayBuffer');
} else {
postMessage(null, '*', [buffer]);
/*
See
https://html.spec.whatwg.org/multipage/comms.html#dom-window-postmessage
which calls
https://html.spec.whatwg.org/multipage/infrastructure.html#structuredclonewithtransfer
which calls
https://html.spec.whatwg.org/multipage/infrastructure.html#transfer-abstract-op
which calls the DetachArrayBuffer abstract operation
https://tc39.github.io/ecma262/#sec-detacharraybuffer
*/
}
},
gc: function() {
if (typeof gc !== 'function') {
throw new Error('No method available to invoke a GC');
}
gc();
},
AbstractModuleSource: function() {
throw new Error('AbstractModuleSource not available');
},
agent: (function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to have some documentation of the high level protocol being implemented, or at least a link to something in test262 which explains it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var workers = [];
var i32a = null;
var pendingReports = [];

// Agents call Atomics.wait on this location to sleep.
var SLEEP_LOC = 0;
// 1 if the started worker is ready, 0 otherwise.
var START_LOC = 1;
// The number of workers that have received the broadcast.
var BROADCAST_LOC = 2;
// Each worker has a count of outstanding reports; worker N uses memory
// location [WORKER_REPORT_LOC + N].
var WORKER_REPORT_LOC = 3;

function workerScript(script) {
return `
var index;
var i32a = null;
var broadcasts = [];
var pendingReceiver = null;

function handleBroadcast() {
if (pendingReceiver && broadcasts.length > 0) {
pendingReceiver.apply(null, broadcasts.shift());
pendingReceiver = null;
}
};

var onmessage = function({data:msg}) {
switch (msg.kind) {
case 'start':
i32a = msg.i32a;
index = msg.index;
(0, eval)(\`${script}\`);
break;

case 'broadcast':
Atomics.add(i32a, ${BROADCAST_LOC}, 1);
broadcasts.push([msg.sab, msg.id]);
handleBroadcast();
break;
}
};

var $262 = {
agent: {
receiveBroadcast(receiver) {
pendingReceiver = receiver;
handleBroadcast();
},

report(msg) {
postMessage(String(msg));
Atomics.add(i32a, ${WORKER_REPORT_LOC} + index, 1);
},

sleep(s) { Atomics.wait(i32a, ${SLEEP_LOC}, 0, s); },

leaving() {},

monotonicNow() {
return performance.now();
}
}
};`;
}

var agent = {
start(script) {
if (i32a === null) {
i32a = new Int32Array(new SharedArrayBuffer(256));
}
var w = new Worker(workerScript(script), {type: 'string'});
w.index = workers.length;
w.postMessage({kind: 'start', i32a: i32a, index: w.index});
workers.push(w);
},

broadcast(sab, id) {
if (!(sab instanceof SharedArrayBuffer)) {
throw new TypeError('sab must be a SharedArrayBuffer.');
}

Atomics.store(i32a, BROADCAST_LOC, 0);

for (var w of workers) {
w.postMessage({kind: 'broadcast', sab: sab, id: id|0});
}

while (Atomics.load(i32a, BROADCAST_LOC) != workers.length) {}
},

getReport() {
for (var w of workers) {
while (Atomics.load(i32a, WORKER_REPORT_LOC + w.index) > 0) {
pendingReports.push(w.getMessage());
Atomics.sub(i32a, WORKER_REPORT_LOC + w.index, 1);
}
}

return pendingReports.shift() || null;
},

sleep(s) { Atomics.wait(i32a, SLEEP_LOC, 0, s); },

monotonicNow() {
return performance.now();
}
};
return agent;

})(),
global: global
};
global.$DONE = function() {}

return global.$262;
}

installAPI(window);

Loading