-
Notifications
You must be signed in to change notification settings - Fork 3.6k
feat(runner): Integrate Test262 execution with wptrunner and add smoke tests [pt 3/5] #56842
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feat/test262-serve-handler
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| [basic-failure.test262.html] | ||
| expected: OK | ||
| [Test] | ||
| expected: FAIL |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| [basic.test262.html] | ||
| expected: OK | ||
| [Test] | ||
| expected: PASS |
| 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 |
| 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 |
| 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 |
| 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"); |
| 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"); |
| 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."); |
| 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(); |
| 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"); |
| 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"; |
| 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(); |
| 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 | ||
| ---*/ |
| 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(); |
| 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(); |
| 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"); |
| 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; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export const a = 1; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| /*--- | ||
| description: A smoketest that throws an unexpected ReferenceError. | ||
| ---*/ | ||
|
|
||
| foo.bar(); |
| 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'; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
perhaps, although I wonder if we really want to always default to None. |
||||||
| iframe.src = ''; // iframeSrc; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this line/comment for? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels potentially surprising, because it means that something like is going to end up with the There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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') { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 () { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. The documentation is at: https://chromium.googlesource.com/external/github.com/tc39/test262/+/HEAD/INTERPRETING.md |
||||||
| 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); | ||||||
|
|
||||||
There was a problem hiding this comment.
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
varhere and elsewhere? I think we're definitely OK with let/const these days.There was a problem hiding this comment.
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.