Skip to content
Draft
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
58 changes: 58 additions & 0 deletions .github/workflows/update-test262-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Update Test262 tests

on:
# Trigger at every Sunday UTC noon, or manually.
schedule:
- cron: '0 12 * * 0'
workflow_dispatch:

jobs:
update-test262:
runs-on: ubuntu-24.04
steps:
- name: Checkout WPT repo
uses: actions/checkout@v4
with:
path: wpt
- name: Checkout Test262 repo
uses: actions/checkout@v4
with:
repository: tc39/test262
path: test262-spec
- name: Copy Test262 tests to WPT
run: |
LATEST_SHA=$(git -C test262-spec rev-parse HEAD)
echo "Latest remote Test262 SHA: $LATEST_SHA"

mkdir -p wpt/third_party/test262/test/
mkdir -p wpt/third_party/test262/harness/
rsync -a --delete test262-spec/test/ wpt/third_party/test262/test/
rsync -a --delete test262-spec/harness/ wpt/third_party/test262/harness/
printf "[test262]\nsource = \"https://github.com/tc39/test262\"\nrev = \"${LATEST_SHA}\"\n" > wpt/third_party/test262/vendored.toml
- name: Commit changes
id: commit
continue-on-error: true
run: |
cd wpt
export BRANCH_NAME="$BRANCH_PREFIX-$(date +'%Y%m%d%H%M%S')"
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
git config user.name "$GIT_AUTHOR_NAME"
git config user.email "$GIT_AUTHOR_EMAIL"
git checkout -B $BRANCH_NAME
git add third_party/test262/
git commit -m "$COMMIT_TITLE"
env:
GIT_AUTHOR_NAME: "wpt-pr-bot"
GIT_AUTHOR_EMAIL: "[email protected]"
BRANCH_PREFIX: "test262-update"
COMMIT_TITLE: "Update Test262 tests"
- name: Create PR
if: ${{ steps.commit.outcome == 'success' }}
run: |
cd wpt
git push --set-upstream origin $BRANCH_NAME
gh pr create --title "$COMMIT_TITLE" --body "$PR_BODY"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMMIT_TITLE: "Update Test262 tests"
PR_BODY: "Scheduled weekly update auto-generated by the '${{ github.workflow }}' workflow."
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');
iframe.style.cssText = 'display: none';
iframe.src = ''; // iframeSrc;
if (global.document.body === null) {
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);
// 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') {
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 () {
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