diff -r 000000000000 -r 6474c204b198 js/src/tests/browser.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/js/src/tests/browser.js Wed Dec 31 06:09:35 2014 +0100
@@ -0,0 +1,566 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var gPageCompleted;
+var GLOBAL = this + '';
+
+// Variables local to jstests harness.
+var jstestsTestPassesUnlessItThrows = false;
+var jstestsRestoreFunction;
+var jstestsOptions;
+
+/*
+ * Signals to this script that the current test case should be considered to
+ * have passed if it doesn't throw an exception.
+ *
+ * Overrides the same-named function in shell.js.
+ */
+function testPassesUnlessItThrows() {
+ jstestsTestPassesUnlessItThrows = true;
+}
+
+/*
+ * Requests to load the given JavaScript file before the file containing the
+ * test case.
+ */
+function include(file) {
+ outputscripttag(file, {language: "type", mimetype: "text/javascript"});
+}
+
+/*
+ * Sets a restore function which restores the standard built-in ECMAScript
+ * properties after a destructive test case, and which will be called after
+ * the test case terminates.
+ */
+function setRestoreFunction(restore) {
+ jstestsRestoreFunction = restore;
+}
+
+function htmlesc(str) {
+ if (str == '<')
+ return '<';
+ if (str == '>')
+ return '>';
+ if (str == '&')
+ return '&';
+ return str;
+}
+
+function DocumentWrite(s)
+{
+ try
+ {
+ var msgDiv = document.createElement('div');
+ msgDiv.innerHTML = s;
+ document.body.appendChild(msgDiv);
+ msgDiv = null;
+ }
+ catch(excp)
+ {
+ document.write(s + '
\n');
+ }
+}
+
+function print() {
+ var s = '';
+ var a;
+ for (var i = 0; i < arguments.length; i++)
+ {
+ a = arguments[i];
+ s += String(a) + ' ';
+ }
+
+ if (typeof dump == 'function')
+ {
+ dump( s + '\n');
+ }
+
+ s = s.replace(/[<>&]/g, htmlesc);
+
+ DocumentWrite(s);
+}
+
+function writeHeaderToLog( string ) {
+ string = String(string);
+
+ if (typeof dump == 'function')
+ {
+ dump( string + '\n');
+ }
+
+ string = string.replace(/[<>&]/g, htmlesc);
+
+ DocumentWrite( "
" + string + "
" );
+}
+
+function writeFormattedResult( expect, actual, string, passed ) {
+ string = String(string);
+
+ if (typeof dump == 'function')
+ {
+ dump( string + '\n');
+ }
+
+ string = string.replace(/[<>&]/g, htmlesc);
+
+ var s = ""+ string ;
+ s += "" ;
+ s += ( passed ) ? " " + PASSED
+ : " " + FAILED + expect;
+
+ DocumentWrite( s + "
" );
+ return passed;
+}
+
+window.onerror = function (msg, page, line)
+{
+ jstestsTestPassesUnlessItThrows = false;
+
+ // Restore options in case a test case used this common variable name.
+ options = jstestsOptions;
+
+ // Restore the ECMAScript environment after potentially destructive tests.
+ if (typeof jstestsRestoreFunction === "function") {
+ jstestsRestoreFunction();
+ }
+
+ optionsPush();
+
+ if (typeof DESCRIPTION == 'undefined')
+ {
+ DESCRIPTION = 'Unknown';
+ }
+ if (typeof EXPECTED == 'undefined')
+ {
+ EXPECTED = 'Unknown';
+ }
+
+ var testcase = new TestCase("unknown-test-name", DESCRIPTION, EXPECTED, "error");
+
+ if (document.location.href.indexOf('-n.js') != -1)
+ {
+ // negative test
+ testcase.passed = true;
+ }
+
+ testcase.reason = page + ':' + line + ': ' + msg;
+
+ reportFailure(msg);
+
+ optionsReset();
+};
+
+function gc()
+{
+ try
+ {
+ SpecialPowers.forceGC();
+ }
+ catch(ex)
+ {
+ print('gc: ' + ex);
+ }
+}
+
+function jsdgc()
+{
+ try
+ {
+ var jsdIDebuggerService = SpecialPowers.Ci.jsdIDebuggerService;
+ var service = SpecialPowers.Cc['@mozilla.org/js/jsd/debugger-service;1'].
+ getService(jsdIDebuggerService);
+ service.GC();
+ }
+ catch(ex)
+ {
+ print('jsdgc: ' + ex);
+ }
+}
+
+function quit()
+{
+}
+
+function options(aOptionName)
+{
+ // return value of options() is a comma delimited list
+ // of the previously set values
+
+ var value = '';
+ for (var optionName in options.currvalues)
+ {
+ value += optionName + ',';
+ }
+ if (value)
+ {
+ value = value.substring(0, value.length-1);
+ }
+
+ if (aOptionName) {
+ if (!(aOptionName in SpecialPowers.Cu)) {
+ // This test is trying to flip an unsupported option, so it's
+ // likely no longer testing what it was supposed to. Fail it
+ // hard.
+ throw "Unsupported JSContext option '"+ aOptionName +"'";
+ }
+
+ if (options.currvalues.hasOwnProperty(aOptionName))
+ // option is set, toggle it to unset
+ delete options.currvalues[aOptionName];
+ else
+ // option is not set, toggle it to set
+ options.currvalues[aOptionName] = true;
+
+ SpecialPowers.Cu[aOptionName] =
+ options.currvalues.hasOwnProperty(aOptionName);
+ }
+
+ return value;
+}
+
+// Keep a reference to options around so that we can restore it after running
+// a test case, which may have used this common name for one of its own
+// variables.
+jstestsOptions = options;
+
+function optionsInit() {
+
+ // hash containing the set options.
+ options.currvalues = {
+ strict: true,
+ werror: true,
+ strict_mode: true
+ };
+
+ // record initial values to support resetting
+ // options to their initial values
+ options.initvalues = {};
+
+ // record values in a stack to support pushing
+ // and popping options
+ options.stackvalues = [];
+
+ for (var optionName in options.currvalues)
+ {
+ var propName = optionName;
+
+ if (!(propName in SpecialPowers.Cu))
+ {
+ throw "options.currvalues is out of sync with Components.utils";
+ }
+ if (!SpecialPowers.Cu[propName])
+ {
+ delete options.currvalues[optionName];
+ }
+ else
+ {
+ options.initvalues[optionName] = true;
+ }
+ }
+}
+
+function gczeal(z)
+{
+ SpecialPowers.setGCZeal(z);
+}
+
+function jit(on)
+{
+}
+
+function jsTestDriverBrowserInit()
+{
+
+ if (typeof dump != 'function')
+ {
+ dump = print;
+ }
+
+ optionsInit();
+ optionsClear();
+
+ if (document.location.search.indexOf('?') != 0)
+ {
+ // not called with a query string
+ return;
+ }
+
+ var properties = {};
+ var fields = document.location.search.slice(1).split(';');
+ for (var ifield = 0; ifield < fields.length; ifield++)
+ {
+ var propertycaptures = /^([^=]+)=(.*)$/.exec(fields[ifield]);
+ if (!propertycaptures)
+ {
+ properties[fields[ifield]] = true;
+ }
+ else
+ {
+ properties[propertycaptures[1]] = decodeURIComponent(propertycaptures[2]);
+ if (propertycaptures[1] == 'language')
+ {
+ // language=(type|language);mimetype
+ properties.mimetype = fields[ifield+1];
+ }
+ }
+ }
+
+ if (properties.language != 'type')
+ {
+ try
+ {
+ properties.version = /javascript([.0-9]+)/.exec(properties.mimetype)[1];
+ }
+ catch(ex)
+ {
+ }
+ }
+
+ if (!properties.version && navigator.userAgent.indexOf('Gecko/') != -1)
+ {
+ // If the version is not specified, and the browser is Gecko,
+ // use the default version corresponding to the shell's version(0).
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=522760#c11
+ // Otherwise adjust the version to match the suite version for 1.6,
+ // and later due to the use of for-each, let, yield, etc.
+ //
+ // Note that js1_8, js1_8_1, and js1_8_5 are treated identically in
+ // the browser.
+ if (properties.test.match(/^js1_6/))
+ {
+ properties.version = '1.6';
+ }
+ else if (properties.test.match(/^js1_7/))
+ {
+ properties.version = '1.7';
+ }
+ else if (properties.test.match(/^js1_8/))
+ {
+ properties.version = '1.8';
+ }
+ }
+
+ // default to language=type;text/javascript. required for
+ // reftest style manifests.
+ if (!properties.language)
+ {
+ properties.language = 'type';
+ properties.mimetype = 'text/javascript';
+ }
+
+ gTestPath = properties.test;
+
+ if (properties.gczeal)
+ {
+ gczeal(Number(properties.gczeal));
+ }
+
+ /*
+ * since the default setting of jit changed from false to true
+ * in http://hg.mozilla.org/tracemonkey/rev/685e00e68be9
+ * bisections which depend upon jit settings can be thrown off.
+ * default jit(false) when not running jsreftests to make bisections
+ * depending upon jit settings consistent over time. This is not needed
+ * in shell tests as the default jit setting has not changed there.
+ */
+
+ if (properties.jit || !document.location.href.match(/jsreftest.html/))
+ jit(properties.jit);
+
+ var testpathparts = properties.test.split(/\//);
+
+ if (testpathparts.length < 3)
+ {
+ // must have at least suitepath/subsuite/testcase.js
+ return;
+ }
+
+ document.write('' + properties.test + '<\/title>');
+
+ // XXX bc - the first document.written script is ignored if the protocol
+ // is file:. insert an empty script tag, to work around it.
+ document.write('');
+
+ // Output script tags for shell.js, then browser.js, at each level of the
+ // test path hierarchy.
+ var prepath = "";
+ var i = 0;
+ for (end = testpathparts.length - 1; i < end; i++) {
+ prepath += testpathparts[i] + "/";
+ outputscripttag(prepath + "shell.js", properties);
+ outputscripttag(prepath + "browser.js", properties);
+ }
+
+ // Output the test script itself.
+ outputscripttag(prepath + testpathparts[i], properties);
+
+ // Finally output the driver-end script to advance to the next test.
+ outputscripttag('js-test-driver-end.js', properties);
+ return;
+}
+
+function outputscripttag(src, properties)
+{
+ if (!src)
+ {
+ return;
+ }
+
+ var s = '