Tests: Update WPT testharness.js to the most recent version
Some checks are pending
CI / macOS, arm64, Sanitizer_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, Clang (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run

This ensures that our test output looks the same as that shown in the
WPT runner.
This commit is contained in:
Tim Ledbetter 2025-06-21 13:07:26 +01:00 committed by Jelle Raaijmakers
commit dede92aa78
Notes: github-actions[bot] 2025-06-21 12:59:20 +00:00
2 changed files with 168 additions and 101 deletions

View file

@ -53,7 +53,7 @@ Pass Explicit value undefined for type i64
Pass Explicit value true for type i64 Pass Explicit value true for type i64
Pass Explicit value false for type i64 Pass Explicit value false for type i64
Pass Explicit value "3" for type i64 Pass Explicit value "3" for type i64
Pass Explicit value bigint "123" for type i64 Pass Explicit value 123n for type i64
Pass Explicit value object with toString returning string for type i64 Pass Explicit value object with toString returning string for type i64
Pass Explicit value object with valueOf returning string for type i64 Pass Explicit value object with valueOf returning string for type i64
Pass Explicit value object with toString returning bigint for type i64 Pass Explicit value object with toString returning bigint for type i64

View file

@ -89,7 +89,7 @@
status: harness_status.structured_clone(), status: harness_status.structured_clone(),
asserts: asserts.map(assert => assert.structured_clone())}); asserts: asserts.map(assert => assert.structured_clone())});
}] }]
} };
on_event(window, 'load', function() { on_event(window, 'load', function() {
setTimeout(() => { setTimeout(() => {
@ -204,7 +204,7 @@
} }
}); });
this.message_events = new_events; this.message_events = new_events;
} };
WindowTestEnvironment.prototype.next_default_test_name = function() { WindowTestEnvironment.prototype.next_default_test_name = function() {
var suffix = this.name_counter > 0 ? " " + this.name_counter : ""; var suffix = this.name_counter > 0 ? " " + this.name_counter : "";
@ -226,8 +226,8 @@
WindowTestEnvironment.prototype.test_timeout = function() { WindowTestEnvironment.prototype.test_timeout = function() {
var metas = document.getElementsByTagName("meta"); var metas = document.getElementsByTagName("meta");
for (var i = 0; i < metas.length; i++) { for (var i = 0; i < metas.length; i++) {
if (metas[i].name == "timeout") { if (metas[i].name === "timeout") {
if (metas[i].content == "long") { if (metas[i].content === "long") {
return settings.harness_timeout.long; return settings.harness_timeout.long;
} }
break; break;
@ -488,7 +488,7 @@
this.all_loaded = false; this.all_loaded = false;
this.on_loaded_callback = null; this.on_loaded_callback = null;
Promise.resolve().then(function() { Promise.resolve().then(function() {
this.all_loaded = true this.all_loaded = true;
if (this.on_loaded_callback) { if (this.on_loaded_callback) {
this.on_loaded_callback(); this.on_loaded_callback();
} }
@ -571,7 +571,7 @@
// The worker object may be from another execution context, // The worker object may be from another execution context,
// so do not use instanceof here. // so do not use instanceof here.
return 'ServiceWorker' in global_scope && return 'ServiceWorker' in global_scope &&
Object.prototype.toString.call(worker) == '[object ServiceWorker]'; Object.prototype.toString.call(worker) === '[object ServiceWorker]';
} }
var seen_func_name = Object.create(null); var seen_func_name = Object.create(null);
@ -818,7 +818,7 @@
return bring_promise_to_current_realm(promise) return bring_promise_to_current_realm(promise)
.then(test.unreached_func("Should have rejected: " + description)) .then(test.unreached_func("Should have rejected: " + description))
.catch(function(e) { .catch(function(e) {
assert_throws_js_impl(constructor, function() { throw e }, assert_throws_js_impl(constructor, function() { throw e; },
description, "promise_rejects_js"); description, "promise_rejects_js");
}); });
} }
@ -870,7 +870,7 @@
return bring_promise_to_current_realm(promise) return bring_promise_to_current_realm(promise)
.then(test.unreached_func("Should have rejected: " + description)) .then(test.unreached_func("Should have rejected: " + description))
.catch(function(e) { .catch(function(e) {
assert_throws_dom_impl(type, function() { throw e }, description, assert_throws_dom_impl(type, function() { throw e; }, description,
"promise_rejects_dom", constructor); "promise_rejects_dom", constructor);
}); });
} }
@ -889,7 +889,7 @@
return bring_promise_to_current_realm(promise) return bring_promise_to_current_realm(promise)
.then(test.unreached_func("Should have rejected: " + description)) .then(test.unreached_func("Should have rejected: " + description))
.catch(function(e) { .catch(function(e) {
assert_throws_exactly_impl(exception, function() { throw e }, assert_throws_exactly_impl(exception, function() { throw e; },
description, "promise_rejects_exactly"); description, "promise_rejects_exactly");
}); });
} }
@ -915,7 +915,7 @@
*/ */
function EventWatcher(test, watchedNode, eventTypes, timeoutPromise) function EventWatcher(test, watchedNode, eventTypes, timeoutPromise)
{ {
if (typeof eventTypes == 'string') { if (typeof eventTypes === 'string') {
eventTypes = [eventTypes]; eventTypes = [eventTypes];
} }
@ -980,7 +980,7 @@
if (waitingFor) { if (waitingFor) {
return Promise.reject('Already waiting for an event or events'); return Promise.reject('Already waiting for an event or events');
} }
if (typeof types == 'string') { if (typeof types === 'string') {
types = [types]; types = [types];
} }
if (options && options.record && options.record === 'all') { if (options && options.record && options.record === 'all') {
@ -995,7 +995,7 @@
// This should always fail, otherwise we should have // This should always fail, otherwise we should have
// resolved the promise. // resolved the promise.
assert_true(waitingFor.types.length == 0, assert_true(waitingFor.types.length === 0,
'Timed out waiting for ' + waitingFor.types.join(', ')); 'Timed out waiting for ' + waitingFor.types.join(', '));
var result = recordedEvents; var result = recordedEvents;
recordedEvents = null; recordedEvents = null;
@ -1019,13 +1019,13 @@
/** /**
* Stop listening for events * Stop listening for events
*/ */
function stop_watching() { this.stop_watching = function() {
for (var i = 0; i < eventTypes.length; i++) { for (var i = 0; i < eventTypes.length; i++) {
watchedNode.removeEventListener(eventTypes[i], eventHandler, false); watchedNode.removeEventListener(eventTypes[i], eventHandler, false);
} }
}; };
test._add_cleanup(stop_watching); test._add_cleanup(this.stop_watching);
return this; return this;
} }
@ -1102,7 +1102,7 @@
{ {
if (typeof func !== "function") { if (typeof func !== "function") {
tests.set_status(tests.status.ERROR, tests.set_status(tests.status.ERROR,
"promise_test invoked without a function"); "`promise_setup` invoked without a function");
tests.complete(); tests.complete();
return; return;
} }
@ -1338,6 +1338,15 @@
"0xffff": "uffff", "0xffff": "uffff",
}; };
const formatEscapeMap = {
"\\": "\\\\",
'"': '\\"'
};
for (const p in replacements) {
formatEscapeMap[String.fromCharCode(p)] = "\\" + replacements[p];
}
const formatEscapePattern = new RegExp(`[${Object.keys(formatEscapeMap).map(k => k === "\\" ? "\\\\" : k).join("")}]`, "g");
/** /**
* Convert a value to a nice, human-readable string * Convert a value to a nice, human-readable string
* *
@ -1388,12 +1397,7 @@
switch (typeof val) { switch (typeof val) {
case "string": case "string":
val = val.replace(/\\/g, "\\\\"); return '"' + val.replace(formatEscapePattern, match => formatEscapeMap[match]) + '"';
for (var p in replacements) {
var replace = "\\" + replacements[p];
val = val.replace(RegExp(String.fromCharCode(p), "g"), replace);
}
return '"' + val.replace(/"/g, '\\"') + '"';
case "boolean": case "boolean":
case "undefined": case "undefined":
return String(val); return String(val);
@ -1404,6 +1408,8 @@
return "-0"; return "-0";
} }
return String(val); return String(val);
case "bigint":
return String(val) + 'n';
case "object": case "object":
if (val === null) { if (val === null) {
return "null"; return "null";
@ -1427,11 +1433,11 @@
case Node.COMMENT_NODE: case Node.COMMENT_NODE:
return "Comment node <!--" + truncate(val.data, 60) + "-->"; return "Comment node <!--" + truncate(val.data, 60) + "-->";
case Node.DOCUMENT_NODE: case Node.DOCUMENT_NODE:
return "Document node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children"); return "Document node with " + val.childNodes.length + (val.childNodes.length === 1 ? " child" : " children");
case Node.DOCUMENT_TYPE_NODE: case Node.DOCUMENT_TYPE_NODE:
return "DocumentType node"; return "DocumentType node";
case Node.DOCUMENT_FRAGMENT_NODE: case Node.DOCUMENT_FRAGMENT_NODE:
return "DocumentFragment node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children"); return "DocumentFragment node with " + val.childNodes.length + (val.childNodes.length === 1 ? " child" : " children");
default: default:
return "Node object of unknown type"; return "Node object of unknown type";
} }
@ -1775,20 +1781,25 @@
/** /**
* Assert that ``actual`` is a number less than ``expected``. * Assert that ``actual`` is a number less than ``expected``.
* *
* @param {number} actual - Test value. * @param {number|bigint} actual - Test value.
* @param {number} expected - Number that ``actual`` must be less than. * @param {number|bigint} expected - Value that ``actual`` must be less than.
* @param {string} [description] - Description of the condition being tested. * @param {string} [description] - Description of the condition being tested.
*/ */
function assert_less_than(actual, expected, description) function assert_less_than(actual, expected, description)
{ {
/* /*
* Test if a primitive number is less than another * Test if a primitive number (or bigint) is less than another
*/ */
assert(typeof actual === "number", assert(typeof actual === "number" || typeof actual === "bigint",
"assert_less_than", description, "assert_less_than", description,
"expected a number but got a ${type_actual}", "expected a number but got a ${type_actual}",
{type_actual:typeof actual}); {type_actual:typeof actual});
assert(typeof actual === typeof expected,
"assert_less_than", description,
"expected a ${type_expected} but got a ${type_actual}",
{type_expected:typeof expected, type_actual:typeof actual});
assert(actual < expected, assert(actual < expected,
"assert_less_than", description, "assert_less_than", description,
"expected a number less than ${expected} but got ${actual}", "expected a number less than ${expected} but got ${actual}",
@ -1799,20 +1810,25 @@
/** /**
* Assert that ``actual`` is a number greater than ``expected``. * Assert that ``actual`` is a number greater than ``expected``.
* *
* @param {number} actual - Test value. * @param {number|bigint} actual - Test value.
* @param {number} expected - Number that ``actual`` must be greater than. * @param {number|bigint} expected - Value that ``actual`` must be greater than.
* @param {string} [description] - Description of the condition being tested. * @param {string} [description] - Description of the condition being tested.
*/ */
function assert_greater_than(actual, expected, description) function assert_greater_than(actual, expected, description)
{ {
/* /*
* Test if a primitive number is greater than another * Test if a primitive number (or bigint) is greater than another
*/ */
assert(typeof actual === "number", assert(typeof actual === "number" || typeof actual === "bigint",
"assert_greater_than", description, "assert_greater_than", description,
"expected a number but got a ${type_actual}", "expected a number but got a ${type_actual}",
{type_actual:typeof actual}); {type_actual:typeof actual});
assert(typeof actual === typeof expected,
"assert_greater_than", description,
"expected a ${type_expected} but got a ${type_actual}",
{type_expected:typeof expected, type_actual:typeof actual});
assert(actual > expected, assert(actual > expected,
"assert_greater_than", description, "assert_greater_than", description,
"expected a number greater than ${expected} but got ${actual}", "expected a number greater than ${expected} but got ${actual}",
@ -1824,21 +1840,31 @@
* Assert that ``actual`` is a number greater than ``lower`` and less * Assert that ``actual`` is a number greater than ``lower`` and less
* than ``upper`` but not equal to either. * than ``upper`` but not equal to either.
* *
* @param {number} actual - Test value. * @param {number|bigint} actual - Test value.
* @param {number} lower - Number that ``actual`` must be greater than. * @param {number|bigint} lower - Value that ``actual`` must be greater than.
* @param {number} upper - Number that ``actual`` must be less than. * @param {number|bigint} upper - Value that ``actual`` must be less than.
* @param {string} [description] - Description of the condition being tested. * @param {string} [description] - Description of the condition being tested.
*/ */
function assert_between_exclusive(actual, lower, upper, description) function assert_between_exclusive(actual, lower, upper, description)
{ {
/* /*
* Test if a primitive number is between two others * Test if a primitive number (or bigint) is between two others
*/ */
assert(typeof actual === "number", assert(typeof lower === typeof upper,
"assert_between_exclusive", description,
"expected lower (${type_lower}) and upper (${type_upper}) types to match (test error)",
{type_lower:typeof lower, type_upper:typeof upper});
assert(typeof actual === "number" || typeof actual === "bigint",
"assert_between_exclusive", description, "assert_between_exclusive", description,
"expected a number but got a ${type_actual}", "expected a number but got a ${type_actual}",
{type_actual:typeof actual}); {type_actual:typeof actual});
assert(typeof actual === typeof lower,
"assert_between_exclusive", description,
"expected a ${type_lower} but got a ${type_actual}",
{type_lower:typeof lower, type_actual:typeof actual});
assert(actual > lower && actual < upper, assert(actual > lower && actual < upper,
"assert_between_exclusive", description, "assert_between_exclusive", description,
"expected a number greater than ${lower} " + "expected a number greater than ${lower} " +
@ -1850,21 +1876,26 @@
/** /**
* Assert that ``actual`` is a number less than or equal to ``expected``. * Assert that ``actual`` is a number less than or equal to ``expected``.
* *
* @param {number} actual - Test value. * @param {number|bigint} actual - Test value.
* @param {number} expected - Number that ``actual`` must be less * @param {number|bigint} expected - Value that ``actual`` must be less
* than or equal to. * than or equal to.
* @param {string} [description] - Description of the condition being tested. * @param {string} [description] - Description of the condition being tested.
*/ */
function assert_less_than_equal(actual, expected, description) function assert_less_than_equal(actual, expected, description)
{ {
/* /*
* Test if a primitive number is less than or equal to another * Test if a primitive number (or bigint) is less than or equal to another
*/ */
assert(typeof actual === "number", assert(typeof actual === "number" || typeof actual === "bigint",
"assert_less_than_equal", description, "assert_less_than_equal", description,
"expected a number but got a ${type_actual}", "expected a number but got a ${type_actual}",
{type_actual:typeof actual}); {type_actual:typeof actual});
assert(typeof actual === typeof expected,
"assert_less_than_equal", description,
"expected a ${type_expected} but got a ${type_actual}",
{type_expected:typeof expected, type_actual:typeof actual});
assert(actual <= expected, assert(actual <= expected,
"assert_less_than_equal", description, "assert_less_than_equal", description,
"expected a number less than or equal to ${expected} but got ${actual}", "expected a number less than or equal to ${expected} but got ${actual}",
@ -1875,21 +1906,26 @@
/** /**
* Assert that ``actual`` is a number greater than or equal to ``expected``. * Assert that ``actual`` is a number greater than or equal to ``expected``.
* *
* @param {number} actual - Test value. * @param {number|bigint} actual - Test value.
* @param {number} expected - Number that ``actual`` must be greater * @param {number|bigint} expected - Value that ``actual`` must be greater
* than or equal to. * than or equal to.
* @param {string} [description] - Description of the condition being tested. * @param {string} [description] - Description of the condition being tested.
*/ */
function assert_greater_than_equal(actual, expected, description) function assert_greater_than_equal(actual, expected, description)
{ {
/* /*
* Test if a primitive number is greater than or equal to another * Test if a primitive number (or bigint) is greater than or equal to another
*/ */
assert(typeof actual === "number", assert(typeof actual === "number" || typeof actual === "bigint",
"assert_greater_than_equal", description, "assert_greater_than_equal", description,
"expected a number but got a ${type_actual}", "expected a number but got a ${type_actual}",
{type_actual:typeof actual}); {type_actual:typeof actual});
assert(typeof actual === typeof expected,
"assert_greater_than_equal", description,
"expected a ${type_expected} but got a ${type_actual}",
{type_expected:typeof expected, type_actual:typeof actual});
assert(actual >= expected, assert(actual >= expected,
"assert_greater_than_equal", description, "assert_greater_than_equal", description,
"expected a number greater than or equal to ${expected} but got ${actual}", "expected a number greater than or equal to ${expected} but got ${actual}",
@ -1901,21 +1937,31 @@
* Assert that ``actual`` is a number greater than or equal to ``lower`` and less * Assert that ``actual`` is a number greater than or equal to ``lower`` and less
* than or equal to ``upper``. * than or equal to ``upper``.
* *
* @param {number} actual - Test value. * @param {number|bigint} actual - Test value.
* @param {number} lower - Number that ``actual`` must be greater than or equal to. * @param {number|bigint} lower - Value that ``actual`` must be greater than or equal to.
* @param {number} upper - Number that ``actual`` must be less than or equal to. * @param {number|bigint} upper - Value that ``actual`` must be less than or equal to.
* @param {string} [description] - Description of the condition being tested. * @param {string} [description] - Description of the condition being tested.
*/ */
function assert_between_inclusive(actual, lower, upper, description) function assert_between_inclusive(actual, lower, upper, description)
{ {
/* /*
* Test if a primitive number is between to two others or equal to either of them * Test if a primitive number (or bigint) is between to two others or equal to either of them
*/ */
assert(typeof actual === "number", assert(typeof lower === typeof upper,
"assert_between_inclusive", description,
"expected lower (${type_lower}) and upper (${type_upper}) types to match (test error)",
{type_lower:typeof lower, type_upper:typeof upper});
assert(typeof actual === "number" || typeof actual === "bigint",
"assert_between_inclusive", description, "assert_between_inclusive", description,
"expected a number but got a ${type_actual}", "expected a number but got a ${type_actual}",
{type_actual:typeof actual}); {type_actual:typeof actual});
assert(typeof actual === typeof lower,
"assert_between_inclusive", description,
"expected a ${type_lower} but got a ${type_actual}",
{type_lower:typeof lower, type_actual:typeof actual});
assert(actual >= lower && actual <= upper, assert(actual >= lower && actual <= upper,
"assert_between_inclusive", description, "assert_between_inclusive", description,
"expected a number greater than or equal to ${lower} " + "expected a number greater than or equal to ${lower} " +
@ -2040,30 +2086,46 @@
/** /**
* Assert that ``object`` has a property named ``property_name`` and that the property is readonly. * Assert that ``object`` has a property named ``property_name`` and that the property is not writable or has no setter.
* *
* Note: The implementation tries to update the named property, so * @param {Object} object - Object that should have the given (not necessarily own) property.
* any side effects of updating will be triggered. Users are
* encouraged to instead inspect the property descriptor of ``property_name`` on ``object``.
*
* @param {Object} object - Object that should have the given property in its prototype chain.
* @param {string} property_name - Expected property name. * @param {string} property_name - Expected property name.
* @param {string} [description] - Description of the condition being tested. * @param {string} [description] - Description of the condition being tested.
*/ */
function assert_readonly(object, property_name, description) function assert_readonly(object, property_name, description)
{ {
var initial_value = object[property_name]; assert(property_name in object,
try { "assert_readonly", description,
//Note that this can have side effects in the case where "property ${p} not found",
//the property has PutForwards {p:property_name});
object[property_name] = initial_value + "a"; //XXX use some other value here?
assert(same_value(object[property_name], initial_value), let desc;
"assert_readonly", description, while (object && (desc = Object.getOwnPropertyDescriptor(object, property_name)) === undefined) {
"changing property ${p} succeeded", object = Object.getPrototypeOf(object);
{p:property_name}); }
} finally {
object[property_name] = initial_value; assert(desc !== undefined,
} "assert_readonly", description,
"could not find a descriptor for property ${p}",
{p:property_name});
if (desc.hasOwnProperty("value")) {
// We're a data property descriptor
assert(desc.writable === false, "assert_readonly", description,
"descriptor [[Writable]] expected false got ${actual}", {actual:desc.writable});
} else if (desc.hasOwnProperty("get") || desc.hasOwnProperty("set")) {
// We're an accessor property descriptor
assert(desc.set === undefined, "assert_readonly", description,
"property ${p} is an accessor property with a [[Set]] attribute, cannot test readonly-ness",
{p:property_name});
} else {
// We're a generic property descriptor
// This shouldn't happen, because Object.getOwnPropertyDescriptor
// forwards the return value of [[GetOwnProperty]] (P), which must
// be a fully populated Property Descriptor or Undefined.
assert(false, "assert_readonly", description,
"Object.getOwnPropertyDescriptor must return a fully populated property descriptor");
}
} }
expose_assert(assert_readonly, "assert_readonly"); expose_assert(assert_readonly, "assert_readonly");
@ -2109,7 +2171,7 @@
{func:func}); {func:func});
// Basic sanity-check on the passed-in constructor // Basic sanity-check on the passed-in constructor
assert(typeof constructor == "function", assert(typeof constructor === "function",
assertion_type, description, assertion_type, description,
"${constructor} is not a constructor", "${constructor} is not a constructor",
{constructor:constructor}); {constructor:constructor});
@ -2184,7 +2246,7 @@
assert(maybeDescription === undefined, assert(maybeDescription === undefined,
"Too many args passed to no-constructor version of assert_throws_dom, or accidentally explicitly passed undefined"); "Too many args passed to no-constructor version of assert_throws_dom, or accidentally explicitly passed undefined");
} }
assert_throws_dom_impl(type, func, description, "assert_throws_dom", constructor) assert_throws_dom_impl(type, func, description, "assert_throws_dom", constructor);
} }
expose_assert(assert_throws_dom, "assert_throws_dom"); expose_assert(assert_throws_dom, "assert_throws_dom");
@ -2217,8 +2279,8 @@
{func:func}); {func:func});
// Sanity-check our type // Sanity-check our type
assert(typeof type == "number" || assert(typeof type === "number" ||
typeof type == "string", typeof type === "string",
assertion_type, description, assertion_type, description,
"${type} is not a number or string", "${type} is not a number or string",
{type:type}); {type:type});
@ -2447,7 +2509,7 @@
function assert_implements(condition, description) { function assert_implements(condition, description) {
assert(!!condition, "assert_implements", description); assert(!!condition, "assert_implements", description);
} }
expose_assert(assert_implements, "assert_implements") expose_assert(assert_implements, "assert_implements");
/** /**
* Assert that an optional feature is implemented, based on a 'truthy' condition. * Assert that an optional feature is implemented, based on a 'truthy' condition.
@ -2561,11 +2623,11 @@
2: "Timeout", 2: "Timeout",
3: "Not Run", 3: "Not Run",
4: "Optional Feature Unsupported", 4: "Optional Feature Unsupported",
} };
Test.prototype.format_status = function() { Test.prototype.format_status = function() {
return this.status_formats[this.status]; return this.status_formats[this.status];
} };
Test.prototype.structured_clone = function() Test.prototype.structured_clone = function()
{ {
@ -2875,7 +2937,7 @@
return new Promise(resolve => { return new Promise(resolve => {
this.step_wait_func(cond, resolve, description, timeout, interval); this.step_wait_func(cond, resolve, description, timeout, interval);
}); });
} };
/* /*
* Private method for registering cleanup functions. `testharness.js` * Private method for registering cleanup functions. `testharness.js`
@ -3108,7 +3170,7 @@
throw new Error("AbortController is not supported in this browser"); throw new Error("AbortController is not supported in this browser");
} }
return this._abortController.signal; return this._abortController.signal;
} };
/** /**
* A RemoteTest object mirrors a Test object on a remote worker. The * A RemoteTest object mirrors a Test object on a remote worker. The
@ -3184,11 +3246,11 @@
function(callback) { function(callback) {
callback(); callback();
}); });
} };
RemoteTest.prototype.format_status = function() { RemoteTest.prototype.format_status = function() {
return Test.prototype.status_formats[this.status]; return Test.prototype.status_formats[this.status];
} };
/* /*
* A RemoteContext listens for test events from a remote test context, such * A RemoteContext listens for test events from a remote test context, such
@ -3460,7 +3522,7 @@
this.all_done_callbacks = []; this.all_done_callbacks = [];
this.hide_test_state = false; this.hide_test_state = false;
this.pending_remotes = []; this.remotes = [];
this.current_test = null; this.current_test = null;
this.asserts_run = []; this.asserts_run = [];
@ -3502,26 +3564,26 @@
for (var p in properties) { for (var p in properties) {
if (properties.hasOwnProperty(p)) { if (properties.hasOwnProperty(p)) {
var value = properties[p]; var value = properties[p];
if (p == "allow_uncaught_exception") { if (p === "allow_uncaught_exception") {
this.allow_uncaught_exception = value; this.allow_uncaught_exception = value;
} else if (p == "explicit_done" && value) { } else if (p === "explicit_done" && value) {
this.wait_for_finish = true; this.wait_for_finish = true;
} else if (p == "explicit_timeout" && value) { } else if (p === "explicit_timeout" && value) {
this.timeout_length = null; this.timeout_length = null;
if (this.timeout_id) if (this.timeout_id)
{ {
clearTimeout(this.timeout_id); clearTimeout(this.timeout_id);
} }
} else if (p == "single_test" && value) { } else if (p === "single_test" && value) {
this.set_file_is_test(); this.set_file_is_test();
} else if (p == "timeout_multiplier") { } else if (p === "timeout_multiplier") {
this.timeout_multiplier = value; this.timeout_multiplier = value;
if (this.timeout_length) { if (this.timeout_length) {
this.timeout_length *= this.timeout_multiplier; this.timeout_length *= this.timeout_multiplier;
} }
} else if (p == "hide_test_state") { } else if (p === "hide_test_state") {
this.hide_test_state = value; this.hide_test_state = value;
} else if (p == "output") { } else if (p === "output") {
this.output = value; this.output = value;
} else if (p === "debug") { } else if (p === "debug") {
settings.debug = value; settings.debug = value;
@ -3614,11 +3676,14 @@
Tests.prototype.push = function(test) Tests.prototype.push = function(test)
{ {
if (this.phase === this.phases.COMPLETE) {
return;
}
if (this.phase < this.phases.HAVE_TESTS) { if (this.phase < this.phases.HAVE_TESTS) {
this.start(); this.start();
} }
this.num_pending++; this.num_pending++;
test.index = this.tests.push(test); test.index = this.tests.push(test) - 1;
this.notify_test_state(test); this.notify_test_state(test);
}; };
@ -3631,11 +3696,11 @@
}; };
Tests.prototype.all_done = function() { Tests.prototype.all_done = function() {
return (this.tests.length > 0 || this.pending_remotes.length > 0) && return (this.tests.length > 0 || this.remotes.length > 0) &&
test_environment.all_loaded && test_environment.all_loaded &&
(this.num_pending === 0 || this.is_aborted) && !this.wait_for_finish && (this.num_pending === 0 || this.is_aborted) && !this.wait_for_finish &&
!this.processing_callbacks && !this.processing_callbacks &&
!this.pending_remotes.some(function(w) { return w.running; }); !this.remotes.some(function(w) { return w.running; });
}; };
Tests.prototype.start = function() { Tests.prototype.start = function() {
@ -3704,7 +3769,8 @@
function(test, testDone) function(test, testDone)
{ {
if (test.phase === test.phases.INITIAL) { if (test.phase === test.phases.INITIAL) {
test.phase = test.phases.COMPLETE; test.phase = test.phases.HAS_RESULT;
test.done();
testDone(); testDone();
} else { } else {
add_test_done_callback(test, testDone); add_test_done_callback(test, testDone);
@ -3715,14 +3781,14 @@
}; };
Tests.prototype.set_assert = function(assert_name, args) { Tests.prototype.set_assert = function(assert_name, args) {
this.asserts_run.push(new AssertRecord(this.current_test, assert_name, args)) this.asserts_run.push(new AssertRecord(this.current_test, assert_name, args));
} };
Tests.prototype.set_assert_status = function(index, status, stack) { Tests.prototype.set_assert_status = function(index, status, stack) {
let assert_record = this.asserts_run[index]; let assert_record = this.asserts_run[index];
assert_record.status = status; assert_record.status = status;
assert_record.stack = stack; assert_record.stack = stack;
} };
/** /**
* Update the harness status to reflect an unrecoverable harness error that * Update the harness status to reflect an unrecoverable harness error that
@ -3864,7 +3930,7 @@
} }
var remoteContext = this.create_remote_worker(worker); var remoteContext = this.create_remote_worker(worker);
this.pending_remotes.push(remoteContext); this.remotes.push(remoteContext);
return remoteContext.done; return remoteContext.done;
}; };
@ -3887,7 +3953,7 @@
} }
var remoteContext = this.create_remote_window(remote); var remoteContext = this.create_remote_window(remote);
this.pending_remotes.push(remoteContext); this.remotes.push(remoteContext);
return remoteContext.done; return remoteContext.done;
}; };
@ -4099,8 +4165,8 @@
} else { } else {
var root = output_document.documentElement; var root = output_document.documentElement;
var is_html = (root && var is_html = (root &&
root.namespaceURI == "http://www.w3.org/1999/xhtml" && root.namespaceURI === "http://www.w3.org/1999/xhtml" &&
root.localName == "html"); root.localName === "html");
var is_svg = (output_document.defaultView && var is_svg = (output_document.defaultView &&
"SVGSVGElement" in output_document.defaultView && "SVGSVGElement" in output_document.defaultView &&
root instanceof output_document.defaultView.SVGSVGElement); root instanceof output_document.defaultView.SVGSVGElement);
@ -4545,7 +4611,7 @@
*/ */
function AssertionError(message) function AssertionError(message)
{ {
if (typeof message == "string") { if (typeof message === "string") {
message = sanitize_unpaired_surrogates(message); message = sanitize_unpaired_surrogates(message);
} }
this.message = message; this.message = message;
@ -4595,7 +4661,7 @@
} }
return lines.slice(i).join("\n"); return lines.slice(i).join("\n");
} };
function OptionalFeatureUnsupportedError(message) function OptionalFeatureUnsupportedError(message)
{ {
@ -4790,7 +4856,8 @@
return META_TITLE; return META_TITLE;
} }
if ('location' in global_scope && 'pathname' in location) { if ('location' in global_scope && 'pathname' in location) {
return location.pathname.substring(location.pathname.lastIndexOf('/') + 1, location.pathname.indexOf('.')); var filename = location.pathname.substring(location.pathname.lastIndexOf('/') + 1);
return filename.substring(0, filename.indexOf('.'));
} }
return "Untitled"; return "Untitled";
} }