Skip to content

Instantly share code, notes, and snippets.

@alexcrichton
Created January 15, 2019 22:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexcrichton/e0ea5ec9ebdd0e2e0918283a4b86292c to your computer and use it in GitHub Desktop.
Save alexcrichton/e0ea5ec9ebdd0e2e0918283a4b86292c to your computer and use it in GitHub Desktop.
[package]
name = "js-parser"
version = "0.1.0"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
edition = "2018"
[dependencies]
ressa = "*"
failure = "*"
resw = "*"
rayon = "*"
use std::fs;
use std::path::Path;
use std::str;
use failure::ResultExt;
use rayon::prelude::*;
fn main() {
walk(std::env::args().nth(1).unwrap().as_ref());
}
fn walk(dir: &Path) {
let files = dir.read_dir().unwrap()
.map(|e| e.unwrap().path())
.collect::<Vec<_>>();
files.par_iter()
.for_each(|path| {
if path.is_file() {
if path.extension() == Some("js".as_ref()) {
if let Err(e) = run(path) {
let path = path.strip_prefix("../gecko-dev").unwrap();
println!("* [{}](https://hg.mozilla.org/mozilla-central/file/tip/{})", e, path.display());
}
}
} else {
walk(&path)
}
});
}
fn run(file: &Path) -> Result<(), failure::Error> {
let contents = fs::read_to_string(file).context("read to string")?;
if contents.starts_with("// |jit-test| error: SyntaxError") {
return Ok(())
}
let mut dst = Vec::<u8>::new();
let mut out = resw::Writer::new(&mut dst);
let mut parts = Vec::new();
for part in ressa::Parser::new(&contents)
.map_err(|e| failure::format_err!("{}", e.to_string()))
.context("create")? {
let part = part
.map_err(|e| failure::format_err!("{}", e.to_string()))?;
out.write_part(&part).context("bad write")?;
parts.push(part);
}
let text = str::from_utf8(&dst).context("utf8")?;
for part in ressa::Parser::new(text).unwrap() {
let part = part
.map_err(|_e| failure::format_err!("failed to re-parse"))?;
if parts.len() == 0 {
failure::bail!("round-trip differed: {} vs {}", contents, text)
} else {
let expected = parts.remove(0);
if expected == part {
continue
}
println!("
<details>
```js
{}
```
vs
```js
{}
```
", contents, text);
failure::bail!("roundtrip differed");
}
}
Ok(())
}
This file has been truncated, but you can view the full file.
<details>
```js
/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
/* 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 appendToActual = function(s) {
actual += s + ',';
}
if (!("gczeal" in this)) {
gczeal = function() { }
}
if (!("schedulegc" in this)) {
schedulegc = function() { }
}
if (!("gcslice" in this)) {
gcslice = function() { }
}
if (!("selectforgc" in this)) {
selectforgc = function() { }
}
if (!("verifyprebarriers" in this)) {
verifyprebarriers = function() { }
}
if (!("verifypostbarriers" in this)) {
verifypostbarriers = function() { }
}
if (!("gcPreserveCode" in this)) {
gcPreserveCode = function() { }
}
```
vs
```js
var appendToActual = (function(s) {
actual += s + ',';
});
if (!"gczeal" in this) {
gczeal = function() { };
}
if (!"schedulegc" in this) {
schedulegc = function() { };
}
if (!"gcslice" in this) {
gcslice = function() { };
}
if (!"selectforgc" in this) {
selectforgc = function() { };
}
if (!"verifyprebarriers" in this) {
verifyprebarriers = function() { };
}
if (!"verifypostbarriers" in this) {
verifypostbarriers = function() { };
}
if (!"gcPreserveCode" in this) {
gcPreserveCode = function() { };
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/prologue.js)
<details>
```js
// Test the source location info in a derived-class default constructor.
function W() { test(); }
class Z extends W {} // line 4
class Y extends Z {} // line 5
class X extends Y {} // line 7
function test() {
for (let frame of new Error().stack.split('\n')) {
function lineNumber(frame) {
return +frame.match(/(\d+):\d+$/)[1];
}
if (frame.startsWith("Z@"))
assertEq(lineNumber(frame), 4);
if (frame.startsWith("Y@"))
assertEq(lineNumber(frame), 5);
if (frame.startsWith("X@"))
assertEq(lineNumber(frame), 7);
}
}
new X;
```
vs
```js
function W() {
test();
}
class Z extends W {
}
class Y extends Z {
}
class X extends Y {
}
function test() {
for (frame of new Error().stack.split('\n')) {
function lineNumber(frame) {
return +frame.match(/(\d+):\d+$/)[1];
}
if (frame.startsWith("Z@")) assertEq(lineNumber(frame), 4);
if (frame.startsWith("Y@")) assertEq(lineNumber(frame), 5);
if (frame.startsWith("X@")) assertEq(lineNumber(frame), 7);
}
}
new X();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/class/bug1473272-default-constructors.js)
<details>
```js
function f(x) {
for (var i = 0; i < 40; ++i) {
var stack = getBacktrace({args: true});
(function() { g = x;});
}
}
f(1);
```
vs
```js
function f(x) {
for (let i = 0;i < 40;++i) {
var stack = getBacktrace({
args: true,
});
function() {
g = x;
};
}
}
f(1);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/self-test/getBacktrace-bug1138195.js)
<details>
```js
// |jit-test| allow-oom
// Appending elements to a dense array should make the array sparse when the
// length exceeds the limit.
function test() {
const MAX_DENSE_ELEMENTS_ALLOCATION = (1 << 28) - 1;
const VALUES_PER_HEADER = 2;
const MAX_DENSE_ELEMENTS_COUNT = MAX_DENSE_ELEMENTS_ALLOCATION - VALUES_PER_HEADER;
const SPARSE_DENSITY_RATIO = 8;
const MIN_DENSE = MAX_DENSE_ELEMENTS_COUNT / SPARSE_DENSITY_RATIO;
const MARGIN = 16;
let a = [];
// Fill the beginning of array to make it keep dense until length exceeds
// MAX_DENSE_ELEMENTS_COUNT.
for (let i = 0; i < MIN_DENSE; i++)
a[i] = i;
// Skip from MIN_DENSE to MAX_DENSE_ELEMENTS_COUNT - MARGIN, to reduce the
// time taken by test.
// Fill the ending of array to make it sparse at MAX_DENSE_ELEMENTS_COUNT.
for (let i = MAX_DENSE_ELEMENTS_COUNT - MARGIN; i < MAX_DENSE_ELEMENTS_COUNT + MARGIN; i++)
a[i] = i;
// Make sure the last element is defined.
assertEq(a.length, MAX_DENSE_ELEMENTS_COUNT + MARGIN);
assertEq(a[a.length - 1], MAX_DENSE_ELEMENTS_COUNT + MARGIN - 1);
// Make sure elements around MAX_DENSE_ELEMENTS_COUNT are also defined.
assertEq(a[MAX_DENSE_ELEMENTS_COUNT - 1], MAX_DENSE_ELEMENTS_COUNT - 1);
assertEq(a[MAX_DENSE_ELEMENTS_COUNT], MAX_DENSE_ELEMENTS_COUNT);
assertEq(a[MAX_DENSE_ELEMENTS_COUNT + 1], MAX_DENSE_ELEMENTS_COUNT + 1);
}
var config = getBuildConfiguration();
// Takes too long time on debug build.
if (!config.debug) {
test();
}
```
vs
```js
function test() {
const MAX_DENSE_ELEMENTS_ALLOCATION = 1 << 28 - 1;
const VALUES_PER_HEADER = 2;
const MAX_DENSE_ELEMENTS_COUNT = MAX_DENSE_ELEMENTS_ALLOCATION - VALUES_PER_HEADER;
const SPARSE_DENSITY_RATIO = 8;
const MIN_DENSE = MAX_DENSE_ELEMENTS_COUNT / SPARSE_DENSITY_RATIO;
const MARGIN = 16;
let a = [];
for (let i = 0;i < MIN_DENSE;i++) a[i] = i;
for (let i = MAX_DENSE_ELEMENTS_COUNT - MARGIN;i < MAX_DENSE_ELEMENTS_COUNT + MARGIN;i++) a[i] = i;
assertEq(a.length, MAX_DENSE_ELEMENTS_COUNT + MARGIN);
assertEq(a[a.length - 1], MAX_DENSE_ELEMENTS_COUNT + MARGIN - 1);
assertEq(a[MAX_DENSE_ELEMENTS_COUNT - 1], MAX_DENSE_ELEMENTS_COUNT - 1);
assertEq(a[MAX_DENSE_ELEMENTS_COUNT], MAX_DENSE_ELEMENTS_COUNT);
assertEq(a[MAX_DENSE_ELEMENTS_COUNT + 1], MAX_DENSE_ELEMENTS_COUNT + 1);
}
var config = getBuildConfiguration();
if (!config.debug) {
test();
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/manual-tests/dense-to-sparse.js)
<details>
```js
// |jit-test| skip-if: helperThreadCount() === 0 || !('oomAtAllocation' in this)
if ("gczeal" in this)
gczeal(0);
eval("g=function() {}")
var lfGlobal = newGlobal();
for (lfLocal in this) {
if (!(lfLocal in lfGlobal)) {
lfGlobal[lfLocal] = this[lfLocal];
}
}
lfGlobal.offThreadCompileScript(`
if (!("oomAtAllocation" in this && "resetOOMFailure" in this))
gczeal(0);
function oomTest(f) {
var i = 1;
do {
try {
oomAtAllocation(i);
f();
more = resetOOMFailure();
} catch (e) {
more = resetOOMFailure();
}
i++;
} while(more);
}
var g = newGlobal();
oomTest(function() { new revocable(); });
`);
try {
lfGlobal.runOffThreadScript();
} catch(e) {
// This can happen if we OOM while bailing out in Ion.
assertEq(e, "out of memory");
}
```
vs
```js
if ("gczeal" in this) gczeal(0);
eval("g=function() {}");
var lfGlobal = newGlobal();
for (lfLocal in this) {
if (!lfLocal in lfGlobal) {
lfGlobal[lfLocal] = this[lfLocal];
}
}
lfGlobal.offThreadCompileScript(`
if (!("oomAtAllocation" in this && "resetOOMFailure" in this))
gczeal(0);
function oomTest(f) {
var i = 1;
do {
try {
oomAtAllocation(i);
f();
more = resetOOMFailure();
} catch (e) {
more = resetOOMFailure();
}
i++;
} while(more);
}
var g = newGlobal();
oomTest(function() { new revocable(); });
`);
try {
lfGlobal.runOffThreadScript();
} catch (e) {
assertEq(e, "out of memory");
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/baseline/bug1209585.js)
<details>
```js
// Some experimental features are enabled only on nightly builds, and disabled
// on beta and release. Tests for these features should not simply disable
// themselves on all but nightly builds, because if we neglect to update such
// tests once the features cease to be experimental, we'll silently skip the
// tests on beta and release, even though they should run.
// Call the function f. On beta and release, expect it to throw an error that is
// an instance of error.
function nightlyOnly(error, f) {
if (getBuildConfiguration().release_or_beta) {
try {
f();
throw new Error("use of feature expected to fail on release and beta, but succeeded; please update test");
} catch (e) {
if (!(e instanceof error)) {
throw e;
}
// All is well.
}
} else {
f();
}
}
```
vs
```js
function nightlyOnly(error, f) {
if (getBuildConfiguration().release_or_beta) {
try {
f();
throw new Error("use of feature expected to fail on release and beta, but succeeded; please update test");
} catch (e) {
if (!e instanceof error) {
throw e;
}
}
} else {
f();
}
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/nightly-only.js)
<details>
```js
if (!wasmIsSupported())
quit();
// We need to find the absolute path that ends like this:
//
// js/src/jit-test/tests/wasm/spec/harness/
//
// because that's where the test harness lives. Fortunately we are provided
// with |libdir|, which is a path that ends thusly
//
// js/src/jit-test/lib/
//
// That is, it has a fixed offset relative to what we need. So we can
// simply do this:
let harnessdir = libdir + "../tests/wasm/spec/harness/";
load(harnessdir + 'index.js');
load(harnessdir + 'wasm-constants.js');
load(harnessdir + 'wasm-module-builder.js');
function test(func, description) {
let maybeErr;
try {
func();
} catch(e) {
maybeErr = e;
}
if (typeof maybeErr !== 'undefined') {
throw new Error(`${description}: FAIL.
${maybeErr}
${maybeErr.stack}`);
} else {
print(`${description}: PASS.`);
}
}
function promise_test(func, description) {
let maybeError = null;
func()
.then(_ => {
print(`${description}: PASS.`);
})
.catch(err => {
print(`${description}: FAIL.
${err}`);
maybeError = err;
});
drainJobQueue();
if (maybeError)
throw maybeError;
}
let assert_equals = assertEq;
let assert_true = (x, errMsg) => { assertEq(x, true); }
let assert_false = (x, errMsg) => { assertEq(x, false); }
function assert_unreached(description) {
throw new Error(`unreachable:\n${description}`);
}
function assert_not_equals(actual, not_expected, description) {
let caught = false;
try {
assertEq(actual, not_expected, description);
} catch (e) {
caught = true;
};
assertEq(caught, true, "assert_not_equals failed: " + description);
}
```
vs
```js
if (!wasmIsSupported()) quit();
let harnessdir = libdir + "../tests/wasm/spec/harness/";
load(harnessdir + 'index.js');
load(harnessdir + 'wasm-constants.js');
load(harnessdir + 'wasm-module-builder.js');
function test(func, description) {
let maybeErr;
try {
func();
} catch (e) {
maybeErr = e;
}
if (typeof maybeErr !== 'undefined') {
throw new Error(`${description}: FAIL.
{maybeErr}
{maybeErr.stack}`);
} else {
print(`${description}: PASS.`);
}
}
function promise_test(func, description) {
let maybeError = null;
func().then(_ => {
print(`${description}: PASS.`);
}).catch(err => {
print(`${description}: FAIL.
{err}`);
maybeError = err;
});
drainJobQueue();
if (maybeError) throw maybeError;
}
let assert_equals = assertEq;
let assert_true = (x, errMsg) => {
assertEq(x, true);
};
let assert_false = (x, errMsg) => {
assertEq(x, false);
};
function assert_unreached(description) {
throw new Error(`unreachable:\n${description}`);
}
function assert_not_equals(actual, not_expected, description) {
let caught = false;
try {
assertEq(actual, not_expected, description);
} catch (e) {
caught = true;
}
;
assertEq(caught, true, "assert_not_equals failed: " + description);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/wasm-testharness.js)
<details>
```js
// These predicates are for tests that require a particular set of JIT options.
// Check if toggles match. Useful for tests that shouldn't be run if a
// different set of JIT toggles are set, since TBPL runs each jit-test
// multiple times with a variety of flags.
function jitTogglesMatch(opts) {
var currentOpts = getJitCompilerOptions();
for (var k in opts) {
if (k.indexOf(".enable") > 0 && opts[k] != currentOpts[k])
return false;
}
// ARM64 does not yet have an Ion code generator, so return false if
// ion.enable is requested.
var conf = getBuildConfiguration();
if (conf['arm64'] && opts['ion.enable'])
return false;
return true;
}
// Run fn under a particular set of JIT options.
function withJitOptions(opts, fn) {
var oldOpts = getJitCompilerOptions();
for (var k in opts)
setJitCompilerOption(k, opts[k]);
try {
fn();
} finally {
for (var k in oldOpts)
setJitCompilerOption(k, oldOpts[k]);
}
}
// N.B. Ion opts *must come before* baseline opts because there's some kind of
// "undo eager compilation" logic. If we don't set the baseline warmup-counter
// *after* the Ion warmup-counter we end up setting the baseline warmup-counter
// to be the default if we hit the "undo eager compilation" logic.
var Opts_BaselineEager =
{
'ion.enable': 1,
'ion.warmup.trigger': 100,
'baseline.enable': 1,
'baseline.warmup.trigger': 0,
'offthread-compilation.enable': 1
};
// Checking for offthread compilation being off is often helpful if the test
// requires a function be Ion compiled. Each individual test will usually
// finish before the Ion compilation thread has a chance to attach the
// compiled code.
var Opts_IonEagerNoOffthreadCompilation =
{
'ion.enable': 1,
'ion.warmup.trigger': 0,
'baseline.enable': 1,
'baseline.warmup.trigger': 0,
'offthread-compilation.enable': 0,
};
var Opts_Ion2NoOffthreadCompilation =
{
'ion.enable': 1,
'ion.warmup.trigger': 2,
'baseline.enable': 1,
'baseline.warmup.trigger': 1,
'offthread-compilation.enable': 0
};
var Opts_NoJits =
{
'ion.enable': 0,
'ion.warmup.trigger': 0,
'baseline.warmup.trigger': 0,
'baseline.enable': 0,
'offthread-compilation.enable': 0
};
```
vs
```js
function jitTogglesMatch(opts) {
var currentOpts = getJitCompilerOptions();
for (k in opts) {
if (k.indexOf(".enable") > 0 && opts[k] != currentOpts[k]) return false;
}
var conf = getBuildConfiguration();
if (conf['arm64'] && opts['ion.enable']) return false;
return true;
}
function withJitOptions(opts, fn) {
var oldOpts = getJitCompilerOptions();
for (k in opts) setJitCompilerOption(k, opts[k]);
try {
fn();
} finally {
for (k in oldOpts) setJitCompilerOption(k, oldOpts[k]);
}
}
var Opts_BaselineEager = ({
'ion.enable': 1,
'ion.warmup.trigger': 100,
'baseline.enable': 1,
'baseline.warmup.trigger': 0,
'offthread-compilation.enable': 1,
});
var Opts_IonEagerNoOffthreadCompilation = ({
'ion.enable': 1,
'ion.warmup.trigger': 0,
'baseline.enable': 1,
'baseline.warmup.trigger': 0,
'offthread-compilation.enable': 0,
});
var Opts_Ion2NoOffthreadCompilation = ({
'ion.enable': 1,
'ion.warmup.trigger': 2,
'baseline.enable': 1,
'baseline.warmup.trigger': 1,
'offthread-compilation.enable': 0,
});
var Opts_NoJits = ({
'ion.enable': 0,
'ion.warmup.trigger': 0,
'baseline.warmup.trigger': 0,
'baseline.enable': 0,
'offthread-compilation.enable': 0,
});
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/jitopts.js)
<details>
```js
function evalWithCache(code, ctx) {
ctx = ctx || {};
ctx = Object.create(ctx, {
fileName: { value: "evalWithCacheCode.js" },
lineNumber: { value: 0 }
});
code = code instanceof Object ? code : cacheEntry(code);
var incremental = ctx.incremental || false;
// We create a new global ...
if (!("global" in ctx))
ctx.global = newGlobal({ cloneSingletons: !incremental });
if (!("isRunOnce" in ctx))
ctx.isRunOnce = true;
var ctx_save;
if (incremental)
ctx_save = Object.create(ctx, {saveIncrementalBytecode: { value: true } });
else
ctx_save = Object.create(ctx, {saveBytecode: { value: true } });
// Fetch the verification function from the evaluation context. This function
// is used to assert the state of the script/function after each run of the
// evaluate function.
var checkAfter = ctx.checkAfter || function(ctx) {};
// The generation counter is used to represent environment variations which
// might cause the program to run differently, and thus to have a different
// set of functions executed.
ctx.global.generation = 0;
var res1 = evaluate(code, ctx_save);
checkAfter(ctx);
ctx.global.generation = 1;
var res2 = evaluate(code, Object.create(ctx_save, {loadBytecode: { value: true } }));
checkAfter(ctx);
ctx.global.generation = 2;
var res3 = evaluate(code, Object.create(ctx, {loadBytecode: { value: true } }));
checkAfter(ctx);
ctx.global.generation = 3;
var res0 = evaluate(code, ctx);
checkAfter(ctx);
if (ctx.assertEqResult) {
assertEq(res0, res1);
assertEq(res0, res2);
assertEq(res0, res3);
}
if (ctx.checkFrozen) {
assertEq(Object.isFrozen(res0), Object.isFrozen(res1));
assertEq(Object.isFrozen(res0), Object.isFrozen(res2));
assertEq(Object.isFrozen(res0), Object.isFrozen(res3));
}
}
```
vs
```js
function evalWithCache(code, ctx) {
ctx = ctx || { };
ctx = Object.create(ctx, {
fileName: {
value: "evalWithCacheCode.js",
},
lineNumber: {
value: 0,
},
});
code = code instanceof Object ? code : cacheEntry(code);
var incremental = ctx.incremental || false;
if (!"global" in ctx) ctx.global = newGlobal({
cloneSingletons: !incremental,
});
if (!"isRunOnce" in ctx) ctx.isRunOnce = true;
var ctx_save;
if (incremental) ctx_save = Object.create(ctx, {
saveIncrementalBytecode: {
value: true,
},
});
else ctx_save = Object.create(ctx, {
saveBytecode: {
value: true,
},
});
var checkAfter = ctx.checkAfter || function(ctx) { };
ctx.global.generation = 0;
var res1 = evaluate(code, ctx_save);
checkAfter(ctx);
ctx.global.generation = 1;
var res2 = evaluate(code, Object.create(ctx_save, {
loadBytecode: {
value: true,
},
}));
checkAfter(ctx);
ctx.global.generation = 2;
var res3 = evaluate(code, Object.create(ctx, {
loadBytecode: {
value: true,
},
}));
checkAfter(ctx);
ctx.global.generation = 3;
var res0 = evaluate(code, ctx);
checkAfter(ctx);
if (ctx.assertEqResult) {
assertEq(res0, res1);
assertEq(res0, res2);
assertEq(res0, res3);
}
if (ctx.checkFrozen) {
assertEq(Object.isFrozen(res0), Object.isFrozen(res1));
assertEq(Object.isFrozen(res0), Object.isFrozen(res2));
assertEq(Object.isFrozen(res0), Object.isFrozen(res3));
}
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/bytecode-cache.js)
<details>
```js
/* 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/. */
load(libdir + "../../tests/non262/shell.js");
if (typeof assertWarning === 'undefined') {
var assertWarning = function assertWarning(f, pattern) {
var hadWerror = options().split(",").indexOf("werror") !== -1;
// Ensure the "werror" option is disabled.
if (hadWerror)
options("werror");
try {
f();
} catch (exc) {
if (hadWerror)
options("werror");
print("assertWarning: Unexpected exception calling " + f +
" with warnings-as-errors disabled");
throw exc;
}
// Enable the "werror" option.
options("werror");
try {
f();
} catch (exc) {
if (!String(exc).match(pattern))
throw new Error(`assertWarning failed: "${exc}" does not match "${pattern}"`);
return;
} finally {
if (!hadWerror)
options("werror");
}
throw new Error("assertWarning failed: no warning");
};
}
if (typeof assertNoWarning === 'undefined') {
var assertNoWarning = function assertNoWarning(f, msg) {
// Ensure the "werror" option is enabled.
var hadWerror = options().split(",").indexOf("werror") !== -1;
if (!hadWerror)
options("werror");
try {
f();
} catch (exc) {
if (msg)
print("assertNoWarning: " + msg);
print("assertNoWarning: Unexpected exception calling " + f +
"with warnings-as-errors enabled");
throw exc;
} finally {
if (!hadWerror)
options("werror");
}
};
}
if (typeof assertErrorMessage === 'undefined') {
var assertErrorMessage = function assertErrorMessage(f, ctor, test) {
try {
f();
} catch (e) {
if (!(e instanceof ctor))
throw new Error("Assertion failed: expected exception " + ctor.name + ", got " + e);
if (typeof test == "string") {
if (test != e.message)
throw new Error("Assertion failed: expected " + test + ", got " + e.message);
} else {
if (!test.test(e.message))
throw new Error("Assertion failed: expected " + test.toString() + ", got " + e.message);
}
return;
}
throw new Error("Assertion failed: expected exception " + ctor.name + ", no exception thrown");
};
}
if (typeof assertTypeErrorMessage === 'undefined') {
var assertTypeErrorMessage = function assertTypeErrorMessage(f, test) {
assertErrorMessage(f, TypeError, test);
};
}
if (typeof assertRangeErrorMessage === 'undefined') {
var assertRangeErrorMessage = function assertRangeErrorMessage(f, test) {
assertErrorMessage(f, RangeError, test);
};
}
```
vs
```js
load(libdir + "../../tests/non262/shell.js");
if (typeof assertWarning === 'undefined') {
var assertWarning = function assertWarning(f, pattern) {
var hadWerror = options().split(",").indexOf("werror") !== -1;
if (hadWerror) options("werror");
try {
f();
} catch (exc) {
if (hadWerror) options("werror");
print("assertWarning: Unexpected exception calling " + f + " with warnings-as-errors disabled");
throw exc;
}
options("werror");
try {
f();
} catch (exc) {
if (!String(exc).match(pattern)) throw new Error(`assertWarning failed: "${exc}" does not match "{pattern}"`);
return;
} finally {
if (!hadWerror) options("werror");
}
throw new Error("assertWarning failed: no warning");
};
}
if (typeof assertNoWarning === 'undefined') {
var assertNoWarning = function assertNoWarning(f, msg) {
var hadWerror = options().split(",").indexOf("werror") !== -1;
if (!hadWerror) options("werror");
try {
f();
} catch (exc) {
if (msg) print("assertNoWarning: " + msg);
print("assertNoWarning: Unexpected exception calling " + f + "with warnings-as-errors enabled");
throw exc;
} finally {
if (!hadWerror) options("werror");
}
};
}
if (typeof assertErrorMessage === 'undefined') {
var assertErrorMessage = function assertErrorMessage(f, ctor, test) {
try {
f();
} catch (e) {
if (!e instanceof ctor) throw new Error("Assertion failed: expected exception " + ctor.name + ", got " + e);
if (typeof test == "string") {
if (test != e.message) throw new Error("Assertion failed: expected " + test + ", got " + e.message);
} else {
if (!test.test(e.message)) throw new Error("Assertion failed: expected " + test.toString() + ", got " + e.message);
}
return;
}
throw new Error("Assertion failed: expected exception " + ctor.name + ", no exception thrown");
};
}
if (typeof assertTypeErrorMessage === 'undefined') {
var assertTypeErrorMessage = function assertTypeErrorMessage(f, test) {
assertErrorMessage(f, TypeError, test);
};
}
if (typeof assertRangeErrorMessage === 'undefined') {
var assertRangeErrorMessage = function assertRangeErrorMessage(f, test) {
assertErrorMessage(f, RangeError, test);
};
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/asserts.js)
<details>
```js
// The Great Computer Language Shootout
// http://shootout.alioth.debian.org/
//
// modified by Isaac Gouy
function pad(number,width){
var s = number.toString();
var prefixWidth = width - s.length;
if (prefixWidth>0){
for (var i=1; i<=prefixWidth; i++) s = " " + s;
}
return s;
}
function nsieve(m, isPrime){
var i, k, count;
for (i=2; i<=m; i++) { isPrime[i] = true; }
count = 0;
for (i=2; i<=m; i++){
if (isPrime[i]) {
for (k=i+i; k<=m; k+=i) isPrime[k] = false;
count++;
}
}
return count;
}
var ret = 0;
function sieve() {
for (var i = 1; i <= 3; i++ ) {
var m = (1<<i)*10000;
var flags = Array(m+1);
ret += nsieve(m, flags);
}
}
sieve();
assertEq(ret, 14302)
```
vs
```js
function pad(number, width) {
var s = number.toString();
var prefixWidth = width - s.length;
if (prefixWidth > 0) {
for (let i = 1;i <= prefixWidth;i++) s = " " + s;
}
return s;
}
function nsieve(m, isPrime) {
var i, k, count;
for (i = 2;i <= m;i++) {
isPrime[i] = true;
}
count = 0;
for (i = 2;i <= m;i++) {
if (isPrime[i]) {
for (k = i + i;k <= m;k += i) isPrime[k] = false;
count++;
}
}
return count;
}
var ret = 0;
function sieve() {
for (let i = 1;i <= 3;i++) {
var m = 1 << i * 10000;
var flags = Array(m + 1);
ret += nsieve(m, flags);
}
}
sieve();
assertEq(ret, 14302);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-access-nsieve.js)
<details>
```js
// Set iterators produces entries in the order they were inserted.
var set = new Set();
var i;
for (i = 7; i !== 1; i = i * 7 % 1117)
set.add(i);
assertEq(set.size, 557);
i = 7;
for (var v of set) {
assertEq(v, i);
i = i * 7 % 1117;
}
assertEq(i, 1);
```
vs
```js
var set = new Set();
var i;
for (i = 7;i !== 1;i = i * 7 % 1117) set.add(i);
assertEq(set.size, 557);
i = 7;
for (v of set) {
assertEq(v, i);
i = i * 7 % 1117;
}
assertEq(i, 1);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-iterator-order.js)
<details>
```js
// Functions for checking results returned by Debugger.Memory.prototype.takeCensus.
const Census = {};
(function () {
// Census.walkCensus(subject, name, walker[, ignore])
//
// Use |walker| to check |subject|, a census object of the sort returned by
// Debugger.Memory.prototype.takeCensus: a tree of objects with integers at the
// leaves. Use |name| as the name for |subject| in diagnostic messages. Return
// the number of leaves of |subject| we visited.
//
// A walker is an object with three methods:
//
// - enter(prop): Return the walker we should use to check the property of the
// subject census named |prop|. This is for recursing into the subobjects of
// the subject.
//
// - done(ignore): Called after we have called 'enter' on every property of
// the subject. Passed the |ignore| set of properties.
//
// - check(value): Check |value|, a leaf in the subject.
//
// Walker methods are expected to simply throw if a node we visit doesn't look
// right.
//
// The optional |ignore| parameter allows you to specify a |Set| of property
// names which should be ignored. The walker will not traverse such
// properties.
Census.walkCensus = (subject, name, walker, ignore = new Set()) =>
walk(subject, name, walker, ignore, 0);
function walk(subject, name, walker, ignore, count) {
if (typeof subject === 'object') {
print(name);
for (let prop in subject) {
if (ignore.has(prop)) {
continue;
}
count = walk(subject[prop],
name + "[" + uneval(prop) + "]",
walker.enter(prop),
ignore,
count);
}
walker.done(ignore);
} else {
print(name + " = " + uneval(subject));
walker.check(subject);
count++;
}
return count;
}
// A walker that doesn't check anything.
Census.walkAnything = {
enter: () => Census.walkAnything,
done: () => undefined,
check: () => undefined
};
// A walker that requires all leaves to be zeros.
Census.assertAllZeros = {
enter: () => Census.assertAllZeros,
done: () => undefined,
check: elt => assertEq(elt, 0)
};
function expectedObject() {
throw "Census mismatch: subject has leaf where basis has nested object";
}
function expectedLeaf() {
throw "Census mismatch: subject has nested object where basis has leaf";
}
// Return a function that, given a 'basis' census, returns a census walker that
// compares the subject census against the basis. The returned walker calls the
// given |compare|, |missing|, and |extra| functions as follows:
//
// - compare(subjectLeaf, basisLeaf): Check a leaf of the subject against the
// corresponding leaf of the basis.
//
// - missing(prop, value): Called when the subject is missing a property named
// |prop| which is present in the basis with value |value|.
//
// - extra(prop): Called when the subject has a property named |prop|, but the
// basis has no such property. This should return a walker that can check
// the subject's value.
function makeBasisChecker({compare, missing, extra}) {
return function makeWalker(basis) {
if (typeof basis === 'object') {
var unvisited = new Set(Object.getOwnPropertyNames(basis));
return {
enter: prop => {
unvisited.delete(prop);
if (prop in basis) {
return makeWalker(basis[prop]);
} else {
return extra(prop);
}
},
done: ignore => [...unvisited].filter(p => !ignore.has(p)).forEach(p => missing(p, basis[p])),
check: expectedObject
};
} else {
return {
enter: expectedLeaf,
done: expectedLeaf,
check: elt => compare(elt, basis)
};
}
};
}
function missingProp(prop) {
throw "Census mismatch: subject lacks property present in basis: " + uneval(prop);
}
function extraProp(prop) {
throw "Census mismatch: subject has property not present in basis: " + uneval(prop);
}
// Return a walker that checks that the subject census has counts all equal to
// |basis|.
Census.assertAllEqual = makeBasisChecker({
compare: assertEq,
missing: missingProp,
extra: extraProp
});
// Return a walker that checks that the subject census has at least as many
// items of each category as |basis|.
Census.assertAllNotLessThan = makeBasisChecker({
compare: (subject, basis) => assertEq(subject >= basis, true),
missing: missingProp,
extra: () => Census.walkAnything
});
// Return a walker that checks that the subject census has at most as many
// items of each category as |basis|.
Census.assertAllNotMoreThan = makeBasisChecker({
compare: (subject, basis) => assertEq(subject <= basis, true),
missing: missingProp,
extra: () => Census.walkAnything
});
// Return a walker that checks that the subject census has within |fudge|
// items of each category of the count in |basis|.
Census.assertAllWithin = function (fudge, basis) {
return makeBasisChecker({
compare: (subject, basis) => assertEq(Math.abs(subject - basis) <= fudge, true),
missing: missingProp,
extra: () => Census.walkAnything
})(basis);
}
})();
```
vs
```js
const Census = ({});
(function() {
Census.walkCensus = (subject, name, walker, ignore = new Set()) => walk(subject, name, walker, ignore, 0);
function walk(subject, name, walker, ignore, count) {
if (typeof subject === 'object') {
print(name);
for (prop in subject) {
if (ignore.has(prop)) {
continue;
}
count = walk(subject[prop], name + "[" + uneval(prop) + "]", walker.enter(prop), ignore, count);
}
walker.done(ignore);
} else {
print(name + " = " + uneval(subject));
walker.check(subject);
count++;
}
return count;
}
Census.walkAnything = {
enter: () => Census.walkAnything,
done: () => undefined,
check: () => undefined,
};
Census.assertAllZeros = {
enter: () => Census.assertAllZeros,
done: () => undefined,
check: elt => assertEq(elt, 0),
};
function expectedObject() {
throw "Census mismatch: subject has leaf where basis has nested object";
}
function expectedLeaf() {
throw "Census mismatch: subject has nested object where basis has leaf";
}
function makeBasisChecker({compare, missing, extra, }) {
return function makeWalker(basis) {
if (typeof basis === 'object') {
var unvisited = new Set(Object.getOwnPropertyNames(basis));
return {
enter: prop => {
unvisited.delete(prop);
if (prop in basis) {
return makeWalker(basis[prop]);
} else {
return extra(prop);
}
},
done: ignore => [...unvisited,].filter(p => !ignore.has(p)).forEach(p => missing(p, basis[p])),
check: expectedObject,
};
} else {
return {
enter: expectedLeaf,
done: expectedLeaf,
check: elt => compare(elt, basis),
};
}
};
}
function missingProp(prop) {
throw "Census mismatch: subject lacks property present in basis: " + uneval(prop);
}
function extraProp(prop) {
throw "Census mismatch: subject has property not present in basis: " + uneval(prop);
}
Census.assertAllEqual = makeBasisChecker({
compare: assertEq,
missing: missingProp,
extra: extraProp,
});
Census.assertAllNotLessThan = makeBasisChecker({
compare: (subject, basis) => assertEq(subject >= basis, true),
missing: missingProp,
extra: () => Census.walkAnything,
});
Census.assertAllNotMoreThan = makeBasisChecker({
compare: (subject, basis) => assertEq(subject <= basis, true),
missing: missingProp,
extra: () => Census.walkAnything,
});
Census.assertAllWithin = function(fudge, basis) {
return makeBasisChecker({
compare: (subject, basis) => assertEq(Math.abs(subject - basis) <= fudge, true),
missing: missingProp,
extra: () => Census.walkAnything,
})(basis);
};
})();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/census.js)
<details>
```js
/* 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/. */
const ASM_TYPE_FAIL_STRING = "asm.js type error:";
const ASM_DIRECTIVE_FAIL_STRING = "\"use asm\" is only meaningful in the Directive Prologue of a function body";
const USE_ASM = '"use asm";';
const HEAP_IMPORTS = "const i8=new glob.Int8Array(b);var u8=new glob.Uint8Array(b);"+
"const i16=new glob.Int16Array(b);var u16=new glob.Uint16Array(b);"+
"const i32=new glob.Int32Array(b);var u32=new glob.Uint32Array(b);"+
"const f32=new glob.Float32Array(b);var f64=new glob.Float64Array(b);";
const BUF_MIN = 64 * 1024;
const BUF_CHANGE_MIN = 16 * 1024 * 1024;
const BUF_64KB = new ArrayBuffer(BUF_MIN);
function asmCompile()
{
var f = Function.apply(null, arguments);
assertEq(!isAsmJSCompilationAvailable() || isAsmJSModule(f), true);
return f;
}
function asmCompileCached()
{
if (!isAsmJSCompilationAvailable())
return Function.apply(null, arguments);
if (!isCachingEnabled()) {
var f = Function.apply(null, arguments);
assertEq(isAsmJSModule(f), true);
return f;
}
var quotedArgs = [];
for (var i = 0; i < arguments.length; i++)
quotedArgs.push("'" + arguments[i] + "'");
var code = "setCachingEnabled(true); var f = new Function(" + quotedArgs.join(',') + ");assertEq(isAsmJSModule(f), true);";
nestedShell("--js-cache", "--no-js-cache-per-process", "--execute=" + code);
var f = Function.apply(null, arguments);
assertEq(isAsmJSModuleLoadedFromCache(f), true);
return f;
}
function assertAsmDirectiveFail(str)
{
if (!isAsmJSCompilationAvailable())
return;
// Turn on warnings-as-errors
var oldOpts = options("werror");
assertEq(oldOpts.indexOf("werror"), -1);
// Verify an error is thrown
var caught = false;
try {
eval(str);
} catch (e) {
if ((''+e).indexOf(ASM_DIRECTIVE_FAIL_STRING) == -1)
throw new Error("Didn't catch the expected directive failure error; instead caught: " + e + "\nStack: " + new Error().stack);
caught = true;
}
if (!caught)
throw new Error("Didn't catch the directive failure error");
// Turn warnings-as-errors back off
options("werror");
}
function assertAsmTypeFail()
{
if (!isAsmJSCompilationAvailable())
return;
// Verify no error is thrown with warnings off
Function.apply(null, arguments);
// Turn on throwing on validation errors
var oldOpts = options("throw_on_asmjs_validation_failure");
assertEq(oldOpts.indexOf("throw_on_asmjs_validation_failure"), -1);
// Verify an error is thrown
var caught = false;
try {
Function.apply(null, arguments);
} catch (e) {
if ((''+e).indexOf(ASM_TYPE_FAIL_STRING) == -1)
throw new Error("Didn't catch the expected type failure error; instead caught: " + e + "\nStack: " + new Error().stack);
caught = true;
}
if (!caught)
throw new Error("Didn't catch the type failure error");
// Turn warnings-as-errors back off
options("throw_on_asmjs_validation_failure");
}
function assertAsmLinkFail(f)
{
if (!isAsmJSCompilationAvailable())
return;
assertEq(isAsmJSModule(f), true);
// Verify no error is thrown with warnings off
var ret = f.apply(null, Array.slice(arguments, 1));
assertEq(isAsmJSFunction(ret), false);
if (typeof ret === 'object')
for (var i in ret)
assertEq(isAsmJSFunction(ret[i]), false);
// Turn on warnings-as-errors
var oldOpts = options("werror");
assertEq(oldOpts.indexOf("werror"), -1);
// Verify an error is thrown
var caught = false;
try {
f.apply(null, Array.slice(arguments, 1));
} catch (e) {
// Arbitrary code an run in the GetProperty, so don't assert any
// particular string
caught = true;
}
if (!caught)
throw new Error("Didn't catch the link failure error");
// Turn warnings-as-errors back off
options("werror");
}
// Linking should throw an exception even without warnings-as-errors
function assertAsmLinkAlwaysFail(f)
{
var caught = false;
try {
f.apply(null, Array.slice(arguments, 1));
} catch (e) {
caught = true;
}
if (!caught)
throw new Error("Didn't catch the link failure error");
// Turn on warnings-as-errors
var oldOpts = options("werror");
assertEq(oldOpts.indexOf("werror"), -1);
// Verify an error is thrown
var caught = false;
try {
f.apply(null, Array.slice(arguments, 1));
} catch (e) {
caught = true;
}
if (!caught)
throw new Error("Didn't catch the link failure error");
// Turn warnings-as-errors back off
options("werror");
}
function assertAsmLinkDeprecated(f)
{
if (!isAsmJSCompilationAvailable())
return;
// Verify no error is thrown with warnings off
f.apply(null, Array.slice(arguments, 1));
// Turn on warnings-as-errors
var oldOpts = options("werror");
assertEq(oldOpts.indexOf("werror"), -1);
// Verify an error is thrown
var caught = false;
try {
f.apply(null, Array.slice(arguments, 1));
} catch (e) {
// Arbitrary code an run in the GetProperty, so don't assert any
// particular string
caught = true;
}
if (!caught)
throw new Error("Didn't catch the link failure error");
// Turn warnings-as-errors back off
options("werror");
}
// Linking should throw a warning-as-error but otherwise run fine
function asmLink(f)
{
if (!isAsmJSCompilationAvailable())
return f.apply(null, Array.slice(arguments, 1));
// Turn on warnings-as-errors
var oldOpts = options("werror");
assertEq(oldOpts.indexOf("werror"), -1);
var ret = f.apply(null, Array.slice(arguments, 1));
// Turn warnings-as-errors back off
options("werror");
return ret;
}
```
vs
```js
const ASM_TYPE_FAIL_STRING = "asm.js type error:";
const ASM_DIRECTIVE_FAIL_STRING = "\"use asm\" is only meaningful in the Directive Prologue of a function body";
const USE_ASM = '"use asm";';
const HEAP_IMPORTS = "const i8=new glob.Int8Array(b);var u8=new glob.Uint8Array(b);" + "const i16=new glob.Int16Array(b);var u16=new glob.Uint16Array(b);" + "const i32=new glob.Int32Array(b);var u32=new glob.Uint32Array(b);" + "const f32=new glob.Float32Array(b);var f64=new glob.Float64Array(b);";
const BUF_MIN = 64 * 1024;
const BUF_CHANGE_MIN = 16 * 1024 * 1024;
const BUF_64KB = new ArrayBuffer(BUF_MIN);
function asmCompile() {
var f = Function.apply(null, arguments);
assertEq(!isAsmJSCompilationAvailable() || isAsmJSModule(f), true);
return f;
}
function asmCompileCached() {
if (!isAsmJSCompilationAvailable()) return Function.apply(null, arguments);
if (!isCachingEnabled()) {
var f = Function.apply(null, arguments);
assertEq(isAsmJSModule(f), true);
return f;
}
var quotedArgs = [];
for (let i = 0;i < arguments.length;i++) quotedArgs.push("'" + arguments[i] + "'");
var code = "setCachingEnabled(true); var f = new Function(" + quotedArgs.join(',') + ");assertEq(isAsmJSModule(f), true);";
nestedShell("--js-cache", "--no-js-cache-per-process", "--execute=" + code);
var f = Function.apply(null, arguments);
assertEq(isAsmJSModuleLoadedFromCache(f), true);
return f;
}
function assertAsmDirectiveFail(str) {
if (!isAsmJSCompilationAvailable()) return;
var oldOpts = options("werror");
assertEq(oldOpts.indexOf("werror"), -1);
var caught = false;
try {
eval(str);
} catch (e) {
if ('' + e.indexOf(ASM_DIRECTIVE_FAIL_STRING) == -1) throw new Error("Didn't catch the expected directive failure error; instead caught: " + e + "\nStack: " + new Error().stack);
caught = true;
}
if (!caught) throw new Error("Didn't catch the directive failure error");
options("werror");
}
function assertAsmTypeFail() {
if (!isAsmJSCompilationAvailable()) return;
Function.apply(null, arguments);
var oldOpts = options("throw_on_asmjs_validation_failure");
assertEq(oldOpts.indexOf("throw_on_asmjs_validation_failure"), -1);
var caught = false;
try {
Function.apply(null, arguments);
} catch (e) {
if ('' + e.indexOf(ASM_TYPE_FAIL_STRING) == -1) throw new Error("Didn't catch the expected type failure error; instead caught: " + e + "\nStack: " + new Error().stack);
caught = true;
}
if (!caught) throw new Error("Didn't catch the type failure error");
options("throw_on_asmjs_validation_failure");
}
function assertAsmLinkFail(f) {
if (!isAsmJSCompilationAvailable()) return;
assertEq(isAsmJSModule(f), true);
var ret = f.apply(null, Array.slice(arguments, 1));
assertEq(isAsmJSFunction(ret), false);
if (typeof ret === 'object') for (i in ret) assertEq(isAsmJSFunction(ret[i]), false);
var oldOpts = options("werror");
assertEq(oldOpts.indexOf("werror"), -1);
var caught = false;
try {
f.apply(null, Array.slice(arguments, 1));
} catch (e) {
caught = true;
}
if (!caught) throw new Error("Didn't catch the link failure error");
options("werror");
}
function assertAsmLinkAlwaysFail(f) {
var caught = false;
try {
f.apply(null, Array.slice(arguments, 1));
} catch (e) {
caught = true;
}
if (!caught) throw new Error("Didn't catch the link failure error");
var oldOpts = options("werror");
assertEq(oldOpts.indexOf("werror"), -1);
var caught = false;
try {
f.apply(null, Array.slice(arguments, 1));
} catch (e) {
caught = true;
}
if (!caught) throw new Error("Didn't catch the link failure error");
options("werror");
}
function assertAsmLinkDeprecated(f) {
if (!isAsmJSCompilationAvailable()) return;
f.apply(null, Array.slice(arguments, 1));
var oldOpts = options("werror");
assertEq(oldOpts.indexOf("werror"), -1);
var caught = false;
try {
f.apply(null, Array.slice(arguments, 1));
} catch (e) {
caught = true;
}
if (!caught) throw new Error("Didn't catch the link failure error");
options("werror");
}
function asmLink(f) {
if (!isAsmJSCompilationAvailable()) return f.apply(null, Array.slice(arguments, 1));
var oldOpts = options("werror");
assertEq(oldOpts.indexOf("werror"), -1);
var ret = f.apply(null, Array.slice(arguments, 1));
options("werror");
return ret;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/asm.js)
<details>
```js
if (!('oomTest' in this))
quit();
oomTest(() => {
var g = newGlobal({sameZoneAs: this});
g.eval("\
function f(){}; \
getLcovInfo(); \
");
});
```
vs
```js
if (!'oomTest' in this) quit();
oomTest(() => {
var g = newGlobal({
sameZoneAs: this,
});
g.eval("function f(){}; getLcovInfo(); ");
});
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/coverage/bug1214548.js)
<details>
```js
setJitCompilerOption("ion.warmup.trigger", 40);
const constructors = [
Int8Array,
Uint8Array,
Uint8ClampedArray,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array ];
// Ensure that when creating TypedArrays under JIT
// the sort() method works as expected (bug 1295034).
for (var ctor of constructors) {
for (var _ of Array(1024)) {
var testArray = new ctor(10);
testArray.sort();
}
}
if (typeof reportCompare === "function")
reportCompare(true, true);
```
vs
```js
setJitCompilerOption("ion.warmup.trigger", 40);
const constructors = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array,];
for (ctor of constructors) {
for (_ of Array(1024)) {
var testArray = new ctor(10);
testArray.sort();
}
}
if (typeof reportCompare === "function") reportCompare(true, true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/typedarray/sort.js)
<details>
```js
// new WeakMap(x) throws if x is not iterable (unless x is undefined).
load(libdir + "asserts.js");
var nonIterables = [true, 1, -0, 3.14, NaN, {}, Math, this];
for (let k of nonIterables)
assertThrowsInstanceOf(function () { new WeakMap(k); }, TypeError);
```
vs
```js
load(libdir + "asserts.js");
var nonIterables = [true, 1, -0, 3.14, NaN, ({}), Math, this,];
for (k of nonIterables) assertThrowsInstanceOf(function() {
new WeakMap(k);
}, TypeError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/WeakMap-constructor-4.js)
<details>
```js
// |jit-test| skip-if: helperThreadCount() === 0
// Let a few threads hammer on memory with atomics to provoke errors
// in exclusion work. This test is not 100% fail-safe: the test may
// pass despite a bug, but this is unlikely.
// Map an Int32Array on shared memory. The first location is used as
// a counter, each worker counts up on exit and the main thread will
// wait until the counter reaches the number of workers. The other
// elements are contended accumulators where we count up and down very
// rapidly and for a long time, any failure in mutual exclusion should
// lead to errors in the result. (For example, the test fails almost
// immediately when I disable simulation of mutual exclusion in the
// ARM simulator.)
const numWorkers = 4; // You're not meant to change this
const iterCount = 255; // Nor this
const sabLength = 1024; // Nor this
const oddResult = (function () {
var v = 0;
for ( var j=0 ; j < numWorkers ; j++ )
v |= (iterCount << (8 * j));
return v;
})();
const evenResult = 0;
const sab = new SharedArrayBuffer(sabLength);
setSharedObject(sab);
const iab = new Int32Array(sab);
function testRun(limit) {
console.log("Limit = " + limit);
// Fork off workers to hammer on memory.
for ( var i=0 ; i < numWorkers ; i++ ) {
evalInWorker(`
const iab = new Int32Array(getSharedObject());
const v = 1 << (8 * ${i});
for ( var i=0 ; i < ${limit} ; i++ ) {
for ( var k=0 ; k < ${iterCount} ; k++ ) {
if (i & 1) {
for ( var j=1 ; j < iab.length ; j++ )
Atomics.sub(iab, j, v);
}
else {
for ( var j=1 ; j < iab.length ; j++ )
Atomics.add(iab, j, v);
}
}
}
Atomics.add(iab, 0, 1);
`);
}
// Wait...
while (Atomics.load(iab, 0) != numWorkers)
;
Atomics.store(iab, 0, 0);
// Check the results and clear the array again.
const v = (limit & 1) ? oddResult : evenResult;
for ( var i=1 ; i < iab.length ; i++ ) {
assertEq(iab[i], v);
iab[i] = 0;
}
}
// Under some configurations the test can take a while to run (and may
// saturate the CPU since it runs four workers); try not to time out.
var then = new Date();
testRun(1);
if (new Date() - then < 20000) {
testRun(2);
if (new Date() - then < 30000) {
testRun(3);
}
}
```
vs
```js
const numWorkers = 4;
const iterCount = 255;
const sabLength = 1024;
const oddResult = (function() {
var v = 0;
for (let j = 0;j < numWorkers;j++) v |= iterCount << 8 * j;
return v;
})();
const evenResult = 0;
const sab = new SharedArrayBuffer(sabLength);
setSharedObject(sab);
const iab = new Int32Array(sab);
function testRun(limit) {
console.log("Limit = " + limit);
for (let i = 0;i < numWorkers;i++) {
evalInWorker(`
const iab = new Int32Array(getSharedObject());
const v = 1 << (8 * ${i});
for ( var i=0 ; i < {limit} ; i++ ) {
for ( var k=0 ; k < {iterCount} ; k++ ) {
if (i & 1) {
for ( var j=1 ; j < iab.length ; j++ )
Atomics.sub(iab, j, v);
}
else {
for ( var j=1 ; j < iab.length ; j++ )
Atomics.add(iab, j, v);
}
}
}
Atomics.add(iab, 0, 1);
`);
}
while (Atomics.load(iab, 0) != numWorkers) ;
Atomics.store(iab, 0, 0);
const v = limit & 1 ? oddResult : evenResult;
for (let i = 1;i < iab.length;i++) {
assertEq(iab[i], v);
iab[i] = 0;
}
}
var then = new Date();
testRun(1);
if (new Date() - then < 20000) {
testRun(2);
if (new Date() - then < 30000) {
testRun(3);
}
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/atomics/mutual-exclusion.js)
<details>
```js
/* The Great Computer Language Shootout
http://shootout.alioth.debian.org/
contributed by Isaac Gouy */
var PI = 3.141592653589793;
var SOLAR_MASS = 4 * PI * PI;
var DAYS_PER_YEAR = 365.24;
function Body(x,y,z,vx,vy,vz,mass){
this.x = x;
this.y = y;
this.z = z;
this.vx = vx;
this.vy = vy;
this.vz = vz;
this.mass = mass;
}
Body.prototype.offsetMomentum = function(px,py,pz) {
this.vx = -px / SOLAR_MASS;
this.vy = -py / SOLAR_MASS;
this.vz = -pz / SOLAR_MASS;
return this;
}
function Jupiter(){
return new Body(
4.84143144246472090e+00,
-1.16032004402742839e+00,
-1.03622044471123109e-01,
1.66007664274403694e-03 * DAYS_PER_YEAR,
7.69901118419740425e-03 * DAYS_PER_YEAR,
-6.90460016972063023e-05 * DAYS_PER_YEAR,
9.54791938424326609e-04 * SOLAR_MASS
);
}
function Saturn(){
return new Body(
8.34336671824457987e+00,
4.12479856412430479e+00,
-4.03523417114321381e-01,
-2.76742510726862411e-03 * DAYS_PER_YEAR,
4.99852801234917238e-03 * DAYS_PER_YEAR,
2.30417297573763929e-05 * DAYS_PER_YEAR,
2.85885980666130812e-04 * SOLAR_MASS
);
}
function Uranus(){
return new Body(
1.28943695621391310e+01,
-1.51111514016986312e+01,
-2.23307578892655734e-01,
2.96460137564761618e-03 * DAYS_PER_YEAR,
2.37847173959480950e-03 * DAYS_PER_YEAR,
-2.96589568540237556e-05 * DAYS_PER_YEAR,
4.36624404335156298e-05 * SOLAR_MASS
);
}
function Neptune(){
return new Body(
1.53796971148509165e+01,
-2.59193146099879641e+01,
1.79258772950371181e-01,
2.68067772490389322e-03 * DAYS_PER_YEAR,
1.62824170038242295e-03 * DAYS_PER_YEAR,
-9.51592254519715870e-05 * DAYS_PER_YEAR,
5.15138902046611451e-05 * SOLAR_MASS
);
}
function Sun(){
return new Body(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS);
}
function NBodySystem(bodies){
this.bodies = bodies;
var px = 0.0;
var py = 0.0;
var pz = 0.0;
var size = this.bodies.length;
for (var i=0; i<size; i++){
var b = this.bodies[i];
var m = b.mass;
px += b.vx * m;
py += b.vy * m;
pz += b.vz * m;
}
this.bodies[0].offsetMomentum(px,py,pz);
}
NBodySystem.prototype.advance = function(dt){
var dx, dy, dz, distance, mag;
var size = this.bodies.length;
for (var i=0; i<size; i++) {
var bodyi = this.bodies[i];
for (var j=i+1; j<size; j++) {
var bodyj = this.bodies[j];
dx = bodyi.x - bodyj.x;
dy = bodyi.y - bodyj.y;
dz = bodyi.z - bodyj.z;
distance = Math.sqrt(dx*dx + dy*dy + dz*dz);
mag = dt / (distance * distance * distance);
bodyi.vx -= dx * bodyj.mass * mag;
bodyi.vy -= dy * bodyj.mass * mag;
bodyi.vz -= dz * bodyj.mass * mag;
bodyj.vx += dx * bodyi.mass * mag;
bodyj.vy += dy * bodyi.mass * mag;
bodyj.vz += dz * bodyi.mass * mag;
}
}
for (var i=0; i<size; i++) {
var body = this.bodies[i];
body.x += dt * body.vx;
body.y += dt * body.vy;
body.z += dt * body.vz;
}
}
NBodySystem.prototype.energy = function(){
var dx, dy, dz, distance;
var e = 0.0;
var size = this.bodies.length;
for (var i=0; i<size; i++) {
var bodyi = this.bodies[i];
e += 0.5 * bodyi.mass *
( bodyi.vx * bodyi.vx
+ bodyi.vy * bodyi.vy
+ bodyi.vz * bodyi.vz );
for (var j=i+1; j<size; j++) {
var bodyj = this.bodies[j];
dx = bodyi.x - bodyj.x;
dy = bodyi.y - bodyj.y;
dz = bodyi.z - bodyj.z;
distance = Math.sqrt(dx*dx + dy*dy + dz*dz);
e -= (bodyi.mass * bodyj.mass) / distance;
}
}
return e;
}
var ret;
for ( var n = 3; n <= 24; n *= 2 ) {
(function(){
var bodies = new NBodySystem( Array(
Sun(),Jupiter(),Saturn(),Uranus(),Neptune()
));
var max = n * 100;
ret = bodies.energy();
for (var i=0; i<max; i++){
bodies.advance(0.01);
}
ret = bodies.energy();
})();
}
assertEq(ret, -0.16906933525822856)
```
vs
```js
var PI = 3.141592653589793;
var SOLAR_MASS = 4 * PI * PI;
var DAYS_PER_YEAR = 365.24;
function Body(x, y, z, vx, vy, vz, mass) {
this.x = x;
this.y = y;
this.z = z;
this.vx = vx;
this.vy = vy;
this.vz = vz;
this.mass = mass;
}
Body.prototype.offsetMomentum = (function(px, py, pz) {
this.vx = -px / SOLAR_MASS;
this.vy = -py / SOLAR_MASS;
this.vz = -pz / SOLAR_MASS;
return this;
});
function Jupiter() {
return new Body(4.84143144246472090e+00, -1.16032004402742839e+00, -1.03622044471123109e-01, 1.66007664274403694e-03 * DAYS_PER_YEAR, 7.69901118419740425e-03 * DAYS_PER_YEAR, -6.90460016972063023e-05 * DAYS_PER_YEAR, 9.54791938424326609e-04 * SOLAR_MASS);
}
function Saturn() {
return new Body(8.34336671824457987e+00, 4.12479856412430479e+00, -4.03523417114321381e-01, -2.76742510726862411e-03 * DAYS_PER_YEAR, 4.99852801234917238e-03 * DAYS_PER_YEAR, 2.30417297573763929e-05 * DAYS_PER_YEAR, 2.85885980666130812e-04 * SOLAR_MASS);
}
function Uranus() {
return new Body(1.28943695621391310e+01, -1.51111514016986312e+01, -2.23307578892655734e-01, 2.96460137564761618e-03 * DAYS_PER_YEAR, 2.37847173959480950e-03 * DAYS_PER_YEAR, -2.96589568540237556e-05 * DAYS_PER_YEAR, 4.36624404335156298e-05 * SOLAR_MASS);
}
function Neptune() {
return new Body(1.53796971148509165e+01, -2.59193146099879641e+01, 1.79258772950371181e-01, 2.68067772490389322e-03 * DAYS_PER_YEAR, 1.62824170038242295e-03 * DAYS_PER_YEAR, -9.51592254519715870e-05 * DAYS_PER_YEAR, 5.15138902046611451e-05 * SOLAR_MASS);
}
function Sun() {
return new Body(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS);
}
function NBodySystem(bodies) {
this.bodies = bodies;
var px = 0.0;
var py = 0.0;
var pz = 0.0;
var size = this.bodies.length;
for (let i = 0;i < size;i++) {
var b = this.bodies[i];
var m = b.mass;
px += b.vx * m;
py += b.vy * m;
pz += b.vz * m;
}
this.bodies[0].offsetMomentum(px, py, pz);
}
NBodySystem.prototype.advance = (function(dt) {
var dx, dy, dz, distance, mag;
var size = this.bodies.length;
for (let i = 0;i < size;i++) {
var bodyi = this.bodies[i];
for (let j = i + 1;j < size;j++) {
var bodyj = this.bodies[j];
dx = bodyi.x - bodyj.x;
dy = bodyi.y - bodyj.y;
dz = bodyi.z - bodyj.z;
distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
mag = dt / distance * distance * distance;
bodyi.vx -= dx * bodyj.mass * mag;
bodyi.vy -= dy * bodyj.mass * mag;
bodyi.vz -= dz * bodyj.mass * mag;
bodyj.vx += dx * bodyi.mass * mag;
bodyj.vy += dy * bodyi.mass * mag;
bodyj.vz += dz * bodyi.mass * mag;
}
}
for (let i = 0;i < size;i++) {
var body = this.bodies[i];
body.x += dt * body.vx;
body.y += dt * body.vy;
body.z += dt * body.vz;
}
});
NBodySystem.prototype.energy = (function() {
var dx, dy, dz, distance;
var e = 0.0;
var size = this.bodies.length;
for (let i = 0;i < size;i++) {
var bodyi = this.bodies[i];
e += 0.5 * bodyi.mass * bodyi.vx * bodyi.vx + bodyi.vy * bodyi.vy + bodyi.vz * bodyi.vz;
for (let j = i + 1;j < size;j++) {
var bodyj = this.bodies[j];
dx = bodyi.x - bodyj.x;
dy = bodyi.y - bodyj.y;
dz = bodyi.z - bodyj.z;
distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
e -= bodyi.mass * bodyj.mass / distance;
}
}
return e;
});
var ret;
for (let n = 3;n <= 24;n *= 2) {
function() {
var bodies = new NBodySystem(Array(Sun(), Jupiter(), Saturn(), Uranus(), Neptune()));
var max = n * 100;
ret = bodies.energy();
for (let i = 0;i < max;i++) {
bodies.advance(0.01);
}
ret = bodies.energy();
}();
}
assertEq(ret, -0.16906933525822856);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-access-nbody.js)
<details>
```js
if (!wasmIsSupported())
quit();
load(libdir + "asserts.js");
function wasmEvalText(str, imports) {
let binary = wasmTextToBinary(str);
let valid = WebAssembly.validate(binary);
let m;
try {
m = new WebAssembly.Module(binary);
assertEq(valid, true);
} catch(e) {
if (!e.toString().match(/out of memory/))
assertEq(valid, false);
throw e;
}
return new WebAssembly.Instance(m, imports);
}
function wasmValidateText(str) {
assertEq(WebAssembly.validate(wasmTextToBinary(str)), true);
}
function wasmFailValidateText(str, pattern) {
let binary = wasmTextToBinary(str);
assertEq(WebAssembly.validate(binary), false);
assertErrorMessage(() => new WebAssembly.Module(binary), WebAssembly.CompileError, pattern);
}
function mismatchError(actual, expect) {
var str = `type mismatch: expression has type ${actual} but expected ${expect}`;
return RegExp(str);
}
const emptyStackError = /from empty stack/;
const unusedValuesError = /unused values not explicitly dropped by end of block/;
function jsify(wasmVal) {
if (wasmVal === 'nan')
return NaN;
if (wasmVal === 'infinity')
return Infinity;
if (wasmVal === '-infinity')
return Infinity;
if (wasmVal === '-0')
return -0;
return wasmVal;
}
function _augmentSrc(src, assertions) {
let i = 0;
let newSrc = src.substr(0, src.lastIndexOf(')'));
for (let { func, args, expected, type } of assertions) {
newSrc += `
(func (export "assert_${i++}") (result i32)
${ args ? args.join('\n') : '' }
call ${func}`;
if (typeof expected !== 'undefined') {
switch (type) {
case 'f32':
newSrc += `
i32.reinterpret/f32
i32.const ${expected}
i32.eq`;
break;
case 'f64':
newSrc += `
i64.reinterpret/f64
i64.const ${expected}
i64.eq`;
break;
case 'i64':
newSrc += `
i64.const ${expected}
i64.eq`;
break;
default:
throw new Error("unexpected usage of wasmAssert");
}
} else {
// Always true when there's no expected return value.
newSrc += "\ni32.const 1";
}
newSrc += ')\n';
}
newSrc += ')';
return newSrc;
}
function wasmAssert(src, assertions, maybeImports = {}) {
let { exports } = wasmEvalText(_augmentSrc(src, assertions), maybeImports);
for (let i = 0; i < assertions.length; i++) {
let { func, expected, params } = assertions[i];
let paramText = params ? params.join(', ') : '';
assertEq(exports[`assert_${i}`](), 1,
`Unexpected value when running ${func}(${paramText}), expecting ${expected}.`);
}
}
// Fully test a module:
// - ensure it validates.
// - ensure it compiles and produces the expected result.
// - ensure textToBinary(binaryToText(binary)) = binary
// Preconditions:
// - the binary module must export a function called "run".
function wasmFullPass(text, expected, maybeImports, ...args) {
let binary = wasmTextToBinary(text);
assertEq(WebAssembly.validate(binary), true, "Must validate.");
let module = new WebAssembly.Module(binary);
let instance = new WebAssembly.Instance(module, maybeImports);
assertEq(typeof instance.exports.run, 'function', "A 'run' function must be exported.");
assertEq(instance.exports.run(...args), expected, "Initial module must return the expected result.");
}
// Ditto, but expects a function named '$run' instead of exported with this name.
function wasmFullPassI64(text, expected, maybeImports, ...args) {
let binary = wasmTextToBinary(text);
assertEq(WebAssembly.validate(binary), true, "Must validate.");
let augmentedSrc = _augmentSrc(text, [ { type: 'i64', func: '$run', args, expected } ]);
let augmentedBinary = wasmTextToBinary(augmentedSrc);
new WebAssembly.Instance(new WebAssembly.Module(augmentedBinary), maybeImports).exports.assert_0();
}
function wasmRunWithDebugger(wast, lib, init, done) {
let g = newGlobal('');
let dbg = new Debugger(g);
g.eval(`
var wasm = wasmTextToBinary('${wast}');
var lib = ${lib || 'undefined'};
var m = new WebAssembly.Instance(new WebAssembly.Module(wasm), lib);`);
var wasmScript = dbg.findScripts().filter(s => s.format == 'wasm')[0];
init({dbg, wasmScript, g,});
let result = undefined, error = undefined;
try {
result = g.eval("m.exports.test()");
} catch (ex) {
error = ex;
}
done({dbg, result, error, wasmScript, g,});
}
const WasmHelpers = {};
(function() {
let enabled = false;
try {
enableSingleStepProfiling();
disableSingleStepProfiling();
enabled = true;
} catch (e) {}
WasmHelpers.isSingleStepProfilingEnabled = enabled;
})();
WasmHelpers._normalizeStack = (stack, preciseStacks) => {
var wasmFrameTypes = [
{re:/^jit call to int64 wasm function$/, sub:"i64>"},
{re:/^out-of-line coercion for jit entry arguments \(in wasm\)$/, sub:"ool>"},
{re:/^wasm-function\[(\d+)\] \(.*\)$/, sub:"$1"},
{re:/^(fast|slow) exit trampoline (to native )?\(in wasm\)$/, sub:"<"},
{re:/^call to[ asm.js]? native (.*) \(in wasm\)$/, sub:"$1"},
{re:/ \(in wasm\)$/, sub:""}
];
let entryRegexps;
if (preciseStacks) {
entryRegexps = [
{re:/^slow entry trampoline \(in wasm\)$/, sub:"!>"},
{re:/^fast entry trampoline \(in wasm\)$/, sub:">"},
];
} else {
entryRegexps = [
{re:/^(fast|slow) entry trampoline \(in wasm\)$/, sub:">"}
];
}
wasmFrameTypes = entryRegexps.concat(wasmFrameTypes);
var framesIn = stack.split(',');
var framesOut = [];
for (let frame of framesIn) {
for (let {re, sub} of wasmFrameTypes) {
if (re.test(frame)) {
framesOut.push(frame.replace(re, sub));
break;
}
}
}
return framesOut.join(',');
};
WasmHelpers._removeAdjacentDuplicates = array => {
if (array.length < 2)
return;
let i = 0;
for (let j = 1; j < array.length; j++) {
if (array[i] !== array[j])
array[++i] = array[j];
}
array.length = i + 1;
}
WasmHelpers.normalizeStacks = (stacks, preciseStacks = false) => {
let observed = [];
for (let i = 0; i < stacks.length; i++)
observed[i] = WasmHelpers._normalizeStack(stacks[i], preciseStacks);
WasmHelpers._removeAdjacentDuplicates(observed);
return observed;
};
WasmHelpers._compareStacks = (got, expect) => {
if (got.length != expect.length) {
return false;
}
for (let i = 0; i < got.length; i++) {
if (got[i] !== expect[i])
return false;
}
return true;
}
WasmHelpers.assertEqImpreciseStacks = (got, expect) => {
let observed = WasmHelpers.normalizeStacks(got, /* precise */ false);
let same = WasmHelpers._compareStacks(observed, expect);
if (!same) {
if (observed.length != expect.length) {
print(`Got:\n${observed.toSource()}\nExpect:\n${expect.toSource()}`);
assertEq(observed.length, expect.length);
}
for (let i = 0; i < observed.length; i++) {
if (observed[i] !== expect[i]) {
print(`On stack ${i}, Got:\n${observed[i]}\nExpect:\n${expect[i]}`);
assertEq(observed[i], expect[i]);
}
}
}
}
WasmHelpers.extractStackFrameFunction = (frameString) => {
var [_, name, filename, line, column] = frameString.match(/^(.*)@(.*):(.*):(.*)$/);
if (name)
return name;
if (/wasm-function/.test(line))
return line;
return "";
};
WasmHelpers.assertStackTrace = (exception, expected) => {
let callsites = exception.stack.trim().split('\n').map(WasmHelpers.extractStackFrameFunction);
assertEq(callsites.length, expected.length);
for (let i = 0; i < callsites.length; i++) {
assertEq(callsites[i], expected[i]);
}
};
WasmHelpers.nextLineNumber = (n=1) => {
return +(new Error().stack).split('\n')[1].split(':')[1] + n;
}
WasmHelpers.startProfiling = () => {
if (!WasmHelpers.isSingleStepProfilingEnabled)
return;
enableSingleStepProfiling();
}
WasmHelpers.endProfiling = () => {
if (!WasmHelpers.isSingleStepProfilingEnabled)
return;
return disableSingleStepProfiling();
}
WasmHelpers.assertEqPreciseStacks = (observed, expectedStacks) => {
if (!WasmHelpers.isSingleStepProfilingEnabled)
return null;
observed = WasmHelpers.normalizeStacks(observed, /* precise */ true);
for (let i = 0; i < expectedStacks.length; i++) {
if (WasmHelpers._compareStacks(observed, expectedStacks[i]))
return i;
}
throw new Error(`no plausible stacks found, observed: ${observed.join('/')}
Expected one of:
${expectedStacks.map(stacks => stacks.join("/")).join('\n')}`);
}
```
vs
```js
if (!wasmIsSupported()) quit();
load(libdir + "asserts.js");
function wasmEvalText(str, imports) {
let binary = wasmTextToBinary(str);
let valid = WebAssembly.validate(binary);
let m;
try {
m = new WebAssembly.Module(binary);
assertEq(valid, true);
} catch (e) {
if (!e.toString().match(/out of memory/)) assertEq(valid, false);
throw e;
}
return new WebAssembly.Instance(m, imports);
}
function wasmValidateText(str) {
assertEq(WebAssembly.validate(wasmTextToBinary(str)), true);
}
function wasmFailValidateText(str, pattern) {
let binary = wasmTextToBinary(str);
assertEq(WebAssembly.validate(binary), false);
assertErrorMessage(() => new WebAssembly.Module(binary), WebAssembly.CompileError, pattern);
}
function mismatchError(actual, expect) {
var str = `type mismatch: expression has type ${actual} but expected {expect}`;
return RegExp(str);
}
const emptyStackError = /from empty stack/;
const unusedValuesError = /unused values not explicitly dropped by end of block/;
function jsify(wasmVal) {
if (wasmVal === 'nan') return NaN;
if (wasmVal === 'infinity') return Infinity;
if (wasmVal === '-infinity') return Infinity;
if (wasmVal === '-0') return -0;
return wasmVal;
}
function _augmentSrc(src, assertions) {
let i = 0;
let newSrc = src.substr(0, src.lastIndexOf(')'));
for ({func, args, expected, type, } of assertions) {
newSrc += `
(func (export "assert_${i++}") (result i32)
{args ? args.join('\n') : ''}
call {func}`;
if (typeof expected !== 'undefined') {
switch (type) {
case 'f32':
newSrc += `
i32.reinterpret/f32
i32.const ${expected}
i32.eq`;
break;
case 'f64':
newSrc += `
i64.reinterpret/f64
i64.const ${expected}
i64.eq`;
break;
case 'i64':
newSrc += `
i64.const ${expected}
i64.eq`;
break;
default:
throw new Error("unexpected usage of wasmAssert");
}
} else {
newSrc += "\ni32.const 1";
}
newSrc += ')\n';
}
newSrc += ')';
return newSrc;
}
function wasmAssert(src, assertions, maybeImports = {}) {
let {exports, } = wasmEvalText(_augmentSrc(src, assertions), maybeImports);
for (let i = 0;i < assertions.length;i++) {
let {func, expected, params, } = assertions[i];
let paramText = params ? params.join(', ') : '';
assertEq(exports[`assert_${i}`](), 1, `Unexpected value when running ${func}({paramText}), expecting {expected}.`);
}
}
function wasmFullPass(text, expected, maybeImports, args) {
let binary = wasmTextToBinary(text);
assertEq(WebAssembly.validate(binary), true, "Must validate.");
let module = new WebAssembly.Module(binary);
let instance = new WebAssembly.Instance(module, maybeImports);
assertEq(typeof instance.exports.run, 'function', "A 'run' function must be exported.");
assertEq(instance.exports.run(...args), expected, "Initial module must return the expected result.");
}
function wasmFullPassI64(text, expected, maybeImports, args) {
let binary = wasmTextToBinary(text);
assertEq(WebAssembly.validate(binary), true, "Must validate.");
let augmentedSrc = _augmentSrc(text, [{
type: 'i64',
func: '$run',
args,
expected,
},]);
let augmentedBinary = wasmTextToBinary(augmentedSrc);
new WebAssembly.Instance(new WebAssembly.Module(augmentedBinary), maybeImports).exports.assert_0();
}
function wasmRunWithDebugger(wast, lib, init, done) {
let g = newGlobal('');
let dbg = new Debugger(g);
g.eval(`
var wasm = wasmTextToBinary('${wast}');
var lib = {lib || 'undefined'};
var m = new WebAssembly.Instance(new WebAssembly.Module(wasm), lib);`);
var wasmScript = dbg.findScripts().filter(s => s.format == 'wasm')[0];
init({
dbg,
wasmScript,
g,
});
let result = undefined, error = undefined;
try {
result = g.eval("m.exports.test()");
} catch (ex) {
error = ex;
}
done({
dbg,
result,
error,
wasmScript,
g,
});
}
const WasmHelpers = ({});
(function() {
let enabled = false;
try {
enableSingleStepProfiling();
disableSingleStepProfiling();
enabled = true;
} catch (e) {
}
WasmHelpers.isSingleStepProfilingEnabled = enabled;
})();
WasmHelpers._normalizeStack = (stack, preciseStacks) => {
var wasmFrameTypes = [{
re: /^jit call to int64 wasm function$/,
sub: "i64>",
}, {
re: /^out-of-line coercion for jit entry arguments \(in wasm\)$/,
sub: "ool>",
}, {
re: /^wasm-function\[(\d+)\] \(.*\)$/,
sub: "$1",
}, {
re: /^(fast|slow) exit trampoline (to native )?\(in wasm\)$/,
sub: "<",
}, {
re: /^call to[ asm.js]? native (.*) \(in wasm\)$/,
sub: "$1",
}, {
re: / \(in wasm\)$/,
sub: "",
},];
let entryRegexps;
if (preciseStacks) {
entryRegexps = [{
re: /^slow entry trampoline \(in wasm\)$/,
sub: "!>",
}, {
re: /^fast entry trampoline \(in wasm\)$/,
sub: ">",
},];
} else {
entryRegexps = [{
re: /^(fast|slow) entry trampoline \(in wasm\)$/,
sub: ">",
},];
}
wasmFrameTypes = entryRegexps.concat(wasmFrameTypes);
var framesIn = stack.split(',');
var framesOut = [];
for (frame of framesIn) {
for ({re, sub, } of wasmFrameTypes) {
if (re.test(frame)) {
framesOut.push(frame.replace(re, sub));
break;
}
}
}
return framesOut.join(',');
};
WasmHelpers._removeAdjacentDuplicates = array => {
if (array.length < 2) return;
let i = 0;
for (let j = 1;j < array.length;j++) {
if (array[i] !== array[j]) array[++i] = array[j];
}
array.length = i + 1;
};
WasmHelpers.normalizeStacks = (stacks, preciseStacks = false) => {
let observed = [];
for (let i = 0;i < stacks.length;i++) observed[i] = WasmHelpers._normalizeStack(stacks[i], preciseStacks);
WasmHelpers._removeAdjacentDuplicates(observed);
return observed;
};
WasmHelpers._compareStacks = (got, expect) => {
if (got.length != expect.length) {
return false;
}
for (let i = 0;i < got.length;i++) {
if (got[i] !== expect[i]) return false;
}
return true;
};
WasmHelpers.assertEqImpreciseStacks = (got, expect) => {
let observed = WasmHelpers.normalizeStacks(got, false);
let same = WasmHelpers._compareStacks(observed, expect);
if (!same) {
if (observed.length != expect.length) {
print(`Got:\n${observed.toSource()}\nExpect:\n{expect.toSource()}`);
assertEq(observed.length, expect.length);
}
for (let i = 0;i < observed.length;i++) {
if (observed[i] !== expect[i]) {
print(`On stack ${i}, Got:\n{observed[i]}\nExpect:\n{expect[i]}`);
assertEq(observed[i], expect[i]);
}
}
}
};
WasmHelpers.extractStackFrameFunction = frameString => {
var [_,name,filename,line,column,] = frameString.match(/^(.*)@(.*):(.*):(.*)$/);
if (name) return name;
if (/wasm-function/.test(line)) return line;
return "";
};
WasmHelpers.assertStackTrace = (exception, expected) => {
let callsites = exception.stack.trim().split('\n').map(WasmHelpers.extractStackFrameFunction);
assertEq(callsites.length, expected.length);
for (let i = 0;i < callsites.length;i++) {
assertEq(callsites[i], expected[i]);
}
};
WasmHelpers.nextLineNumber = n = 1 => {
return +new Error().stack.split('\n')[1].split(':')[1] + n;
};
WasmHelpers.startProfiling = () => {
if (!WasmHelpers.isSingleStepProfilingEnabled) return;
enableSingleStepProfiling();
};
WasmHelpers.endProfiling = () => {
if (!WasmHelpers.isSingleStepProfilingEnabled) return;
return disableSingleStepProfiling();
};
WasmHelpers.assertEqPreciseStacks = (observed, expectedStacks) => {
if (!WasmHelpers.isSingleStepProfilingEnabled) return null;
observed = WasmHelpers.normalizeStacks(observed, true);
for (let i = 0;i < expectedStacks.length;i++) {
if (WasmHelpers._compareStacks(observed, expectedStacks[i])) return i;
}
throw new Error(`no plausible stacks found, observed: ${observed.join('/')}
Expected one of:
{expectedStacks.map(stacks => stacks.join("/")).join('\n')}`);
};
```
<details>
```js
load(libdir + "iteration.js");
// break in finally.
function *f1() {
L: try {
yield 1;
} finally {
break L;
}
return 2;
}
it = f1();
assertIteratorNext(it, 1);
assertIteratorResult(it.return(4), 2, true);
assertIteratorDone(it);
// continue in finally, followed by return.
function *f2() {
do try {
yield 1;
} catch (e) {
assertEq(0, 1);
} finally {
continue;
} while (0);
return 2;
}
it = f2();
assertIteratorNext(it, 1);
assertIteratorResult(it.return(4), 2, true);
assertIteratorDone(it);
// continue in finally, followed by yield.
function *f3() {
do try {
yield 1;
} catch (e) {
assertEq(0, 1);
} finally {
continue;
} while (0);
yield 2;
}
it = f3();
assertIteratorNext(it, 1);
assertIteratorResult(it.return(4), 2, false);
assertIteratorDone(it);
// continue in finally.
function *f4() {
var i = 0;
while (true) {
try {
yield i++;
} finally {
if (i < 3)
continue;
}
}
}
it = f4();
assertIteratorNext(it, 0);
assertIteratorResult(it.return(-1), 1, false);
assertIteratorResult(it.return(-2), 2, false);
assertIteratorResult(it.return(-3), -3, true);
assertIteratorDone(it);
```
vs
```js
load(libdir + "iteration.js");
function *f1() {
L: try {
yield 1;
} finally {
break L;
}
return 2;
}
it = f1();
assertIteratorNext(it, 1);
assertIteratorResult(it.return(4), 2, true);
assertIteratorDone(it);
function *f2() {
do try {
yield 1;
} catch (e) {
assertEq(0, 1);
} finally {
continue;
}
while (0);
;
return 2;
}
it = f2();
assertIteratorNext(it, 1);
assertIteratorResult(it.return(4), 2, true);
assertIteratorDone(it);
function *f3() {
do try {
yield 1;
} catch (e) {
assertEq(0, 1);
} finally {
continue;
}
while (0);
;
yield 2;
}
it = f3();
assertIteratorNext(it, 1);
assertIteratorResult(it.return(4), 2, false);
assertIteratorDone(it);
function *f4() {
var i = 0;
while (true) {
try {
yield i++;
} finally {
if (i < 3) continue;
}
}
}
it = f4();
assertIteratorNext(it, 0);
assertIteratorResult(it.return(-1), 1, false);
assertIteratorResult(it.return(-2), 2, false);
assertIteratorResult(it.return(-3), -3, true);
assertIteratorDone(it);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/wasm.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/generators/return-break-continue.js)
* [Unexpected Token at line: 2, column: 11: Expected `function`, `this`, `class`, or `import`; found Keyword(Import)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/modules/exportImportMeta.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/regexp_parse.js)
* [Unexpected Token at line: 17, column: 4: Expected `function`, `this`, `class`, or `import`; found Keyword(Await)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/stream/bug-1387503-2.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/self-test/assertRecoveredOnBailout-1.js)
* [Unexpected Token at line: 36, column: 8: Expected `function`, `this`, `class`, or `import`; found Keyword(Package)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/syntax-errors.js)
* [Unexpected Token at line: 3, column: 35: Found unexpected token: ++; Cannot increment when not at assignment target](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/bug672122.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/latin1/latin1.js)
<details>
```js
// Rest parameters are allowed in arrow functions.
var A = (...x) => x;
assertEq(A().toSource(), "[]");
assertEq("" + A(3, 4, 5), "3,4,5");
```
vs
```js
var A = x => x;
assertEq(A().toSource(), "[]");
assertEq("" + A(3, 4, 5), "3,4,5");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/params-rest-1.js)
<details>
```js
/**
* A test case spec is an array of objects of the following kind:
* { 'match': Num|Str|Null,
* 'body': Num|Str|Null,
* 'fallthrough': Boolean }
*
* If the 'match' is null, then it represents a 'default:'
* If the 'match' is not null, it represents a 'case X:' where X is the value.
* If the 'body' is null, then it means that the case body is empty. Otherwise,
* it means that the case body is a single 'arr.push(V);' where "arr" is an input
* array to the function containing the switch statement, and V is the value.
* If 'fallthrough' is false, then the body is terminated with a break, otherwise
* it is not.
*
* So a spec: [{'match':3, 'body':null, 'fallthrough':false}, {'match':null, 'body':"foo", 'fallthrough':true}]
* Represents a switch function:
* function(x, arr) {
* switch(x) {
* case 3:
* break;
* default:
* arr.push('foo');
* }
* }
*
* GenerateSpecPermutes generates a bunch of relevant specs, using the given case match-values,
* and appends them to result the array passed into it.
*
* InterpretSwitch takes a spec, a value, and a result array, and behaves as if the switch specified
* by the spec had been called on the value and the result array.
*
* VerifySwitchSpec is there but not used in the code. I was using it while testing the test case
* generator. It verifies that a switch spec is sane.
*
* RunSpec uses eval to run the test directly. It's not used currently.
*
* GenerateSwitchCode generates a string of the form "function NAME(x, arg) { .... }" which
* contains the switch modeled by its input spec.
*
* RunTest is there to be used from within the generated script. Its code is dumped out
* to the generated script text, and invoked there.
*
* Hope all of this makes some sort of sense.
* -kannan
*/
/** HELPERS **/
function ASSERT(cond, msg) { assertEq(cond, true, msg); }
function IsUndef(x) { return typeof(x) == 'undefined'; }
function IsNull(x) { return typeof(x) == 'object' && x == null; }
function IsNum(x) { return typeof(x) == 'number'; }
function IsStr(x) { return typeof(x) == 'string'; }
function IsBool(x) { return typeof(x) == 'boolean'; }
function Repr(x) {
ASSERT(IsNum(x) || IsStr(x), "Repr");
if(IsNum(x)) { return ""+x; }
else { return "'"+x+"'"; }
}
function RandBool() { return Math.random() >= 0.5; }
function RandInt(max) {
if(IsUndef(max)) { max = 0x7fffffff; }
return (Math.random() * max)|0;
}
var CHARS = "abcdefghijklmnopqrstuvywxyzABCDEFGHIJKLMNOPQRSTUVYWXYZ0123456789~!@#$%^&*()-_=+{}[]";
function RandStr() {
var arr = [];
var len = Math.floor(Math.random() * 10) + 1;
for(var i = 0; i < len; i++) {
var c = Math.floor(Math.random() * CHARS.length);
arr.push(CHARS[c]);
}
return arr.join('');
}
function RandVal() { return RandBool() ? RandInt() : RandStr(); }
/**
* Compare two arrays and ensure they are equal.
*/
function ArraysEqual(arr1, arr2) {
ASSERT(arr1.length == arr2.length, "Lengths not equal");
for(var i = 0; i < arr1.length; i++) {
ASSERT(typeof(arr1[i]) == typeof(arr2[i]), "Types not equal for position " + i);
ASSERT(arr1[i] == arr2[i], "Values not equal for position " + i);
}
}
function VerifySwitchSpec(spec) {
var foundDefault = undefined;
for(var i = 0; i < spec.length; i++) {
var caseSpec = spec[i],
match = caseSpec.match,
body = caseSpec.body,
fallthrough = caseSpec.fallthrough;
ASSERT(IsNum(match) || IsStr(match) || IsNull(match), "Invalid case match for " + i);
ASSERT(IsNum(body) || IsStr(body) || IsNull(body), "Invalid case body for " + i);
ASSERT(IsBool(fallthrough), "Invalid fallthrough for " + i);
if(IsNull(match)) {
ASSERT(IsUndef(foundDefault), "Duplicate default found at " + i);
foundDefault = i;
}
}
}
/**
* Do a manual interpretation of a particular spec, given an input
* and outputting to an output array.
*/
function InterpretSwitch(spec, input, outputArray) {
var foundMatch = undefined, foundDefault = undefined;
// Go through cases, trying to find a matching clause.
for(var i = 0; i < spec.length; i++) {
var caseSpec = spec[i], match = caseSpec.match;
if(IsNull(match)) {
foundDefault = i;
continue;
} else if(match === input) {
foundMatch = i;
break;
}
}
// Select either matching clause or default.
var matchI = IsNum(foundMatch) ? foundMatch : foundDefault;
// If match or default was found, interpret body from that point on.
if(IsNum(matchI)) {
for(var i = matchI; i < spec.length; i++) {
var caseSpec = spec[i],
match = caseSpec.match,
body = caseSpec.body,
fallthrough = caseSpec.fallthrough;
if(!IsNull(body)) { outputArray.push(body); }
if(!fallthrough) { break; }
}
}
}
/**
* Generate the code string for a javascript function containing the
* switch specified by the spec, in pure JS syntax.
*/
function GenerateSwitchCode(spec, name) {
var lines = [];
if(!name) { name = ""; }
lines.push("function "+name+"(x, arr) {");
lines.push(" switch(x) {");
for(var i = 0; i < spec.length; i++) {
var caseSpec = spec[i],
match = caseSpec.match,
body = caseSpec.body,
fallthrough = caseSpec.fallthrough;
if(IsNull(match)) { lines.push(" default:"); }
else { lines.push(" case "+Repr(match)+":"); }
if(!IsNull(body)) { lines.push(" arr.push("+Repr(body)+");"); }
if(!fallthrough) { lines.push(" break;"); }
}
lines.push(" }");
lines.push("}");
return lines.join("\n");
}
/**
* Generates all possible specs for a given set of case match values.
*/
function GenerateSpecPermutes(matchVals, resultArray) {
ASSERT((0 < matchVals.length) && (matchVals.length <= 5), "Invalid matchVals");
var maxPermuteBody = (1 << matchVals.length) - 1;
for(var bod_pm = 0; bod_pm <= maxPermuteBody; bod_pm++) {
var maxPermuteFallthrough = (1 << matchVals.length) - 1;
for(var ft_pm = 0; ft_pm <= maxPermuteFallthrough; ft_pm++) {
// use bod_m and ft_pm to decide the placement of null vs value bodies,
// and the placement of fallthroughs vs breaks.
// Empty bodies always fall through, so fallthrough bitmask 1s must be
// a subset of the body bitmask 1s.
if((bod_pm | ft_pm) != bod_pm) {
continue;
}
var spec = [];
for(var k = 0; k < matchVals.length; k++) {
var match = matchVals[k];
var body = ((bod_pm & (1 << k)) > 0) ? null : RandVal();
var fallthrough = ((ft_pm & (1 << k)) > 0) ? true : false;
var caseSpec = {'match':match, 'body':body, 'fallthrough':fallthrough};
spec.push(caseSpec);
}
// Variant specs for following cases:
// Default with empty body, fallthrough
GenerateDefaultPermutes(spec, null, true, resultArray);
// Default with nonempty body, fallthrough
GenerateDefaultPermutes(spec, RandVal(), true, resultArray);
// Default with nonempty body, break
GenerateDefaultPermutes(spec, RandVal(), false, resultArray);
}
}
}
function GenerateDefaultPermutes(spec, body, fallthrough, resultArray) {
if(spec.length <= 2) {
for(var i = 0; i <= spec.length; i++) {
var copy = CopySpec(spec);
if(IsNull(body)) {
copy.splice(i,0,{'match':null, 'body':null, 'fallthrough':true});
} else {
copy.splice(i,0,{'match':null, 'body':body, 'fallthrough':fallthrough});
}
resultArray.push(copy);
}
} else {
var posns = [0, Math.floor(spec.length / 2), spec.length];
posns.forEach(function (i) {
var copy = CopySpec(spec);
if(IsNull(body)) {
copy.splice(i,0,{'match':null, 'body':null, 'fallthrough':true});
} else {
copy.splice(i,0,{'match':null, 'body':body, 'fallthrough':fallthrough});
}
resultArray.push(copy);
});
}
}
function CopySpec(spec) {
var newSpec = [];
for(var i = 0; i < spec.length; i++) {
var caseSpec = spec[i];
newSpec.push({'match':caseSpec.match,
'body':caseSpec.body,
'fallthrough':caseSpec.fallthrough});
}
return newSpec;
}
function RunSpec(spec, matchVals) {
var code = GenerateSwitchCode(spec);
// Generate roughly 200 inputs for the test case spec, exercising
// every match value, as well as 3 randomly generated values for every
// iteration of the match values.
var inputs = [];
while(inputs.length < 500) {
for(var i = 0; i < matchVals.length; i++) { inputs.push(matchVals[i]); }
for(var i = 0; i < 3; i++) { inputs.push(RandVal()); }
}
// Interpret the lookupswitch with the inputs.
var interpResults = [];
for(var i = 0; i < inputs.length; i++) {
InterpretSwitch(spec, inputs[i], interpResults);
}
// Run compiled lookupswitch with the inputs.
var fn = eval("_ = " + code);
print("Running spec: " + code);
var compileResults = RunCompiled(fn, inputs);
print("Done Running spec");
// Verify that they produce the same output.
ASSERT(interpResults.length == compileResults.length, "Length mismatch");
for(var i = 0; i < interpResults.length; i++) {
ASSERT(interpResults[i] == compileResults[i], "Value mismatch");
}
}
function RunCompiled(fn, inputs) {
var results = [];
var len = inputs.length;
for(var i = 0; i < len; i++) { fn(inputs[i], results); }
return results;
}
function PrintSpec(spec, inputs, fname) {
var code = GenerateSwitchCode(spec, fname);
var input_s = fname + ".INPUTS = [" + inputs.map(Repr).join(', ') + "];";
var spec_s = fname + ".SPEC = " + JSON.stringify(spec) + ";";
print(code + "\n" + input_s + "\n" + spec_s);
}
function RunTest(test) {
// Exercise every test case as well as one case which won't match with any of the
// ("But what if it randomly generates a string case match whose value is
// UNMATCHED_CASE?!", you ask incredulously. Well, RandStr limits itself to 11 chars.
// So there.)
var inputs = test.INPUTS;
inputs.push("UNMATCHED_CASE");
var spec = test.SPEC;
var results1 = [];
for(var i = 0; i < 80; i++) {
for(var j = 0; j < inputs.length; j++) {
test(inputs[j], results1);
}
}
var results2 = [];
for(var i = 0; i < 80; i++) {
for(var j = 0; j < inputs.length; j++) {
InterpretSwitch(spec, inputs[j], results2);
}
}
ArraysEqual(results1, results2);
}
// NOTES:
// * RunTest is used within the generated test script.
// * InterpretSwitch is printed out into the generated test script.
print("/////////////////////////////////////////");
print("// This is a generated file!");
print("// See jit-tests/etc/generate-lookupswitch-tests.js for the code");
print("// that generated this code!");
print("/////////////////////////////////////////");
print("");
print("/////////////////////////////////////////");
print("// PRELUDE //");
print("/////////////////////////////////////////");
print("");
print("// Avoid eager compilation of the global-scope.");
print("try{} catch (x) {};");
print("");
print(ASSERT);
print(IsNull);
print(IsNum);
print(ArraysEqual);
print(InterpretSwitch);
print(RunTest);
print("");
print("/////////////////////////////////////////");
print("// TEST CASES //");
print("/////////////////////////////////////////");
print("");
print("var TESTS = [];");
var MATCH_SETS = [["foo", "bar", "zing"]];
var count = 0;
for(var i = 0; i < MATCH_SETS.length; i++) {
var matchSet = MATCH_SETS[i];
var specs = [];
GenerateSpecPermutes(matchSet, specs);
for(var j = 0; j < specs.length; j++) {
count++;
PrintSpec(specs[j], matchSet.slice(), 'test_'+count);
print("TESTS.push(test_"+count+");\n");
}
}
print("");
print("/////////////////////////////////////////");
print("// RUNNER //");
print("/////////////////////////////////////////");
print("");
print("for(var i = 0; i < TESTS.length; i++) {");
print(" RunTest(TESTS[i]);");
print("}");
```
vs
```js
function ASSERT(cond, msg) {
assertEq(cond, true, msg);
}
function IsUndef(x) {
return typeof x == 'undefined';
}
function IsNull(x) {
return typeof x == 'object' && x == null;
}
function IsNum(x) {
return typeof x == 'number';
}
function IsStr(x) {
return typeof x == 'string';
}
function IsBool(x) {
return typeof x == 'boolean';
}
function Repr(x) {
ASSERT(IsNum(x) || IsStr(x), "Repr");
if (IsNum(x)) {
return "" + x;
} else {
return "'" + x + "'";
}
}
function RandBool() {
return Math.random() >= 0.5;
}
function RandInt(max) {
if (IsUndef(max)) {
max = 0x7fffffff;
}
return Math.random() * max | 0;
}
var CHARS = "abcdefghijklmnopqrstuvywxyzABCDEFGHIJKLMNOPQRSTUVYWXYZ0123456789~!@#$%^&*()-_=+{}[]";
function RandStr() {
var arr = [];
var len = Math.floor(Math.random() * 10) + 1;
for (let i = 0;i < len;i++) {
var c = Math.floor(Math.random() * CHARS.length);
arr.push(CHARS[c]);
}
return arr.join('');
}
function RandVal() {
return RandBool() ? RandInt() : RandStr();
}
function ArraysEqual(arr1, arr2) {
ASSERT(arr1.length == arr2.length, "Lengths not equal");
for (let i = 0;i < arr1.length;i++) {
ASSERT(typeof arr1[i] == typeof arr2[i], "Types not equal for position " + i);
ASSERT(arr1[i] == arr2[i], "Values not equal for position " + i);
}
}
function VerifySwitchSpec(spec) {
var foundDefault = undefined;
for (let i = 0;i < spec.length;i++) {
var caseSpec = spec[i], match = caseSpec.match, body = caseSpec.body, fallthrough = caseSpec.fallthrough;
ASSERT(IsNum(match) || IsStr(match) || IsNull(match), "Invalid case match for " + i);
ASSERT(IsNum(body) || IsStr(body) || IsNull(body), "Invalid case body for " + i);
ASSERT(IsBool(fallthrough), "Invalid fallthrough for " + i);
if (IsNull(match)) {
ASSERT(IsUndef(foundDefault), "Duplicate default found at " + i);
foundDefault = i;
}
}
}
function InterpretSwitch(spec, input, outputArray) {
var foundMatch = undefined, foundDefault = undefined;
for (let i = 0;i < spec.length;i++) {
var caseSpec = spec[i], match = caseSpec.match;
if (IsNull(match)) {
foundDefault = i;
continue;
} else if (match === input) {
foundMatch = i;
break;
}
}
var matchI = IsNum(foundMatch) ? foundMatch : foundDefault;
if (IsNum(matchI)) {
for (let i = matchI;i < spec.length;i++) {
var caseSpec = spec[i], match = caseSpec.match, body = caseSpec.body, fallthrough = caseSpec.fallthrough;
if (!IsNull(body)) {
outputArray.push(body);
}
if (!fallthrough) {
break;
}
}
}
}
function GenerateSwitchCode(spec, name) {
var lines = [];
if (!name) {
name = "";
}
lines.push("function " + name + "(x, arr) {");
lines.push(" switch(x) {");
for (let i = 0;i < spec.length;i++) {
var caseSpec = spec[i], match = caseSpec.match, body = caseSpec.body, fallthrough = caseSpec.fallthrough;
if (IsNull(match)) {
lines.push(" default:");
} else {
lines.push(" case " + Repr(match) + ":");
}
if (!IsNull(body)) {
lines.push(" arr.push(" + Repr(body) + ");");
}
if (!fallthrough) {
lines.push(" break;");
}
}
lines.push(" }");
lines.push("}");
return lines.join("\n");
}
function GenerateSpecPermutes(matchVals, resultArray) {
ASSERT(0 < matchVals.length && matchVals.length <= 5, "Invalid matchVals");
var maxPermuteBody = 1 << matchVals.length - 1;
for (let bod_pm = 0;bod_pm <= maxPermuteBody;bod_pm++) {
var maxPermuteFallthrough = 1 << matchVals.length - 1;
for (let ft_pm = 0;ft_pm <= maxPermuteFallthrough;ft_pm++) {
if (bod_pm | ft_pm != bod_pm) {
continue;
}
var spec = [];
for (let k = 0;k < matchVals.length;k++) {
var match = matchVals[k];
var body = bod_pm & 1 << k > 0 ? null : RandVal();
var fallthrough = ft_pm & 1 << k > 0 ? true : false;
var caseSpec = {
'match': match,
'body': body,
'fallthrough': fallthrough,
};
spec.push(caseSpec);
}
GenerateDefaultPermutes(spec, null, true, resultArray);
GenerateDefaultPermutes(spec, RandVal(), true, resultArray);
GenerateDefaultPermutes(spec, RandVal(), false, resultArray);
}
}
}
function GenerateDefaultPermutes(spec, body, fallthrough, resultArray) {
if (spec.length <= 2) {
for (let i = 0;i <= spec.length;i++) {
var copy = CopySpec(spec);
if (IsNull(body)) {
copy.splice(i, 0, {
'match': null,
'body': null,
'fallthrough': true,
});
} else {
copy.splice(i, 0, {
'match': null,
'body': body,
'fallthrough': fallthrough,
});
}
resultArray.push(copy);
}
} else {
var posns = [0, Math.floor(spec.length / 2), spec.length,];
posns.forEach(function(i) {
var copy = CopySpec(spec);
if (IsNull(body)) {
copy.splice(i, 0, {
'match': null,
'body': null,
'fallthrough': true,
});
} else {
copy.splice(i, 0, {
'match': null,
'body': body,
'fallthrough': fallthrough,
});
}
resultArray.push(copy);
});
}
}
function CopySpec(spec) {
var newSpec = [];
for (let i = 0;i < spec.length;i++) {
var caseSpec = spec[i];
newSpec.push({
'match': caseSpec.match,
'body': caseSpec.body,
'fallthrough': caseSpec.fallthrough,
});
}
return newSpec;
}
function RunSpec(spec, matchVals) {
var code = GenerateSwitchCode(spec);
var inputs = [];
while (inputs.length < 500) {
for (let i = 0;i < matchVals.length;i++) {
inputs.push(matchVals[i]);
}
for (let i = 0;i < 3;i++) {
inputs.push(RandVal());
}
}
var interpResults = [];
for (let i = 0;i < inputs.length;i++) {
InterpretSwitch(spec, inputs[i], interpResults);
}
var fn = eval("_ = " + code);
print("Running spec: " + code);
var compileResults = RunCompiled(fn, inputs);
print("Done Running spec");
ASSERT(interpResults.length == compileResults.length, "Length mismatch");
for (let i = 0;i < interpResults.length;i++) {
ASSERT(interpResults[i] == compileResults[i], "Value mismatch");
}
}
function RunCompiled(fn, inputs) {
var results = [];
var len = inputs.length;
for (let i = 0;i < len;i++) {
fn(inputs[i], results);
}
return results;
}
function PrintSpec(spec, inputs, fname) {
var code = GenerateSwitchCode(spec, fname);
var input_s = fname + ".INPUTS = [" + inputs.map(Repr).join(', ') + "];";
var spec_s = fname + ".SPEC = " + JSON.stringify(spec) + ";";
print(code + "\n" + input_s + "\n" + spec_s);
}
function RunTest(test) {
var inputs = test.INPUTS;
inputs.push("UNMATCHED_CASE");
var spec = test.SPEC;
var results1 = [];
for (let i = 0;i < 80;i++) {
for (let j = 0;j < inputs.length;j++) {
test(inputs[j], results1);
}
}
var results2 = [];
for (let i = 0;i < 80;i++) {
for (let j = 0;j < inputs.length;j++) {
InterpretSwitch(spec, inputs[j], results2);
}
}
ArraysEqual(results1, results2);
}
print("/////////////////////////////////////////");
print("// This is a generated file!");
print("// See jit-tests/etc/generate-lookupswitch-tests.js for the code");
print("// that generated this code!");
print("/////////////////////////////////////////");
print("");
print("/////////////////////////////////////////");
print("// PRELUDE //");
print("/////////////////////////////////////////");
print("");
print("// Avoid eager compilation of the global-scope.");
print("try{} catch (x) {};");
print("");
print(ASSERT);
print(IsNull);
print(IsNum);
print(ArraysEqual);
print(InterpretSwitch);
print(RunTest);
print("");
print("/////////////////////////////////////////");
print("// TEST CASES //");
print("/////////////////////////////////////////");
print("");
print("var TESTS = [];");
var MATCH_SETS = [["foo", "bar", "zing",],];
var count = 0;
for (let i = 0;i < MATCH_SETS.length;i++) {
var matchSet = MATCH_SETS[i];
var specs = [];
GenerateSpecPermutes(matchSet, specs);
for (let j = 0;j < specs.length;j++) {
count++;
PrintSpec(specs[j], matchSet.slice(), 'test_' + count);
print("TESTS.push(test_" + count + ");\n");
}
}
print("");
print("/////////////////////////////////////////");
print("// RUNNER //");
print("/////////////////////////////////////////");
print("");
print("for(var i = 0; i < TESTS.length; i++) {");
print(" RunTest(TESTS[i]);");
print("}");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/etc/generate-lookupswitch-tests.js)
<details>
```js
load(libdir + "asserts.js");
// 'arguments' is allowed in a non-arrow-function with a rest param.
assertEq((function(...rest) { return (x => arguments)(1, 2)})().length, 0);
function restAndArgs(...rest) {
return () => eval("arguments");
}
var args = restAndArgs(1, 2, 3)();
assertEq(args.length, 3);
assertEq(args[0], 1);
assertEq(args[1], 2);
assertEq(args[2], 3);
(function() {
return ((...rest) => {
assertDeepEq(rest, [1, 2, 3]);
assertEq(arguments.length, 2);
assertEq(eval("arguments").length, 2);
})(1, 2, 3);
})(4, 5);
```
vs
```js
load(libdir + "asserts.js");
assertEq((function(rest) {
return x => arguments(1, 2);
})().length, 0);
function restAndArgs(rest) {
return () => eval("arguments");
}
var args = restAndArgs(1, 2, 3)();
assertEq(args.length, 3);
assertEq(args[0], 1);
assertEq(args[1], 2);
assertEq(args[2], 3);
(function() {
return rest => {
assertDeepEq(rest, [1, 2, 3,]);
assertEq(arguments.length, 2);
assertEq(eval("arguments").length, 2);
}(1, 2, 3);
})(4, 5);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/arguments-4.js)
* [Unexpected Token at line: 27, column: 8: Expected `function`, `this`, `class`, or `import`; found Keyword(Await)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/stream/bug-1387503-1.js)
<details>
```js
function test(fun) {
fun();
}
// Generate a CallAnyScripted stub in test()
for (let i = 0; i < 20; i++) {
test(function() { /* wheeee */ });
}
class foo {
constructor() { }
}
// Compile foo()
for (let i = 0; i < 11; i++)
new foo();
try {
test(foo);
throw new Error("Invoking a class constructor without new must throw");
} catch (e) {
if (!(e instanceof TypeError))
throw e;
}
```
vs
```js
function test(fun) {
fun();
}
for (let i = 0;i < 20;i++) {
test(function() { });
}
class foo {
constructor() { }
}
for (let i = 0;i < 11;i++) new foo();
try {
test(foo);
throw new Error("Invoking a class constructor without new must throw");
} catch (e) {
if (!e instanceof TypeError) throw e;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/baseline/classConstructor-AnyScripted.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/precedence-3.js)
<details>
```js
// MagicNumber = 0x6d736100;
const magic0 = 0x00; // '\0'
const magic1 = 0x61; // 'a'
const magic2 = 0x73; // 's'
const magic3 = 0x6d; // 'm'
// EncodingVersion
const encodingVersion = 0x1;
const ver0 = (encodingVersion >>> 0) & 0xff;
const ver1 = (encodingVersion >>> 8) & 0xff;
const ver2 = (encodingVersion >>> 16) & 0xff;
const ver3 = (encodingVersion >>> 24) & 0xff;
// Section opcodes
const userDefinedId = 0;
const typeId = 1;
const importId = 2;
const functionId = 3;
const tableId = 4;
const memoryId = 5;
const globalId = 6;
const exportId = 7;
const startId = 8;
const elemId = 9;
const codeId = 10;
const dataId = 11;
const gcFeatureOptInId = 42;
// User-defined section names
const nameName = "name";
// Name section name types
const nameTypeModule = 0;
const nameTypeFunction = 1;
const nameTypeLocal = 2;
// Type codes
const I32Code = 0x7f;
const I64Code = 0x7e;
const F32Code = 0x7d;
const F64Code = 0x7c;
const AnyFuncCode = 0x70;
const AnyrefCode = 0x6f;
const RefCode = 0x6e;
const FuncCode = 0x60;
const VoidCode = 0x40;
// Opcodes
const UnreachableCode = 0x00
const BlockCode = 0x02;
const EndCode = 0x0b;
const CallCode = 0x10;
const CallIndirectCode = 0x11;
const DropCode = 0x1a;
const SelectCode = 0x1b;
const I32Load = 0x28;
const I64Load = 0x29;
const F32Load = 0x2a;
const F64Load = 0x2b;
const I32Load8S = 0x2c;
const I32Load8U = 0x2d;
const I32Load16S = 0x2e;
const I32Load16U = 0x2f;
const I64Load8S = 0x30;
const I64Load8U = 0x31;
const I64Load16S = 0x32;
const I64Load16U = 0x33;
const I64Load32S = 0x34;
const I64Load32U = 0x35;
const I32Store = 0x36;
const I64Store = 0x37;
const F32Store = 0x38;
const F64Store = 0x39;
const I32Store8 = 0x3a;
const I32Store16 = 0x3b;
const I64Store8 = 0x3c;
const I64Store16 = 0x3d;
const I64Store32 = 0x3e;
const GrowMemoryCode = 0x40;
const I32ConstCode = 0x41;
const I64ConstCode = 0x42;
const F32ConstCode = 0x43;
const F64ConstCode = 0x44;
const I32AddCode = 0x6a;
const I32DivSCode = 0x6d;
const I32DivUCode = 0x6e;
const I32RemSCode = 0x6f;
const I32RemUCode = 0x70;
const I32TruncSF32Code = 0xa8;
const I32TruncUF32Code = 0xa9;
const I32TruncSF64Code = 0xaa;
const I32TruncUF64Code = 0xab;
const I64TruncSF32Code = 0xae;
const I64TruncUF32Code = 0xaf;
const I64TruncSF64Code = 0xb0;
const I64TruncUF64Code = 0xb1;
const I64DivSCode = 0x7f;
const I64DivUCode = 0x80;
const I64RemSCode = 0x81;
const I64RemUCode = 0x82;
const RefNull = 0xd0;
const FirstInvalidOpcode = 0xc5;
const LastInvalidOpcode = 0xfb;
const MiscPrefix = 0xfc;
const SimdPrefix = 0xfd;
const ThreadPrefix = 0xfe;
const MozPrefix = 0xff;
// Secondary opcode bytes for misc prefix
const StructNew = 0x50; // UNOFFICIAL
const StructGet = 0x51; // UNOFFICIAL
const StructSet = 0x52; // UNOFFICIAL
const StructNarrow = 0x53; // UNOFFICIAL
// DefinitionKind
const FunctionCode = 0x00;
const TableCode = 0x01;
const MemoryCode = 0x02;
const GlobalCode = 0x03;
// ResizableFlags
const HasMaximumFlag = 0x1;
function toU8(array) {
for (let b of array)
assertEq(b < 256, true);
return Uint8Array.from(array);
}
function varU32(u32) {
assertEq(u32 >= 0, true);
assertEq(u32 < Math.pow(2,32), true);
var bytes = [];
do {
var byte = u32 & 0x7f;
u32 >>>= 7;
if (u32 != 0)
byte |= 0x80;
bytes.push(byte);
} while (u32 != 0);
return bytes;
}
function varS32(s32) {
assertEq(s32 >= -Math.pow(2,31), true);
assertEq(s32 < Math.pow(2,31), true);
var bytes = [];
do {
var byte = s32 & 0x7f;
s32 >>= 7;
if (s32 != 0 && s32 != -1)
byte |= 0x80;
bytes.push(byte);
} while (s32 != 0 && s32 != -1);
return bytes;
}
function moduleHeaderThen(...rest) {
return [magic0, magic1, magic2, magic3, ver0, ver1, ver2, ver3, ...rest];
}
function string(name) {
var nameBytes = name.split('').map(c => {
var code = c.charCodeAt(0);
assertEq(code < 128, true); // TODO
return code
});
return varU32(nameBytes.length).concat(nameBytes);
}
function encodedString(name, len) {
var name = unescape(encodeURIComponent(name)); // break into string of utf8 code points
var nameBytes = name.split('').map(c => c.charCodeAt(0)); // map to array of numbers
return varU32(len === undefined ? nameBytes.length : len).concat(nameBytes);
}
function moduleWithSections(sectionArray) {
var bytes = moduleHeaderThen();
for (let section of sectionArray) {
bytes.push(section.name);
bytes.push(...varU32(section.body.length));
bytes.push(...section.body);
}
return toU8(bytes);
}
function gcFeatureOptInSection(version) {
return { name: gcFeatureOptInId, body: [ version & 0x7F ] }
}
function sigSection(sigs) {
var body = [];
body.push(...varU32(sigs.length));
for (let sig of sigs) {
body.push(...varU32(FuncCode));
body.push(...varU32(sig.args.length));
for (let arg of sig.args)
body.push(...varU32(arg));
body.push(...varU32(sig.ret == VoidCode ? 0 : 1));
if (sig.ret != VoidCode)
body.push(...varU32(sig.ret));
}
return { name: typeId, body };
}
function declSection(decls) {
var body = [];
body.push(...varU32(decls.length));
for (let decl of decls)
body.push(...varU32(decl));
return { name: functionId, body };
}
function funcBody(func, withEndCode=true) {
var body = varU32(func.locals.length);
for (let local of func.locals)
body.push(...varU32(local));
body = body.concat(...func.body);
if (withEndCode)
body.push(EndCode);
body.splice(0, 0, ...varU32(body.length));
return body;
}
function bodySection(bodies) {
var body = varU32(bodies.length).concat(...bodies);
return { name: codeId, body };
}
function importSection(imports) {
var body = [];
body.push(...varU32(imports.length));
for (let imp of imports) {
body.push(...string(imp.module));
body.push(...string(imp.func));
body.push(...varU32(FunctionCode));
body.push(...varU32(imp.sigIndex));
}
return { name: importId, body };
}
function exportSection(exports) {
var body = [];
body.push(...varU32(exports.length));
for (let exp of exports) {
body.push(...string(exp.name));
body.push(...varU32(FunctionCode));
body.push(...varU32(exp.funcIndex));
}
return { name: exportId, body };
}
function tableSection(initialSize) {
var body = [];
body.push(...varU32(1)); // number of tables
body.push(...varU32(AnyFuncCode));
body.push(...varU32(0x0)); // for now, no maximum
body.push(...varU32(initialSize));
return { name: tableId, body };
}
function memorySection(initialSize) {
var body = [];
body.push(...varU32(1)); // number of memories
body.push(...varU32(0x0)); // for now, no maximum
body.push(...varU32(initialSize));
return { name: memoryId, body };
}
function dataSection(segmentArrays) {
var body = [];
body.push(...varU32(segmentArrays.length));
for (let array of segmentArrays) {
body.push(...varU32(0)); // table index
body.push(...varU32(I32ConstCode));
body.push(...varS32(array.offset));
body.push(...varU32(EndCode));
body.push(...varU32(array.elems.length));
for (let elem of array.elems)
body.push(...varU32(elem));
}
return { name: dataId, body };
}
function elemSection(elemArrays) {
var body = [];
body.push(...varU32(elemArrays.length));
for (let array of elemArrays) {
body.push(...varU32(0)); // table index
body.push(...varU32(I32ConstCode));
body.push(...varS32(array.offset));
body.push(...varU32(EndCode));
body.push(...varU32(array.elems.length));
for (let elem of array.elems)
body.push(...varU32(elem));
}
return { name: elemId, body };
}
function moduleNameSubsection(moduleName) {
var body = [];
body.push(...varU32(nameTypeModule));
var subsection = encodedString(moduleName);
body.push(...varU32(subsection.length));
body.push(...subsection);
return body;
}
function funcNameSubsection(funcNames) {
var body = [];
body.push(...varU32(nameTypeFunction));
var subsection = varU32(funcNames.length);
var funcIndex = 0;
for (let f of funcNames) {
subsection.push(...varU32(f.index ? f.index : funcIndex));
subsection.push(...encodedString(f.name, f.nameLen));
funcIndex++;
}
body.push(...varU32(subsection.length));
body.push(...subsection);
return body;
}
function nameSection(subsections) {
var body = [];
body.push(...string(nameName));
for (let ss of subsections)
body.push(...ss);
return { name: userDefinedId, body };
}
function customSection(name, ...body) {
return { name: userDefinedId, body: [...string(name), ...body] };
}
function tableSection0() {
var body = [];
body.push(...varU32(0)); // number of tables
return { name: tableId, body };
}
function memorySection0() {
var body = [];
body.push(...varU32(0)); // number of memories
return { name: memoryId, body };
}
```
vs
```js
const magic0 = 0x00;
const magic1 = 0x61;
const magic2 = 0x73;
const magic3 = 0x6d;
const encodingVersion = 0x1;
const ver0 = encodingVersion >>> 0 & 0xff;
const ver1 = encodingVersion >>> 8 & 0xff;
const ver2 = encodingVersion >>> 16 & 0xff;
const ver3 = encodingVersion >>> 24 & 0xff;
const userDefinedId = 0;
const typeId = 1;
const importId = 2;
const functionId = 3;
const tableId = 4;
const memoryId = 5;
const globalId = 6;
const exportId = 7;
const startId = 8;
const elemId = 9;
const codeId = 10;
const dataId = 11;
const gcFeatureOptInId = 42;
const nameName = "name";
const nameTypeModule = 0;
const nameTypeFunction = 1;
const nameTypeLocal = 2;
const I32Code = 0x7f;
const I64Code = 0x7e;
const F32Code = 0x7d;
const F64Code = 0x7c;
const AnyFuncCode = 0x70;
const AnyrefCode = 0x6f;
const RefCode = 0x6e;
const FuncCode = 0x60;
const VoidCode = 0x40;
const UnreachableCode = 0x00;
const BlockCode = 0x02;
const EndCode = 0x0b;
const CallCode = 0x10;
const CallIndirectCode = 0x11;
const DropCode = 0x1a;
const SelectCode = 0x1b;
const I32Load = 0x28;
const I64Load = 0x29;
const F32Load = 0x2a;
const F64Load = 0x2b;
const I32Load8S = 0x2c;
const I32Load8U = 0x2d;
const I32Load16S = 0x2e;
const I32Load16U = 0x2f;
const I64Load8S = 0x30;
const I64Load8U = 0x31;
const I64Load16S = 0x32;
const I64Load16U = 0x33;
const I64Load32S = 0x34;
const I64Load32U = 0x35;
const I32Store = 0x36;
const I64Store = 0x37;
const F32Store = 0x38;
const F64Store = 0x39;
const I32Store8 = 0x3a;
const I32Store16 = 0x3b;
const I64Store8 = 0x3c;
const I64Store16 = 0x3d;
const I64Store32 = 0x3e;
const GrowMemoryCode = 0x40;
const I32ConstCode = 0x41;
const I64ConstCode = 0x42;
const F32ConstCode = 0x43;
const F64ConstCode = 0x44;
const I32AddCode = 0x6a;
const I32DivSCode = 0x6d;
const I32DivUCode = 0x6e;
const I32RemSCode = 0x6f;
const I32RemUCode = 0x70;
const I32TruncSF32Code = 0xa8;
const I32TruncUF32Code = 0xa9;
const I32TruncSF64Code = 0xaa;
const I32TruncUF64Code = 0xab;
const I64TruncSF32Code = 0xae;
const I64TruncUF32Code = 0xaf;
const I64TruncSF64Code = 0xb0;
const I64TruncUF64Code = 0xb1;
const I64DivSCode = 0x7f;
const I64DivUCode = 0x80;
const I64RemSCode = 0x81;
const I64RemUCode = 0x82;
const RefNull = 0xd0;
const FirstInvalidOpcode = 0xc5;
const LastInvalidOpcode = 0xfb;
const MiscPrefix = 0xfc;
const SimdPrefix = 0xfd;
const ThreadPrefix = 0xfe;
const MozPrefix = 0xff;
const StructNew = 0x50;
const StructGet = 0x51;
const StructSet = 0x52;
const StructNarrow = 0x53;
const FunctionCode = 0x00;
const TableCode = 0x01;
const MemoryCode = 0x02;
const GlobalCode = 0x03;
const HasMaximumFlag = 0x1;
function toU8(array) {
for (b of array) assertEq(b < 256, true);
return Uint8Array.from(array);
}
function varU32(u32) {
assertEq(u32 >= 0, true);
assertEq(u32 < Math.pow(2, 32), true);
var bytes = [];
do {
var byte = u32 & 0x7f;
u32 >>>= 7;
if (u32 != 0) byte |= 0x80;
bytes.push(byte);
} while (u32 != 0);
;
return bytes;
}
function varS32(s32) {
assertEq(s32 >= -Math.pow(2, 31), true);
assertEq(s32 < Math.pow(2, 31), true);
var bytes = [];
do {
var byte = s32 & 0x7f;
s32 >>= 7;
if (s32 != 0 && s32 != -1) byte |= 0x80;
bytes.push(byte);
} while (s32 != 0 && s32 != -1);
;
return bytes;
}
function moduleHeaderThen(rest) {
return [magic0, magic1, magic2, magic3, ver0, ver1, ver2, ver3, ...rest,];
}
function string(name) {
var nameBytes = name.split('').map(c => {
var code = c.charCodeAt(0);
assertEq(code < 128, true);
return code;
});
return varU32(nameBytes.length).concat(nameBytes);
}
function encodedString(name, len) {
var name = unescape(encodeURIComponent(name));
var nameBytes = name.split('').map(c => c.charCodeAt(0));
return varU32(len === undefined ? nameBytes.length : len).concat(nameBytes);
}
function moduleWithSections(sectionArray) {
var bytes = moduleHeaderThen();
for (section of sectionArray) {
bytes.push(section.name);
bytes.push(...varU32(section.body.length));
bytes.push(...section.body);
}
return toU8(bytes);
}
function gcFeatureOptInSection(version) {
return {
name: gcFeatureOptInId,
body: [version & 0x7F,],
};
}
function sigSection(sigs) {
var body = [];
body.push(...varU32(sigs.length));
for (sig of sigs) {
body.push(...varU32(FuncCode));
body.push(...varU32(sig.args.length));
for (arg of sig.args) body.push(...varU32(arg));
body.push(...varU32(sig.ret == VoidCode ? 0 : 1));
if (sig.ret != VoidCode) body.push(...varU32(sig.ret));
}
return {
name: typeId,
body,
};
}
function declSection(decls) {
var body = [];
body.push(...varU32(decls.length));
for (decl of decls) body.push(...varU32(decl));
return {
name: functionId,
body,
};
}
function funcBody(func, withEndCode = true) {
var body = varU32(func.locals.length);
for (local of func.locals) body.push(...varU32(local));
body = body.concat(...func.body);
if (withEndCode) body.push(EndCode);
body.splice(0, 0, ...varU32(body.length));
return body;
}
function bodySection(bodies) {
var body = varU32(bodies.length).concat(...bodies);
return {
name: codeId,
body,
};
}
function importSection(imports) {
var body = [];
body.push(...varU32(imports.length));
for (imp of imports) {
body.push(...string(imp.module));
body.push(...string(imp.func));
body.push(...varU32(FunctionCode));
body.push(...varU32(imp.sigIndex));
}
return {
name: importId,
body,
};
}
function exportSection(exports) {
var body = [];
body.push(...varU32(exports.length));
for (exp of exports) {
body.push(...string(exp.name));
body.push(...varU32(FunctionCode));
body.push(...varU32(exp.funcIndex));
}
return {
name: exportId,
body,
};
}
function tableSection(initialSize) {
var body = [];
body.push(...varU32(1));
body.push(...varU32(AnyFuncCode));
body.push(...varU32(0x0));
body.push(...varU32(initialSize));
return {
name: tableId,
body,
};
}
function memorySection(initialSize) {
var body = [];
body.push(...varU32(1));
body.push(...varU32(0x0));
body.push(...varU32(initialSize));
return {
name: memoryId,
body,
};
}
function dataSection(segmentArrays) {
var body = [];
body.push(...varU32(segmentArrays.length));
for (array of segmentArrays) {
body.push(...varU32(0));
body.push(...varU32(I32ConstCode));
body.push(...varS32(array.offset));
body.push(...varU32(EndCode));
body.push(...varU32(array.elems.length));
for (elem of array.elems) body.push(...varU32(elem));
}
return {
name: dataId,
body,
};
}
function elemSection(elemArrays) {
var body = [];
body.push(...varU32(elemArrays.length));
for (array of elemArrays) {
body.push(...varU32(0));
body.push(...varU32(I32ConstCode));
body.push(...varS32(array.offset));
body.push(...varU32(EndCode));
body.push(...varU32(array.elems.length));
for (elem of array.elems) body.push(...varU32(elem));
}
return {
name: elemId,
body,
};
}
function moduleNameSubsection(moduleName) {
var body = [];
body.push(...varU32(nameTypeModule));
var subsection = encodedString(moduleName);
body.push(...varU32(subsection.length));
body.push(...subsection);
return body;
}
function funcNameSubsection(funcNames) {
var body = [];
body.push(...varU32(nameTypeFunction));
var subsection = varU32(funcNames.length);
var funcIndex = 0;
for (f of funcNames) {
subsection.push(...varU32(f.index ? f.index : funcIndex));
subsection.push(...encodedString(f.name, f.nameLen));
funcIndex++;
}
body.push(...varU32(subsection.length));
body.push(...subsection);
return body;
}
function nameSection(subsections) {
var body = [];
body.push(...string(nameName));
for (ss of subsections) body.push(...ss);
return {
name: userDefinedId,
body,
};
}
function customSection(name, body) {
return {
name: userDefinedId,
body: [...string(name), ...body,],
};
}
function tableSection0() {
var body = [];
body.push(...varU32(0));
return {
name: tableId,
body,
};
}
function memorySection0() {
var body = [];
body.push(...varU32(0));
return {
name: memoryId,
body,
};
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/wasm-binary.js)
* [Unexpected Token at line: 42, column: 27: Expected `function`, `this`, `class`, or `import`; found Keyword(Await)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/saved-stacks/1438121-async-function.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/bug934997.js)
<details>
```js
// Don't assert if the wrapper that's the value of stream.[[reader]] gets nuked.
load(libdir + "asserts.js");
let g = newGlobal();
let stream = new ReadableStream({
start(controller) {
controller.enqueue("ponies");
controller.close();
}
});
g.stream = stream;
g.eval("var reader = ReadableStream.prototype.getReader.call(stream);");
nukeCCW(g.reader);
assertErrorMessage(() => g.eval("reader.read()"), g.TypeError, "can't access dead object");
g.eval("reader.releaseLock();");
```
vs
```js
load(libdir + "asserts.js");
let g = newGlobal();
let stream = new ReadableStream(({
start: (function(controller) {
controller.enqueue("ponies");
controller.close();
}),
}));
g.stream = stream;
g.eval("var reader = ReadableStream.prototype.getReader.call(stream);");
nukeCCW(g.reader);
assertErrorMessage(() => g.eval("reader.read()"), g.TypeError, "can't access dead object");
g.eval("reader.releaseLock();");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/stream/bug-1503399-1.js)
<details>
```js
// |jit-test| error: Assertion failed: bad label: 2
try {
this['Module'] = Module;
} catch (e) {
this['Module'] = Module = {};
}
var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function';
var ENVIRONMENT_IS_WEB = typeof window === 'object';
var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
if (ENVIRONMENT_IS_SHELL) {
Module['print'] = print;
Module['arguments'] = [];
}
var Runtime = {
alignMemory: function alignMemory(size, quantum) {},
}
function SAFE_HEAP_CLEAR(dest) {
}
function SAFE_HEAP_STORE(dest, value, type, ignore) {
setValue(dest, value, type, 1);
}
function SAFE_HEAP_LOAD(dest, type, unsigned, ignore) {
try { } catch(e) {};
var ret = getValue(dest, type, 1);
return ret;
};
function SAFE_HEAP_LOAD1(dest, type) {
return getValue(dest, type, 1);
};
function abort(text) {
Module.print(text + ':\n' + (new Error).stack);
throw "Assertion: " + text;
}
function assert(condition, text) {
if (!condition) {
abort('Assertion failed: ' + text);
}
}
function setValue(ptr, value, type, noSafe) {
if (type.charAt(type.length - 1) === '*') type = 'i32'; // pointers are 32-bit
if (noSafe) {
switch (type) {
case 'i32':
HEAP32[((ptr) >> 2)] = value;
}
}
}
function getValue(ptr, type, noSafe) {
if (type.charAt(type.length - 1) === '*') type = 'i32'; // pointers are 32-bit
if (noSafe) {
switch (type) {
case 'i32':
return HEAP32[((ptr) >> 2)];
}
}
}
var ALLOC_STATIC = 2; // Cannot be freed
function allocate(slab, types, allocator, ptr) {}
var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216;
var buffer = new ArrayBuffer(TOTAL_MEMORY);
HEAP32 = new Int32Array(buffer);
STACK_ROOT = STACKTOP = Runtime.alignMemory(1);
function intArrayFromString(stringy, dontAddNull, length /* optional */ ) {}
function __ZN11btRigidBody14getMotionStateEv($this_0_20_val) {
}
function __ZN16btCollisionWorld23getCollisionObjectArrayEv($this) {}
function __ZN20btAlignedObjectArrayIP17btCollisionObjectEixEi($this_0_3_val, $n) {}
function _main($argc, $argv) {
label = 2;
while (1) switch (label) {
case 2:
var $31 = __Znwj(268);
var $32 = $31;
var $67 = __ZN17btCollisionObjectnwEj();
var $68 = $67;
__ZN23btDiscreteDynamicsWorld12addRigidBodyEP11btRigidBody($32, $68);
var $99 = $31;
var $104 = __ZN23btDiscreteDynamicsWorld14stepSimulationEfif($32, .01666666753590107, 10, .01666666753590107);
var $106 = __ZNK16btCollisionWorld22getNumCollisionObjectsEv($99);
var $108 = __ZN16btCollisionWorld23getCollisionObjectArrayEv($99);
var $_idx6 = $108 + 12 | 0;
var $j_049_in = $106;
var $j_049 = $j_049_in - 1 | 0;
var $_idx6_val = SAFE_HEAP_LOAD($_idx6, "%class.btCollisionObject**", 0, 0);
var $109 = __ZN20btAlignedObjectArrayIP17btCollisionObjectEixEi($_idx6_val, $j_049);
var $110 = SAFE_HEAP_LOAD($109, "%class.btCollisionObject*", 0, 0);
var $111 = __ZN11btRigidBody6upcastEP17btCollisionObject($110);
var $_idx9 = $111 + 472 | 0;
var $_idx9_val = SAFE_HEAP_LOAD($_idx9, "%class.btMotionState*", 0, 0);
var $114 = __ZN11btRigidBody14getMotionStateEv($_idx9_val);
var $138 = $i_057 + 1 | 0;
var $139 = ($138 | 0) < 135;
if ($139) {
var $i_057 = $138;
break;
}
assert(0, "bad label: " + label);
}
}
Module["_main"] = _main;
function __ZN17btCollisionObjectnwEj() {
return __Z22btAlignedAllocInternalji(608);
}
function __ZNK16btCollisionWorld22getNumCollisionObjectsEv($this) {}
function __ZN11btRigidBody6upcastEP17btCollisionObject($colObj) {
label = 2;
while (1) switch (label) {
case 2:
var $_0;
return $_0;
}
}
function __ZNK9btVector33dotERKS_($this_0_0_0_val, $this_0_0_1_val, $this_0_0_2_val, $v_0_0_0_val, $v_0_0_1_val, $v_0_0_2_val) {
}
function __ZN20btAlignedObjectArrayIP11btRigidBodyEixEi($this_0_3_val, $n) {}
function __ZNK17btCollisionObject14getHitFractionEv($this_0_21_val) {}
function __ZN17btCollisionObject30getInterpolationWorldTransformEv($this) {}
function __ZNK17btCollisionObject30getInterpolationLinearVelocityEv($this) {}
function __ZNK17btCollisionObject31getInterpolationAngularVelocityEv($this) {}
function __ZN23btDiscreteDynamicsWorld28synchronizeSingleMotionStateEP11btRigidBody($this, $body) {
assertEq($body, 16);
var __stackBase__ = STACKTOP;
while (1) switch (label) {
case 2:
var $interpolatedTransform = __stackBase__;
var $4 = $body | 0;
var $7 = __ZN17btCollisionObject30getInterpolationWorldTransformEv($4);
var $8 = __ZNK17btCollisionObject30getInterpolationLinearVelocityEv($4);
var $9 = __ZNK17btCollisionObject31getInterpolationAngularVelocityEv($4);
var $10 = $this + 236 | 0;
var $11 = SAFE_HEAP_LOAD($10, "float", 0, 0);
var $_idx2 = $body + 240 | 0;
var $_idx2_val = SAFE_HEAP_LOAD($_idx2, "float", 0, 0);
var $12 = __ZNK17btCollisionObject14getHitFractionEv($_idx2_val);
var $13 = $11 * $12;
var $_idx3 = $8 | 0;
var $_idx3_val = SAFE_HEAP_LOAD($_idx3, "float", 0, 0);
var $_idx4 = $8 + 4 | 0;
var $_idx4_val = SAFE_HEAP_LOAD($_idx4, "float", 0, 0);
var $_idx5 = $8 + 8 | 0;
var $_idx5_val = SAFE_HEAP_LOAD($_idx5, "float", 0, 0);
__ZN15btTransformUtil18integrateTransformERK11btTransformRK9btVector3S5_fRS0_($7, $_idx3_val, $_idx4_val, $_idx5_val, $9, $13, $interpolatedTransform);
return;
}
}
function __ZN15btTransformUtil18integrateTransformERK11btTransformRK9btVector3S5_fRS0_($curTrans, $linvel_0_0_0_val, $linvel_0_0_1_val, $linvel_0_0_2_val, $angvel, $timeStep, $predictedTransform) {
var __stackBase__ = STACKTOP;
STACKTOP = STACKTOP + 132 | 0;
while (1) {
switch (label) {
case 2:
var $axis = __stackBase__ + 32;
var $3 = __stackBase__ + 48;
var $angvel_idx10 = $angvel | 0;
var $angvel_idx10_val = SAFE_HEAP_LOAD($angvel_idx10, "float", 0, 0);
var $angvel_idx11 = $angvel + 4 | 0;
var $angvel_idx11_val = SAFE_HEAP_LOAD($angvel_idx11, "float", 0, 0);
var $angvel_idx12 = $angvel + 8 | 0;
var $angvel_idx12_val = SAFE_HEAP_LOAD($angvel_idx12, "float", 0, 0);
var $7 = __ZNK9btVector36lengthEv($angvel_idx10_val, $angvel_idx11_val, $angvel_idx12_val);
var $8 = $7 * $timeStep;
if ($8 > .7853981852531433) {} else {
var $fAngle_0 = $7;
label = 5;
}
break;
case 5:
var $22 = $axis;
var $23 = $3;
SAFE_HEAP_STORE($22 + 12, SAFE_HEAP_LOAD1($23 + 12, "i32"), "i32", 0);
assertEq(SAFE_HEAP_LOAD1(0, "%class.btRigidBody*"), 16);
label = 7;
break;
case 6:
SAFE_HEAP_STORE($29 + 12, SAFE_HEAP_LOAD1($30 + 12, "i32"), "i32", 0);
case 7:
for (var i = __stackBase__; i < STACKTOP; i++) SAFE_HEAP_CLEAR(i);
return;
}
}
}
function __ZN23btDiscreteDynamicsWorld12addRigidBodyEP11btRigidBody($this, $body) {
SAFE_HEAP_STORE(STACKTOP, $body, "%class.btRigidBody*", 0);
assertEq(SAFE_HEAP_LOAD(0, "%class.btRigidBody*", 0, 0), 16);
}
function __ZN23btDiscreteDynamicsWorld23synchronizeMotionStatesEv($this) {
var $20 = SAFE_HEAP_LOAD(0, "%class.btRigidBody*", 0, 0);
assertEq($20, 16);
__ZN23btDiscreteDynamicsWorld28synchronizeSingleMotionStateEP11btRigidBody($this, $20);
}
function __ZN23btDiscreteDynamicsWorld14stepSimulationEfif($this, $timeStep, $maxSubSteps, $fixedTimeStep) {
label = 2;
while (1) switch (label) {
case 2:
var $numSimulationSubSteps_0;
__ZN23btDiscreteDynamicsWorld23synchronizeMotionStatesEv($this);
return $numSimulationSubSteps_0;
}
}
function __ZNK9btVector37length2Ev($this_0_0_0_val, $this_0_0_1_val, $this_0_0_2_val) {
return __ZNK9btVector33dotERKS_($this_0_0_0_val, $this_0_0_1_val, $this_0_0_2_val, $this_0_0_0_val, $this_0_0_1_val, $this_0_0_2_val);
}
function __Z6btSqrtf($y) {
return Math.sqrt($y);
}
function __ZNK9btVector36lengthEv($this_0_0_0_val, $this_0_0_1_val, $this_0_0_2_val) {
return __Z6btSqrtf(__ZNK9btVector37length2Ev($this_0_0_0_val, $this_0_0_1_val, $this_0_0_2_val));
}
function __ZL21btAlignedAllocDefaultji($size, $alignment) {
while (1) switch (label) {
case 2:
var $1 = $size + 4 | 0;
var $2 = $alignment - 1 | 0;
var $3 = $1 + $2 | 0;
var $4 = __ZL14btAllocDefaultj($3);
var $7 = $4 + 4 | 0;
var $8 = $7;
var $9 = $alignment - $8 | 0;
var $10 = $9 & $2;
var $_sum = $10 + 4 | 0;
var $11 = $4 + $_sum | 0;
var $ret_0 = $11;
return $ret_0;
}
}
function __ZL14btAllocDefaultj($size) {
return _malloc($size);
}
function __Z22btAlignedAllocInternalji($size) {
return __ZL21btAlignedAllocDefaultji($size, 16);
}
function _malloc($bytes) {
while (1) switch (label) {
case 2:
var $189 = SAFE_HEAP_LOAD(5244020, "%struct.malloc_chunk*", 0, 0);
var $198 = $189 + 8 | 0;
var $199 = $198;
var $mem_0 = $199;
return $mem_0;
}
}
function __Znwj($size) {
while (1) switch (label) {
case 2:
var $1 = ($size | 0) == 0;
var $_size = $1 ? 1 : $size;
var $3 = _malloc($_size);
return $3;
}
}
Module.callMain = function callMain(args) {
var argc = args.length + 1;
var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_STATIC)];
return Module['_main'](argc, argv, 0);
}
function run(args) {
args = args || Module['arguments'];
function doRun() {
if (Module['_main']) {
ret = Module.callMain(args);
}
}
if (Module['setStatus']) {} else {
return doRun();
}
}
run();
```
vs
```js
try {
this['Module'] = Module;
} catch (e) {
this['Module'] = Module = ({ });
}
var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function';
var ENVIRONMENT_IS_WEB = typeof window === 'object';
var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
if (ENVIRONMENT_IS_SHELL) {
Module['print'] = print;
Module['arguments'] = [];
}
var Runtime = ({
alignMemory: (function alignMemory(size, quantum) { }),
});
function SAFE_HEAP_CLEAR(dest) { }
function SAFE_HEAP_STORE(dest, value, type, ignore) {
setValue(dest, value, type, 1);
}
function SAFE_HEAP_LOAD(dest, type, unsigned, ignore) {
try {
} catch (e) {
}
;
var ret = getValue(dest, type, 1);
return ret;
}
;
function SAFE_HEAP_LOAD1(dest, type) {
return getValue(dest, type, 1);
}
;
function abort(text) {
Module.print(text + ':\n' + new Error().stack);
throw "Assertion: " + text;
}
function assert(condition, text) {
if (!condition) {
abort('Assertion failed: ' + text);
}
}
function setValue(ptr, value, type, noSafe) {
if (type.charAt(type.length - 1) === '*') type = 'i32';
if (noSafe) {
switch (type) {
case 'i32':
HEAP32[ptr >> 2] = value;
}
}
}
function getValue(ptr, type, noSafe) {
if (type.charAt(type.length - 1) === '*') type = 'i32';
if (noSafe) {
switch (type) {
case 'i32':
return HEAP32[ptr >> 2];
}
}
}
var ALLOC_STATIC = 2;
function allocate(slab, types, allocator, ptr) { }
var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216;
var buffer = new ArrayBuffer(TOTAL_MEMORY);
HEAP32 = new Int32Array(buffer);
STACK_ROOT = STACKTOP = Runtime.alignMemory(1);
function intArrayFromString(stringy, dontAddNull, length) { }
function __ZN11btRigidBody14getMotionStateEv($this_0_20_val) { }
function __ZN16btCollisionWorld23getCollisionObjectArrayEv($this) { }
function __ZN20btAlignedObjectArrayIP17btCollisionObjectEixEi($this_0_3_val, $n) { }
function _main($argc, $argv) {
label = 2;
while (1) switch (label) {
case 2:
var $31 = __Znwj(268);
var $32 = $31;
var $67 = __ZN17btCollisionObjectnwEj();
var $68 = $67;
__ZN23btDiscreteDynamicsWorld12addRigidBodyEP11btRigidBody($32, $68);
var $99 = $31;
var $104 = __ZN23btDiscreteDynamicsWorld14stepSimulationEfif($32, .01666666753590107, 10, .01666666753590107);
var $106 = __ZNK16btCollisionWorld22getNumCollisionObjectsEv($99);
var $108 = __ZN16btCollisionWorld23getCollisionObjectArrayEv($99);
var $_idx6 = $108 + 12 | 0;
var $j_049_in = $106;
var $j_049 = $j_049_in - 1 | 0;
var $_idx6_val = SAFE_HEAP_LOAD($_idx6, "%class.btCollisionObject**", 0, 0);
var $109 = __ZN20btAlignedObjectArrayIP17btCollisionObjectEixEi($_idx6_val, $j_049);
var $110 = SAFE_HEAP_LOAD($109, "%class.btCollisionObject*", 0, 0);
var $111 = __ZN11btRigidBody6upcastEP17btCollisionObject($110);
var $_idx9 = $111 + 472 | 0;
var $_idx9_val = SAFE_HEAP_LOAD($_idx9, "%class.btMotionState*", 0, 0);
var $114 = __ZN11btRigidBody14getMotionStateEv($_idx9_val);
var $138 = $i_057 + 1 | 0;
var $139 = $138 | 0 < 135;
if ($139) {
var $i_057 = $138;
break;
}
assert(0, "bad label: " + label);
}
}
Module["_main"] = _main;
function __ZN17btCollisionObjectnwEj() {
return __Z22btAlignedAllocInternalji(608);
}
function __ZNK16btCollisionWorld22getNumCollisionObjectsEv($this) { }
function __ZN11btRigidBody6upcastEP17btCollisionObject($colObj) {
label = 2;
while (1) switch (label) {
case 2:
var $_0;
return $_0;
}
}
function __ZNK9btVector33dotERKS_($this_0_0_0_val, $this_0_0_1_val, $this_0_0_2_val, $v_0_0_0_val, $v_0_0_1_val, $v_0_0_2_val) { }
function __ZN20btAlignedObjectArrayIP11btRigidBodyEixEi($this_0_3_val, $n) { }
function __ZNK17btCollisionObject14getHitFractionEv($this_0_21_val) { }
function __ZN17btCollisionObject30getInterpolationWorldTransformEv($this) { }
function __ZNK17btCollisionObject30getInterpolationLinearVelocityEv($this) { }
function __ZNK17btCollisionObject31getInterpolationAngularVelocityEv($this) { }
function __ZN23btDiscreteDynamicsWorld28synchronizeSingleMotionStateEP11btRigidBody($this, $body) {
assertEq($body, 16);
var __stackBase__ = STACKTOP;
while (1) switch (label) {
case 2:
var $interpolatedTransform = __stackBase__;
var $4 = $body | 0;
var $7 = __ZN17btCollisionObject30getInterpolationWorldTransformEv($4);
var $8 = __ZNK17btCollisionObject30getInterpolationLinearVelocityEv($4);
var $9 = __ZNK17btCollisionObject31getInterpolationAngularVelocityEv($4);
var $10 = $this + 236 | 0;
var $11 = SAFE_HEAP_LOAD($10, "float", 0, 0);
var $_idx2 = $body + 240 | 0;
var $_idx2_val = SAFE_HEAP_LOAD($_idx2, "float", 0, 0);
var $12 = __ZNK17btCollisionObject14getHitFractionEv($_idx2_val);
var $13 = $11 * $12;
var $_idx3 = $8 | 0;
var $_idx3_val = SAFE_HEAP_LOAD($_idx3, "float", 0, 0);
var $_idx4 = $8 + 4 | 0;
var $_idx4_val = SAFE_HEAP_LOAD($_idx4, "float", 0, 0);
var $_idx5 = $8 + 8 | 0;
var $_idx5_val = SAFE_HEAP_LOAD($_idx5, "float", 0, 0);
__ZN15btTransformUtil18integrateTransformERK11btTransformRK9btVector3S5_fRS0_($7, $_idx3_val, $_idx4_val, $_idx5_val, $9, $13, $interpolatedTransform);
return;
}
}
function __ZN15btTransformUtil18integrateTransformERK11btTransformRK9btVector3S5_fRS0_($curTrans, $linvel_0_0_0_val, $linvel_0_0_1_val, $linvel_0_0_2_val, $angvel, $timeStep, $predictedTransform) {
var __stackBase__ = STACKTOP;
STACKTOP = STACKTOP + 132 | 0;
while (1) {
switch (label) {
case 2:
var $axis = __stackBase__ + 32;
var $3 = __stackBase__ + 48;
var $angvel_idx10 = $angvel | 0;
var $angvel_idx10_val = SAFE_HEAP_LOAD($angvel_idx10, "float", 0, 0);
var $angvel_idx11 = $angvel + 4 | 0;
var $angvel_idx11_val = SAFE_HEAP_LOAD($angvel_idx11, "float", 0, 0);
var $angvel_idx12 = $angvel + 8 | 0;
var $angvel_idx12_val = SAFE_HEAP_LOAD($angvel_idx12, "float", 0, 0);
var $7 = __ZNK9btVector36lengthEv($angvel_idx10_val, $angvel_idx11_val, $angvel_idx12_val);
var $8 = $7 * $timeStep;
if ($8 > .7853981852531433) {
} else {
var $fAngle_0 = $7;
label = 5;
}
break;
case 5:
var $22 = $axis;
var $23 = $3;
SAFE_HEAP_STORE($22 + 12, SAFE_HEAP_LOAD1($23 + 12, "i32"), "i32", 0);
assertEq(SAFE_HEAP_LOAD1(0, "%class.btRigidBody*"), 16);
label = 7;
break;
case 6:
SAFE_HEAP_STORE($29 + 12, SAFE_HEAP_LOAD1($30 + 12, "i32"), "i32", 0);
case 7:
for (let i = __stackBase__;i < STACKTOP;i++) SAFE_HEAP_CLEAR(i);
return;
}
}
}
function __ZN23btDiscreteDynamicsWorld12addRigidBodyEP11btRigidBody($this, $body) {
SAFE_HEAP_STORE(STACKTOP, $body, "%class.btRigidBody*", 0);
assertEq(SAFE_HEAP_LOAD(0, "%class.btRigidBody*", 0, 0), 16);
}
function __ZN23btDiscreteDynamicsWorld23synchronizeMotionStatesEv($this) {
var $20 = SAFE_HEAP_LOAD(0, "%class.btRigidBody*", 0, 0);
assertEq($20, 16);
__ZN23btDiscreteDynamicsWorld28synchronizeSingleMotionStateEP11btRigidBody($this, $20);
}
function __ZN23btDiscreteDynamicsWorld14stepSimulationEfif($this, $timeStep, $maxSubSteps, $fixedTimeStep) {
label = 2;
while (1) switch (label) {
case 2:
var $numSimulationSubSteps_0;
__ZN23btDiscreteDynamicsWorld23synchronizeMotionStatesEv($this);
return $numSimulationSubSteps_0;
}
}
function __ZNK9btVector37length2Ev($this_0_0_0_val, $this_0_0_1_val, $this_0_0_2_val) {
return __ZNK9btVector33dotERKS_($this_0_0_0_val, $this_0_0_1_val, $this_0_0_2_val, $this_0_0_0_val, $this_0_0_1_val, $this_0_0_2_val);
}
function __Z6btSqrtf($y) {
return Math.sqrt($y);
}
function __ZNK9btVector36lengthEv($this_0_0_0_val, $this_0_0_1_val, $this_0_0_2_val) {
return __Z6btSqrtf(__ZNK9btVector37length2Ev($this_0_0_0_val, $this_0_0_1_val, $this_0_0_2_val));
}
function __ZL21btAlignedAllocDefaultji($size, $alignment) {
while (1) switch (label) {
case 2:
var $1 = $size + 4 | 0;
var $2 = $alignment - 1 | 0;
var $3 = $1 + $2 | 0;
var $4 = __ZL14btAllocDefaultj($3);
var $7 = $4 + 4 | 0;
var $8 = $7;
var $9 = $alignment - $8 | 0;
var $10 = $9 & $2;
var $_sum = $10 + 4 | 0;
var $11 = $4 + $_sum | 0;
var $ret_0 = $11;
return $ret_0;
}
}
function __ZL14btAllocDefaultj($size) {
return _malloc($size);
}
function __Z22btAlignedAllocInternalji($size) {
return __ZL21btAlignedAllocDefaultji($size, 16);
}
function _malloc($bytes) {
while (1) switch (label) {
case 2:
var $189 = SAFE_HEAP_LOAD(5244020, "%struct.malloc_chunk*", 0, 0);
var $198 = $189 + 8 | 0;
var $199 = $198;
var $mem_0 = $199;
return $mem_0;
}
}
function __Znwj($size) {
while (1) switch (label) {
case 2:
var $1 = $size | 0 == 0;
var $_size = $1 ? 1 : $size;
var $3 = _malloc($_size);
return $3;
}
}
Module.callMain = (function callMain(args) {
var argc = args.length + 1;
var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_STATIC),];
return Module['_main'](argc, argv, 0);
});
function run(args) {
args = args || Module['arguments'];
function doRun() {
if (Module['_main']) {
ret = Module.callMain(args);
}
}
if (Module['setStatus']) {
} else {
return doRun();
}
}
run();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/bug830943.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/typeof.js)
* [Unexpected Token at line: 6, column: 14: Expected `variable identifier`; found Keyword(Await)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/bug1302432.js)
<details>
```js
g = newGlobal()
g.parent = this
g.eval("Debugger(parent).onExceptionUnwind=(function(){})")
try {
function f(code) {
n = parseInt('', 0);
return g("try{}catch(e){}", n)
}
function g(s, n) {
s2 = s + s
d = (n - (function () {
return "" + this.id + eval.id;
} )().abstract) / 2
m = g(s2, d)
}
f("switch(''){default:break;}")
} catch(exc1) {}
```
vs
```js
g = newGlobal();
g.parent = this;
g.eval("Debugger(parent).onExceptionUnwind=(function(){})");
try {
function f(code) {
n = parseInt('', 0);
return g("try{}catch(e){}", n);
}
function g(s, n) {
s2 = s + s;
d = n - function() {
return "" + this.id + eval.id;
}().abstract / 2;
m = g(s2, d);
}
f("switch(''){default:break;}");
} catch (exc1) {
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/bug1111199.js)
<details>
```js
// Funny case that looks kind of like default arguments isn't.
var f = (msg='hi', w=window => w.alert(a, b)); // sequence expression
assertEq(msg, 'hi');
assertEq(typeof w, 'function');
assertEq(f, w);
```
vs
```js
var f = msg = 'hi', w = window => w.alert(a, b);
assertEq(msg, 'hi');
assertEq(typeof w, 'function');
assertEq(f, w);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/precedence-4.js)
<details>
```js
// |jit-test| error: TypeError
"use strict";
setJitCompilerOption("baseline.warmup.trigger", 0);
let moduleRepo = {};
setModuleResolveHook(function(module, specifier) {
if (specifier in moduleRepo)
return moduleRepo[specifier];
throw "Module '" + specifier + "' not found";
});
let mainSrc = `
import A from "A";
const a = A;
function requestAnimationFrame(f) { Promise.resolve().then(f); };
requestAnimationFrame(loopy);
a = 2;
function loopy() {
A;
}
`;
let ASrc = `
export default 1;
`;
moduleRepo['A'] = parseModule(ASrc);
let m = parseModule(mainSrc);
m.declarationInstantiation()
m.evaluation();
```
vs
```js
'use strict';
setJitCompilerOption("baseline.warmup.trigger", 0);
let moduleRepo = ({});
setModuleResolveHook((function(module, specifier) {
if (specifier in moduleRepo) return moduleRepo[specifier];
throw "Module '" + specifier + "' not found";
}));
let mainSrc = `
import A from "A";
const a = A;
function requestAnimationFrame(f) { Promise.resolve().then(f); };
requestAnimationFrame(loopy);
a = 2;
function loopy() {
A;
}
`;
let ASrc = `
export default 1;
`;
moduleRepo['A'] = parseModule(ASrc);
let m = parseModule(mainSrc);
m.declarationInstantiation();
m.evaluation();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/modules/bug-1443555.js)
<details>
```js
/* test Set.prototype.forEach */
load(libdir + 'asserts.js');
load(libdir + 'iteration.js');
// testing success conditions of Set.prototype.forEach
var testSet = new Set();
function callback(value, key, set) {
assertEq(value, key);
testSet.add(value);
assertEq(set.has(key), true);
}
var initialSet = new Set(['a', 1, undefined]);
initialSet.forEach(callback);
// test that both the Sets are equal and are in same order
var iterator = initialSet[Symbol.iterator]();
var count = 0;
for (var v of testSet) {
assertEq(initialSet.has(v), true);
assertIteratorNext(iterator, v);
count++;
}
//check both the Sets we have are equal in size
assertEq(initialSet.size, testSet.size);
assertEq(initialSet.size, count);
var x = { abc: 'test'};
function callback2(value, key, set) {
assertEq(x, this);
}
initialSet = new Set(['a']);
initialSet.forEach(callback2, x);
// testing failure conditions of Set.prototype.forEach
var m = new Map([['a', 1], ['b', 2.3], ['c', undefined]]);
assertThrowsInstanceOf(function() {
Set.prototype.forEach.call(m, callback);
}, TypeError, "Set.prototype.forEach should raise TypeError if not a used on a Set");
var fn = 2;
assertThrowsInstanceOf(function() {
initialSet.forEach(fn);
}, TypeError, "Set.prototype.forEach should raise TypeError if callback is not a function");
```
vs
```js
load(libdir + 'asserts.js');
load(libdir + 'iteration.js');
var testSet = new Set();
function callback(value, key, set) {
assertEq(value, key);
testSet.add(value);
assertEq(set.has(key), true);
}
var initialSet = new Set(['a', 1, undefined,]);
initialSet.forEach(callback);
var iterator = initialSet[Symbol.iterator]();
var count = 0;
for (v of testSet) {
assertEq(initialSet.has(v), true);
assertIteratorNext(iterator, v);
count++;
}
assertEq(initialSet.size, testSet.size);
assertEq(initialSet.size, count);
var x = ({
abc: 'test',
});
function callback2(value, key, set) {
assertEq(x, this);
}
initialSet = new Set(['a',]);
initialSet.forEach(callback2, x);
var m = new Map([['a', 1,], ['b', 2.3,], ['c', undefined,],]);
assertThrowsInstanceOf((function() {
Set.prototype.forEach.call(m, callback);
}), TypeError, "Set.prototype.forEach should raise TypeError if not a used on a Set");
var fn = 2;
assertThrowsInstanceOf((function() {
initialSet.forEach(fn);
}), TypeError, "Set.prototype.forEach should raise TypeError if callback is not a function");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-forEach.js)
<details>
```js
// Set breakpoints "everywhere" in a function, then call the function and check that
// the breakpoints were added are at the expected columns, and the breakpoints
// were executed in th expected order.
//
// `code` is a JS Script. The final line should define a function `f` to validate.
// `expectedBpts` is a string of spaces and carets ('^'). Throws if we don't hit
// breakpoints on exactly the columns indicated by the carets.
// `expectedOrdering` is a string of integer indices for the offsets that are
// executed, in the order that then are executed. Test code can also push
// additional items into this string using items.push("!").
function assertOffsetColumns(code, expectedBpts, expectedOrdering = null) {
if (expectedOrdering === null) {
// The default ordering simply runs the breakpoints in order.
expectedOrdering = Array.from(expectedBpts.match(/\^/g), (_, i) => i).join(" ");
}
// Define the function `f` in a new global.
const global = newGlobal();
const lines = code.split(/\r?\n|\r]/g);
const initCode = lines.slice(0, -1).join("\n");
const execCode = lines[lines.length - 1];
// Treat everything but the last line as initialization code.
global.eval(initCode);
// Run the test code itself.
global.eval(execCode);
// Allow some tests to append to a log that will show up in expected ordering.
const hits = global.hits = [];
const bpts = new Set();
// Set breakpoints everywhere and call the function.
const dbg = new Debugger;
let debuggeeFn = dbg.addDebuggee(global).makeDebuggeeValue(global.f);
if (debuggeeFn.isBoundFunction) {
debuggeeFn = debuggeeFn.boundTargetFunction;
}
const { script } = debuggeeFn;
for (const offset of script.getAllColumnOffsets()) {
assertEq(offset.lineNumber, 1);
assertEq(offset.columnNumber < execCode.length, true);
bpts.add(offset.columnNumber);
script.setBreakpoint(offset.offset, {
hit(frame) {
hits.push(offset.columnNumber);
},
});
}
global.f(3);
const actualBpts = Array.from(execCode, (_, i) => {
return bpts.has(i) ? "^" : " ";
}).join("");
if (actualBpts.trimEnd() !== expectedBpts.trimEnd()) {
throw new Error(`Assertion failed:
code: ${execCode}
expected bpts: ${expectedBpts}
actual bpts: ${actualBpts}\n`);
}
const indexLookup = new Map(
Array.from(bpts).sort().map((col, i) => [col, i]));
const actualOrdering = hits
.map(item => typeof item === "number" ? indexLookup.get(item) : item)
.join(" ");
if (actualOrdering.trimEnd() !== expectedOrdering.trimEnd()) {
throw new Error(`Assertion failed:
code: ${execCode}
bpts: ${expectedBpts}
expected order: ${expectedOrdering}
actual order: ${actualOrdering}\n`);
}
}
```
vs
```js
function assertOffsetColumns(code, expectedBpts, expectedOrdering = null) {
if (expectedOrdering === null) {
expectedOrdering = Array.from(expectedBpts.match(/\^/g), (_, i) => i).join(" ");
}
const global = newGlobal();
const lines = code.split(/\r?\n|\r]/g);
const initCode = lines.slice(0, -1).join("\n");
const execCode = lines[lines.length - 1];
global.eval(initCode);
global.eval(execCode);
const hits = global.hits = [];
const bpts = new Set();
const dbg = new Debugger();
let debuggeeFn = dbg.addDebuggee(global).makeDebuggeeValue(global.f);
if (debuggeeFn.isBoundFunction) {
debuggeeFn = debuggeeFn.boundTargetFunction;
}
const {script, } = debuggeeFn;
for (offset of script.getAllColumnOffsets()) {
assertEq(offset.lineNumber, 1);
assertEq(offset.columnNumber < execCode.length, true);
bpts.add(offset.columnNumber);
script.setBreakpoint(offset.offset, {
hit: function(frame) {
hits.push(offset.columnNumber);
},
});
}
global.f(3);
const actualBpts = Array.from(execCode, (_, i) => {
return bpts.has(i) ? "^" : " ";
}).join("");
if (actualBpts.trimEnd() !== expectedBpts.trimEnd()) {
throw new Error(`Assertion failed:
code: ${execCode}
expected bpts: {expectedBpts}
actual bpts: {actualBpts}\n`);
}
const indexLookup = new Map(Array.from(bpts).sort().map((col, i) => [col, i,]));
const actualOrdering = hits.map(item => typeof item === "number" ? indexLookup.get(item) : item).join(" ");
if (actualOrdering.trimEnd() !== expectedOrdering.trimEnd()) {
throw new Error(`Assertion failed:
code: ${execCode}
bpts: {expectedBpts}
expected order: {expectedOrdering}
actual order: {actualOrdering}\n`);
}
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/assert-offset-columns.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Frame-eval-29.js)
<details>
```js
// Copyright (c) 2004 by Arthur Langereis (arthur_ext at domain xfinitegames, tld com
// 1 op = 6 ANDs, 3 SHRs, 3 SHLs, 4 assigns, 2 ADDs
// O(1)
function fast3bitlookup(b) {
var c, bi3b = 0xE994; // 0b1110 1001 1001 0100; // 3 2 2 1 2 1 1 0
c = 3 & (bi3b >> ((b << 1) & 14));
c += 3 & (bi3b >> ((b >> 2) & 14));
c += 3 & (bi3b >> ((b >> 5) & 6));
return c;
/*
lir4,0xE994; 9 instructions, no memory access, minimal register dependence, 6 shifts, 2 adds, 1 inline assign
rlwinmr5,r3,1,28,30
rlwinmr6,r3,30,28,30
rlwinmr7,r3,27,29,30
rlwnmr8,r4,r5,30,31
rlwnmr9,r4,r6,30,31
rlwnmr10,r4,r7,30,31
addr3,r8,r9
addr3,r3,r10
*/
}
var ret = 0;
function TimeFunc(func) {
var x, y, t;
for(var x=0; x<500; x++)
for(var y=0; y<256; y++) {
ret += func(y);
}
}
TimeFunc(fast3bitlookup);
assertEq(ret, 512000)
```
vs
```js
function fast3bitlookup(b) {
var c, bi3b = 0xE994;
c = 3 & bi3b >> b << 1 & 14;
c += 3 & bi3b >> b >> 2 & 14;
c += 3 & bi3b >> b >> 5 & 6;
return c;
}
var ret = 0;
function TimeFunc(func) {
var x, y, t;
for (let x = 0;x < 500;x++) for (let y = 0;y < 256;y++) {
ret += func(y);
}
}
TimeFunc(fast3bitlookup);
assertEq(ret, 512000);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-bitops-3bit-bits-in-byte.js)
<details>
```js
class C { };
C.prototype.a = "a";
C.prototype.b = "b";
C.prototype.c = "c";
C.prototype.d = "d";
C.prototype.e = "e";
C.prototype.f = "f";
C.prototype.g = "g";
C.prototype.h = "h";
C.prototype.i = "i";
C.prototype.j = "j";
C.prototype.k = "k";
C.prototype.l = "l";
C.prototype.m = "m";
C.prototype.n = "n";
C.prototype.o = "o";
C.prototype.p = "p";
C.prototype.q = "q";
C.prototype.r = "r";
class D extends C {
foo(p) {
return super[p];
}
}
var d = new D();
for (let i = 0; i < 20; ++i) {
for (let p in C.prototype) {
assertEq(p, d.foo(p));
}
}
```
vs
```js
class C {
}
;
C.prototype.a = "a";
C.prototype.b = "b";
C.prototype.c = "c";
C.prototype.d = "d";
C.prototype.e = "e";
C.prototype.f = "f";
C.prototype.g = "g";
C.prototype.h = "h";
C.prototype.i = "i";
C.prototype.j = "j";
C.prototype.k = "k";
C.prototype.l = "l";
C.prototype.m = "m";
C.prototype.n = "n";
C.prototype.o = "o";
C.prototype.p = "p";
C.prototype.q = "q";
C.prototype.r = "r";
class D extends C {
foo(p) {
return super[p];
}
}
var d = new D();
for (let i = 0;i < 20;++i) {
for (p in C.prototype) {
assertEq(p, d.foo(p));
}
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/class/superElemMegamorphic.js)
<details>
```js
// test frame.eval in non-top frames
var g = newGlobal();
var N = g.N = 12; // must be even
assertEq(N % 2, 0);
var dbg = new Debugger(g);
var hits = 0;
dbg.onDebuggerStatement = function (frame) {
var n = frame.eval("n").return;
if (n === 0) {
for (var i = 0; i <= N; i++) {
assertEq(frame.type, 'call');
assertEq(frame.callee.name, i % 2 === 0 ? 'even' : 'odd');
assertEq(frame.eval("n").return, i);
frame = frame.older;
}
assertEq(frame.type, 'call');
assertEq(frame.callee.name, undefined);
frame = frame.older;
assertEq(frame.type, 'eval');
hits++;
}
};
var result = g.eval("(" + function () {
function odd(n) { return n > 0 && !even(n - 1); }
function even(n) { debugger; return n == 0 || !odd(n - 1); }
return even(N);
} + ")();");
assertEq(result, true);
assertEq(hits, 1);
```
vs
```js
var g = newGlobal();
var N = g.N = 12;
assertEq(N % 2, 0);
var dbg = new Debugger(g);
var hits = 0;
dbg.onDebuggerStatement = (function(frame) {
var n = frame.eval("n").return;
if (n === 0) {
for (let i = 0;i <= N;i++) {
assertEq(frame.type, 'call');
assertEq(frame.callee.name, i % 2 === 0 ? 'even' : 'odd');
assertEq(frame.eval("n").return, i);
frame = frame.older;
}
assertEq(frame.type, 'call');
assertEq(frame.callee.name, undefined);
frame = frame.older;
assertEq(frame.type, 'eval');
hits++;
}
});
var result = g.eval("(" + (function() {
function odd(n) {
return n > 0 && !even(n - 1);
}
function even(n) {
debugger;;
return n == 0 || !odd(n - 1);
}
return even(N);
}) + ")();");
assertEq(result, true);
assertEq(hits, 1);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Frame-eval-07.js)
<details>
```js
// Debugger.Object.prototype.getErrorMessageName returns the error message name
// associated with some error object.
var g = newGlobal();
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
assertEq(gw.executeInGlobal("(42).toString(0)").throw.errorMessageName, "JSMSG_BAD_RADIX");
// Custom errors have no error message name.
assertEq(gw.executeInGlobal("throw new Error()").throw.errorMessageName, undefined);
// Ensure that the method works across globals.
g.eval(`var g = newGlobal();
g.eval('var err; try { (42).toString(0); } catch (e) { err = e; }');
var err2 = g.err;`);
assertEq(gw.executeInGlobal("throw err2").throw.errorMessageName, "JSMSG_BAD_RADIX");
// Ensure that non-error objects return undefined.
const Args = [
"1",
"'blah'",
"({})",
"[]",
"() => 1"
]
for (let arg of Args)
assertEq(gw.executeInGlobal(`${arg}`).return.errorMessageName, undefined);
```
vs
```js
var g = newGlobal();
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
assertEq(gw.executeInGlobal("(42).toString(0)").throw.errorMessageName, "JSMSG_BAD_RADIX");
assertEq(gw.executeInGlobal("throw new Error()").throw.errorMessageName, undefined);
g.eval(`var g = newGlobal();
g.eval('var err; try { (42).toString(0); } catch (e) { err = e; }');
var err2 = g.err;`);
assertEq(gw.executeInGlobal("throw err2").throw.errorMessageName, "JSMSG_BAD_RADIX");
const Args = ["1", "'blah'", "({})", "[]", "() => 1",];
for (arg of Args) assertEq(gw.executeInGlobal(`${arg}`).return.errorMessageName, undefined);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Object-getErrorMessageName.js)
<details>
```js
// deoptimize `arguments` in the arrow's closest enclosing non-arrow-function
// non-arrow-function -> arrow function
a = 0;
(function() {
a = (() => eval("arguments"))();
})(1, 2, 3, 4);
assertEq(a.length, 4);
// non-arrow-function -> arrow function -> arrow function
a = 0;
(function() {
(() => {
a = (() => eval("arguments"))();
})();
})(1, 2, 3, 4);
assertEq(a.length, 4);
// non-arrow-function -> arrow function -> non-arrow-function -> arrow function
a = 0;
(function() {
(() => {
(function () {
a = (() => eval("arguments"))();
})(1, 2, 3, 4);
})();
})();
assertEq(a.length, 4);
```
vs
```js
a = 0;
(function() {
a = () => eval("arguments")();
})(1, 2, 3, 4);
assertEq(a.length, 4);
a = 0;
(function() {
() => {
a = () => eval("arguments")();
}();
})(1, 2, 3, 4);
assertEq(a.length, 4);
a = 0;
(function() {
() => {
function() {
a = () => eval("arguments")();
}(1, 2, 3, 4);
}();
})();
assertEq(a.length, 4);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/bug-885067-2.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-access-fannkuch.js)
<details>
```js
// Parameter default values work in arrow functions
var f = (a=1, b=2, ...rest) => [a, b, rest];
assertEq(f().toSource(), "[1, 2, []]");
assertEq(f(0, 0).toSource(), "[0, 0, []]");
assertEq(f(0, 1, 1, 2, 3, 5).toSource(), "[0, 1, [1, 2, 3, 5]]");
```
vs
```js
var f = (a = 1, b = 2, rest) => [a, b, rest,];
assertEq(f().toSource(), "[1, 2, []]");
assertEq(f(0, 0).toSource(), "[0, 0, []]");
assertEq(f(0, 1, 1, 2, 3, 5).toSource(), "[0, 1, [1, 2, 3, 5]]");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/params-default-2.js)
<details>
```js
// |jit-test| --code-coverage;
// Currently the Jit integration has a few issues, let's keep this test
// case deterministic.
//
// - Baseline OSR increments the loop header twice.
// - Ion is not updating any counter yet.
//
if (getJitCompilerOptions()["ion.warmup.trigger"] != 30)
setJitCompilerOption("ion.warmup.trigger", 30);
if (getJitCompilerOptions()["baseline.warmup.trigger"] != 10)
setJitCompilerOption("baseline.warmup.trigger", 10);
/*
* These test cases are annotated with the output produced by LCOV [1]. Comment
* starting with //<key> without any spaces are used as a reference for the code
* coverage output. Any "$" in these line comments are replaced by the current
* line number, and any "%" are replaced with the current function name (defined
* by the FN key).
*
* [1] http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php
*/
function checkLcov(fun) {
var keys = [ "TN", "SF", "FN", "FNDA", "FNF", "FNH", "BRDA", "BRF", "BRH", "DA", "LF", "LH" ];
function startsWithKey(s) {
for (k of keys) {
if (s.startsWith(k))
return true;
}
return false;
};
// Extract the body of the function, as the code to be executed.
var source = fun.toSource();
source = source.slice(source.indexOf('{') + 1, source.lastIndexOf('}'));
// Extract comment starting with the previous keys, as a reference of the
// output expected from getLcovInfo.
var lcovRef = [];
var currLine = 0;
var currFun = "<badfunction>";
for (var line of source.split('\n')) {
currLine++;
for (var comment of line.split("//").slice(1)) {
if (!startsWithKey(comment))
continue;
comment = comment.trim();
if (comment.startsWith("FN:"))
currFun = comment.split(',')[1];
comment = comment.replace('$', currLine);
comment = comment.replace('%', currFun);
lcovRef.push(comment);
}
}
// Evaluate the code, and generate the Lcov result from the execution. We have
// to disable lazy parsing, as we rely on the ZoneCellIter to emulate the
// behaviour of the finalizer.
var g = newGlobal({ disableLazyParsing: true });
g.eval(source);
var lcovResRaw = getLcovInfo(g);
// Check that all the lines are present the result.
var lcovRes = lcovResRaw.split('\n');
for (ref of lcovRef) {
if (lcovRes.indexOf(ref) == -1) {
print("Cannot find `" + ref + "` in the following Lcov result:\n", lcovResRaw);
print("In the following source:\n", source);
assertEq(true, false);
}
}
}
checkLcov(function () { //FN:$,top-level //FNDA:1,%
",".split(','); //DA:$,1
//FNF:1
//FNH:1
//LF:1
//LH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
function f() { //FN:$,f
",".split(','); //DA:$,0
}
",".split(','); //DA:$,1
//FNF:2
//FNH:1
//LF:2
//LH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
function f() { //FN:$,f //FNDA:1,%
",".split(','); //DA:$,1
}
f(); //DA:$,1
//FNF:2
//FNH:2
//LF:2
//LH:2
});
checkLcov(function () { ','.split(','); //FN:$,top-level //FNDA:1,% //DA:$,1
//FNF:1
//FNH:1
//LF:1
//LH:1
});
checkLcov(function () { function f() { ','.split(','); } //FN:$,top-level //FNDA:1,% //FN:$,f //FNDA:1,f //DA:$,1
f(); //DA:$,1
//FNF:2
//FNH:2
//LF:2
//LH:2
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
if (l.length == 3) //DA:$,1 //BRDA:$,0,0,1 //BRDA:$,0,1,0
l.push(''); //DA:$,0
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:4
//LH:3
//BRF:2
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
if (l.length == 2) //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,1
l.push(''); //DA:$,1
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:4
//LH:4
//BRF:2
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
if (l.length == 3) //DA:$,1 //BRDA:$,0,0,1 //BRDA:$,0,1,0
l.push(''); //DA:$,0
else
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:4
//LH:3
//BRF:2
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
if (l.length == 2) //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,1
l.push(''); //DA:$,1
else
l.pop(); //DA:$,0
//FNF:1
//FNH:1
//LF:4
//LH:3
//BRF:2
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
if (l.length == 2) //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,1
l.push(''); //DA:$,1
else {
if (l.length == 1) //DA:$,0 //BRDA:$,1,0,- //BRDA:$,1,1,-
l.pop(); //DA:$,0
}
//FNF:1
//FNH:1
//LF:5
//LH:3
//BRF:4
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
function f(i) { //FN:$,f //FNDA:2,%
var x = 0; //DA:$,2
while (i--) { // Currently OSR wrongly count the loop header twice.
// So instead of DA:$,12 , we have DA:$,13 .
x += i; //DA:$,10
x = x / 2; //DA:$,10
}
return x; //DA:$,2
//BRF:2
//BRH:2
}
f(5); //DA:$,1
f(5); //DA:$,1
//FNF:2
//FNH:2
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
try { //DA:$,1
var l = ",".split(','); //DA:$,1
if (l.length == 2) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,1
l.push(''); //DA:$,1
throw l; //DA:$,1
}
l.pop(); //DA:$,0
} catch (x) { //DA:$,1
x.pop(); //DA:$,1
}
//FNF:1
//FNH:1
//LF:8
//LH:7
//BRF:2
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
try { //DA:$,1
try { //DA:$,1
if (l.length == 2) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,1
l.push(''); //DA:$,1
throw l; //DA:$,1
}
l.pop(); //DA:$,0
} finally { //DA:$,1
l.pop(); //DA:$,1
}
} catch (x) { //DA:$,1
}
//FNF:1
//FNH:1
//LF:10
//LH:9
//BRF:2
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
function f() { //FN:$,f //FNDA:1,%
throw 1; //DA:$,1
f(); //DA:$,0
}
var l = ",".split(','); //DA:$,1
try { //DA:$,1
f(); //DA:$,1
f(); //DA:$,0
} catch (x) { //DA:$,1
}
//FNF:2
//FNH:2
//LF:7
//LH:5
//BRF:0
//BRH:0
});
// Test TableSwitch opcode
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,0 //BRDA:$,0,2,1 //BRDA:$,0,3,0 //BRDA:$,0,4,0
case 0:
l.push('0'); //DA:$,0
break;
case 1:
l.push('1'); //DA:$,0
break;
case 2:
l.push('2'); //DA:$,1
break;
case 3:
l.push('3'); //DA:$,0
break;
}
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:7
//LH:4
//BRF:5
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,0 //BRDA:$,0,2,1 //BRDA:$,0,3,0 //BRDA:$,0,4,0
case 0:
l.push('0'); //DA:$,0
case 1:
l.push('1'); //DA:$,0
case 2:
l.push('2'); //DA:$,1
case 3:
l.push('3'); //DA:$,1
}
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:7
//LH:5
//BRF:5
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
// Branches are ordered, and starting at 0
switch (l.length) { //DA:$,1 //BRDA:$,0,0,1 //BRDA:$,0,1,0 //BRDA:$,0,2,0 //BRDA:$,0,3,0 //BRDA:$,0,4,0
case 5:
l.push('5'); //DA:$,0
case 4:
l.push('4'); //DA:$,0
case 3:
l.push('3'); //DA:$,0
case 2:
l.push('2'); //DA:$,1
}
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:7
//LH:4
//BRF:5
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
switch (l.length) { //DA:$,1 //BRDA:$,0,0,1 //BRDA:$,0,1,0 //BRDA:$,0,2,0
case 2:
l.push('2'); //DA:$,1
case 5:
l.push('5'); //DA:$,1
}
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:5
//LH:5
//BRF:3
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,1 //BRDA:$,0,2,0
case 3:
l.push('1'); //DA:$,0
case 5:
l.push('5'); //DA:$,0
}
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:5
//LH:3
//BRF:3
//BRH:1
});
// Unfortunately the differences between switch implementations leaks in the
// code coverage reports.
checkLcov(function () { //FN:$,top-level //FNDA:1,%
function f(a) { //FN:$,f //FNDA:2,%
return a; //DA:$,2
}
var l = ",".split(','); //DA:$,1
switch (l.length) { //DA:$,1
case f(-42): //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,1
l.push('1'); //DA:$,0
case f(51): //DA:$,1 //BRDA:$,1,0,0 //BRDA:$,1,1,1
l.push('5'); //DA:$,0
}
l.pop(); //DA:$,1
//FNF:2
//FNH:2
//LF:8
//LH:6
//BRF:4
//BRH:2
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,1 //BRDA:$,0,2,0 //BRDA:$,0,3,0
case 0:
case 1:
l.push('0'); //DA:$,0
l.push('1'); //DA:$,0
case 2:
l.push('2'); //DA:$,1
case 3:
l.push('3'); //DA:$,1
}
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:7
//LH:5
//BRF:4
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,0 //BRDA:$,0,2,1 //BRDA:$,0,3,0
case 0:
l.push('0'); //DA:$,0
case 1:
l.push('1'); //DA:$,0
case 2:
case 3:
l.push('2'); //DA:$,1
l.push('3'); //DA:$,1
}
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:7
//LH:5
//BRF:4
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,0 //BRDA:$,0,2,1 //BRDA:$,0,3,0
case 0:
l.push('0'); //DA:$,0
case 1:
default:
l.push('1'); //DA:$,0
case 2:
l.push('2'); //DA:$,1
case 3:
l.push('3'); //DA:$,1
}
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:7
//LH:5
//BRF:4
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,0 //BRDA:$,0,2,1 //BRDA:$,0,3,0
case 0:
l.push('0'); //DA:$,0
case 1:
l.push('1'); //DA:$,0
default:
case 2:
l.push('2'); //DA:$,1
case 3:
l.push('3'); //DA:$,1
}
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:7
//LH:5
//BRF:4
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,0 //BRDA:$,0,2,1 //BRDA:$,0,3,0 //BRDA:$,0,4,0
case 0:
l.push('0'); //DA:$,0
case 1:
l.push('1'); //DA:$,0
default:
l.push('default'); //DA:$,0
case 2:
l.push('2'); //DA:$,1
case 3:
l.push('3'); //DA:$,1
}
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:8
//LH:5
//BRF:5
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ",".split(','); //DA:$,1
switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,0 //BRDA:$,0,2,1 //BRDA:$,0,3,0
case 0:
l.push('0'); //DA:$,0
case 1:
l.push('1'); //DA:$,0
default:
l.push('2'); //DA:$,1
case 3:
l.push('3'); //DA:$,1
}
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:7
//LH:5
//BRF:4
//BRH:1
});
checkLcov(function () { //FN:$,top-level //FNDA:1,%
var l = ','.split(','); //DA:$,1
if (l.length === 45) { //DA:$,1 //BRDA:$,0,0,1 //BRDA:$,0,1,0
switch (l[0]) { //DA:$,0 //BRDA:$,1,0,- //BRDA:$,1,1,-
case ',':
l.push('0'); //DA:$,0
default:
l.push('1'); //DA:$,0
}
}
l.pop(); //DA:$,1
//FNF:1
//FNH:1
//LF:6
//LH:3
//BRF:4
//BRH:1
});
// These tests are not included in ../debug/Script-getOffsetsCoverage-01.js
// because we're specifically testing a feature of Lcov output that
// Debugger.Script doesn't have (the aggregation of hits that are on the
// same line but in different functions).
{
checkLcov(function () { //FN:$,top-level //FNDA:1,%
function f() { return 0; } var l = f(); //DA:$,2
//FNF:2
//FNH:2
//LF:1
//LH:1
});
// A single line has two functions on it, and both hit.
checkLcov(function () { //FN:$,top-level //FNDA:1,%
function f() { return 0; } function g() { return 1; } //DA:$,2
var v = f() + g(); //DA:$,1
//FNF:3
//FNH:3
//LF:2
//LH:2
});
// A line has both function code and toplevel code, and only one of them hits.
checkLcov(function () { //FN:$,top-level //FNDA:1,%
if (1 === 2) //DA:$,1
throw "0 hits here"; function f() { return "1 hit here"; } //DA:$,1
f(); //DA:$,1
//FNF:2
//FNH:2
//LF:3
//LH:3
});
}
// If you add a test case here, do the same in
// jit-test/tests/debug/Script-getOffsetsCoverage-01.js
```
vs
```js
if (getJitCompilerOptions()["ion.warmup.trigger"] != 30) setJitCompilerOption("ion.warmup.trigger", 30);
if (getJitCompilerOptions()["baseline.warmup.trigger"] != 10) setJitCompilerOption("baseline.warmup.trigger", 10);
function checkLcov(fun) {
var keys = ["TN", "SF", "FN", "FNDA", "FNF", "FNH", "BRDA", "BRF", "BRH", "DA", "LF", "LH",];
function startsWithKey(s) {
for (k of keys) {
if (s.startsWith(k)) return true;
}
return false;
}
;
var source = fun.toSource();
source = source.slice(source.indexOf('{') + 1, source.lastIndexOf('}'));
var lcovRef = [];
var currLine = 0;
var currFun = "<badfunction>";
for (line of source.split('\n')) {
currLine++;
for (comment of line.split("//").slice(1)) {
if (!startsWithKey(comment)) continue;
comment = comment.trim();
if (comment.startsWith("FN:")) currFun = comment.split(',')[1];
comment = comment.replace('$', currLine);
comment = comment.replace('%', currFun);
lcovRef.push(comment);
}
}
var g = newGlobal({
disableLazyParsing: true,
});
g.eval(source);
var lcovResRaw = getLcovInfo(g);
var lcovRes = lcovResRaw.split('\n');
for (ref of lcovRef) {
if (lcovRes.indexOf(ref) == -1) {
print("Cannot find `" + ref + "` in the following Lcov result:\n", lcovResRaw);
print("In the following source:\n", source);
assertEq(true, false);
}
}
}
checkLcov((function() {
",".split(',');
}));
checkLcov((function() {
function f() {
",".split(',');
}
",".split(',');
}));
checkLcov((function() {
function f() {
",".split(',');
}
f();
}));
checkLcov((function() {
','.split(',');
}));
checkLcov((function() {
function f() {
','.split(',');
}
f();
}));
checkLcov((function() {
var l = ",".split(',');
if (l.length == 3) l.push('');
l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
if (l.length == 2) l.push('');
l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
if (l.length == 3) l.push('');
else l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
if (l.length == 2) l.push('');
else l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
if (l.length == 2) l.push('');
else {
if (l.length == 1) l.pop();
}
}));
checkLcov((function() {
function f(i) {
var x = 0;
while (i--) {
x += i;
x = x / 2;
}
return x;
}
f(5);
f(5);
}));
checkLcov((function() {
try {
var l = ",".split(',');
if (l.length == 2) {
l.push('');
throw l;
}
l.pop();
} catch (x) {
x.pop();
}
}));
checkLcov((function() {
var l = ",".split(',');
try {
try {
if (l.length == 2) {
l.push('');
throw l;
}
l.pop();
} finally {
l.pop();
}
} catch (x) {
}
}));
checkLcov((function() {
function f() {
throw 1;
f();
}
var l = ",".split(',');
try {
f();
f();
} catch (x) {
}
}));
checkLcov((function() {
var l = ",".split(',');
switch (l.length) {
case 0:
l.push('0');
break;
case 1:
l.push('1');
break;
case 2:
l.push('2');
break;
case 3:
l.push('3');
break;
}
l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
switch (l.length) {
case 0:
l.push('0');
case 1:
l.push('1');
case 2:
l.push('2');
case 3:
l.push('3');
}
l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
switch (l.length) {
case 5:
l.push('5');
case 4:
l.push('4');
case 3:
l.push('3');
case 2:
l.push('2');
}
l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
switch (l.length) {
case 2:
l.push('2');
case 5:
l.push('5');
}
l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
switch (l.length) {
case 3:
l.push('1');
case 5:
l.push('5');
}
l.pop();
}));
checkLcov((function() {
function f(a) {
return a;
}
var l = ",".split(',');
switch (l.length) {
case f(-42):
l.push('1');
case f(51):
l.push('5');
}
l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
switch (l.length) {
case 0:
case 1:
l.push('0');
l.push('1');
case 2:
l.push('2');
case 3:
l.push('3');
}
l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
switch (l.length) {
case 0:
l.push('0');
case 1:
l.push('1');
case 2:
case 3:
l.push('2');
l.push('3');
}
l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
switch (l.length) {
case 0:
l.push('0');
case 1:
default:
l.push('1');
case 2:
l.push('2');
case 3:
l.push('3');
}
l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
switch (l.length) {
case 0:
l.push('0');
case 1:
l.push('1');
default:
case 2:
l.push('2');
case 3:
l.push('3');
}
l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
switch (l.length) {
case 0:
l.push('0');
case 1:
l.push('1');
default:
l.push('default');
case 2:
l.push('2');
case 3:
l.push('3');
}
l.pop();
}));
checkLcov((function() {
var l = ",".split(',');
switch (l.length) {
case 0:
l.push('0');
case 1:
l.push('1');
default:
l.push('2');
case 3:
l.push('3');
}
l.pop();
}));
checkLcov((function() {
var l = ','.split(',');
if (l.length === 45) {
switch (l[0]) {
case ',':
l.push('0');
default:
l.push('1');
}
}
l.pop();
}));
{
checkLcov(function() {
function f() {
return 0;
}
var l = f();
});
checkLcov(function() {
function f() {
return 0;
}
function g() {
return 1;
}
var v = f() + g();
});
checkLcov(function() {
if (1 === 2) throw "0 hits here";
function f() {
return "1 hit here";
}
f();
});
}
```
<details>
```js
// A Map iterator does not visit entries removed by clear().
load(libdir + "iteration.js");
var m = new Map();
var it = m[Symbol.iterator]();
m.clear();
assertIteratorDone(it, undefined);
m = new Map([["a", 1], ["b", 2], ["c", 3], ["d", 4]]);
it = m[Symbol.iterator]();
assertIteratorNext(it, ["a", 1]);
m.clear();
assertIteratorDone(it, undefined);
var log = "";
m = new Map([["a", 1], ["b", 2], ["c", 3], ["d", 4]]);
for (var [k, v] of m) {
log += k + v;
if (k == "b")
m.clear();
}
assertEq(log, "a1b2");
```
vs
```js
load(libdir + "iteration.js");
var m = new Map();
var it = m[Symbol.iterator]();
m.clear();
assertIteratorDone(it, undefined);
m = new Map([["a", 1,], ["b", 2,], ["c", 3,], ["d", 4,],]);
it = m[Symbol.iterator]();
assertIteratorNext(it, ["a", 1,]);
m.clear();
assertIteratorDone(it, undefined);
var log = "";
m = new Map([["a", 1,], ["b", 2,], ["c", 3,], ["d", 4,],]);
for ([k,v,] of m) {
log += k + v;
if (k == "b") m.clear();
}
assertEq(log, "a1b2");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-clear-iterators-1.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/coverage/simple.js)
<details>
```js
load(libdir + "asserts.js");
var g = newGlobal();
for (var cls of [Map, Set]) {
var getter = Object.getOwnPropertyDescriptor(cls.prototype, "size").get;
assertThrowsInstanceOf(function () { getter.apply(g, []); }, g.TypeError);
}
```
vs
```js
load(libdir + "asserts.js");
var g = newGlobal();
for (cls of [Map, Set,]) {
var getter = Object.getOwnPropertyDescriptor(cls.prototype, "size").get;
assertThrowsInstanceOf(function() {
getter.apply(g, []);
}, g.TypeError);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/bug-743101.js)
<details>
```js
// frame.onStep can coexist with breakpoints.
var g = newGlobal();
var dbg = Debugger(g);
var log = '';
dbg.onEnterFrame = function (frame) {
var handler = {hit: function () { log += 'B'; }};
var lines = frame.script.getAllOffsets();
for (var line in lines) {
line = Number(line);
var offs = lines[line];
for (var i = 0; i < offs.length; i++)
frame.script.setBreakpoint(offs[i], handler);
}
frame.onStep = function () { log += 's'; };
};
g.eval("one = 1;\n" +
"two = 2;\n" +
"three = 3;\n" +
"four = 4;\n");
assertEq(g.four, 4);
// Breakpoints hit on all four lines, plus the final line.
assertEq(log.replace(/[^B]/g, ''), 'BBBBB');
// onStep was called between each pair of breakpoints.
assertEq(/BB/.exec(log), null);
```
vs
```js
var g = newGlobal();
var dbg = Debugger(g);
var log = '';
dbg.onEnterFrame = (function(frame) {
var handler = {
hit: function() {
log += 'B';
},
};
var lines = frame.script.getAllOffsets();
for (line in lines) {
line = Number(line);
var offs = lines[line];
for (let i = 0;i < offs.length;i++) frame.script.setBreakpoint(offs[i], handler);
}
frame.onStep = function() {
log += 's';
};
});
g.eval("one = 1;\n" + "two = 2;\n" + "three = 3;\n" + "four = 4;\n");
assertEq(g.four, 4);
assertEq(log.replace(/[^B]/g, ''), 'BBBBB');
assertEq(/BB/.exec(log), null);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Frame-onStep-08.js)
<details>
```js
// The Great Computer Language Shootout
// http://shootout.alioth.debian.org
//
// Contributed by Ian Osgood
var result = [];
function pad(n,width) {
var s = n.toString();
while (s.length < width) s = ' ' + s;
return s;
}
function primes(isPrime, n) {
var i, count = 0, m = 10000<<n, size = m+31>>5;
for (i=0; i<size; i++) isPrime[i] = 0xffffffff;
for (i=2; i<m; i++)
if (isPrime[i>>5] & 1<<(i&31)) {
for (var j=i+i; j<m; j+=i)
result.push(isPrime[j>>5] &= ~(1<<(j&31)));
count++;
}
}
function sieve() {
for (var i = 4; i <= 4; i++) {
var isPrime = new Array((10000<<i)+31>>5);
primes(isPrime, i);
}
}
sieve();
var ret = 0;
for (var i = 0; i < result.length; ++i)
ret += result[i];
assertEq(ret, -211235557404919)
```
vs
```js
var result = [];
function pad(n, width) {
var s = n.toString();
while (s.length < width) s = ' ' + s;
return s;
}
function primes(isPrime, n) {
var i, count = 0, m = 10000 << n, size = m + 31 >> 5;
for (i = 0;i < size;i++) isPrime[i] = 0xffffffff;
for (i = 2;i < m;i++) if (isPrime[i >> 5] & 1 << i & 31) {
for (let j = i + i;j < m;j += i) result.push(isPrime[j >> 5] &= ~1 << j & 31);
count++;
}
}
function sieve() {
for (let i = 4;i <= 4;i++) {
var isPrime = new Array(10000 << i + 31 >> 5);
primes(isPrime, i);
}
}
sieve();
var ret = 0;
for (let i = 0;i < result.length;++i) ret += result[i];
assertEq(ret, -211235557404919);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-bitops-nsieve-bits.js)
<details>
```js
// Tests for the assertEqual function in jit-test/lib/asserts.js
load(libdir + "asserts.js");
function assertNotDeepEq(a, b, options) {
assertThrowsInstanceOf(() => assertDeepEq(a, b, options), Error);
}
// primitives
assertDeepEq(undefined, undefined);
assertDeepEq("1", "1");
assertNotDeepEq(1, "1");
assertNotDeepEq(undefined, null);
assertNotDeepEq({}, null);
// symbols
assertDeepEq(Symbol(), Symbol());
assertNotDeepEq(Symbol(), Symbol(""));
assertDeepEq(Symbol("tweedledum"), Symbol("tweedledum"));
assertNotDeepEq(Symbol("tweedledum"), Symbol("alice"));
assertNotDeepEq(Symbol("what-its-called"), Symbol.for("what-its-called"));
assertNotDeepEq(Symbol.iterator, Symbol.for("Symbol.iterator"));
assertDeepEq([Symbol(), Symbol(), Symbol()],
[Symbol(), Symbol(), Symbol()]);
var sym = Symbol();
assertDeepEq([sym, sym], [sym, sym]);
assertNotDeepEq([sym, sym], [Symbol(), Symbol()]);
assertNotDeepEq([sym, sym], [Symbol(), sym]);
var obj1 = {}, obj2 = {};
obj1[Symbol("x")] = "y";
obj2[Symbol("x")] = "y";
assertDeepEq(obj1, obj2);
// objects
assertDeepEq({}, {});
assertDeepEq({one: 1, two: 2}, {one: 1, two: 2});
assertNotDeepEq(Object.freeze({}), {});
assertDeepEq(Object.create(null), Object.create(null));
assertNotDeepEq(Object.create(null, {a: {configurable: false, value: 3}}),
Object.create(null, {a: {configurable: true, value: 3}}));
assertNotDeepEq({one: 1}, {one: 1, two: 2});
assertNotDeepEq({yes: true}, {oui: true});
assertNotDeepEq({zero: 0}, {zero: "0"});
// test the comment
var x = {}, y = {}, ax = [x];
assertDeepEq([ax, x], [ax, y]); // passes (bogusly)
assertNotDeepEq([ax, x], [ax, y], {strictEquivalence: true});
assertDeepEq([x, ax], [y, ax]); // passes (bogusly)
assertNotDeepEq([x, ax], [y, ax], {strictEquivalence: true});
// object identity
assertNotDeepEq([x, y], [x, x]);
assertDeepEq([x, y], [x, y]);
assertDeepEq([y, x], [x, y]);
// proto chain
var x = {};
assertDeepEq(Object.create(x), Object.create(x));
assertDeepEq(Object.create({}), Object.create({})); // equivalent but not identical proto objects
// arrays
assertDeepEq([], []);
assertNotDeepEq([], [1]);
assertDeepEq([1], [1]);
assertNotDeepEq([0], [1]);
assertDeepEq([1, 2, 3], [1, 2, 3]);
assertNotDeepEq([1, , 3], [1, undefined, 3]);
var p = [], q = [];
p.prop = 1;
assertNotDeepEq(p, q);
assertNotDeepEq(q, p);
q.prop = 1;
assertDeepEq(q, p);
// functions
assertNotDeepEq(() => 1, () => 2);
assertNotDeepEq((...x) => 1, x => 1);
assertNotDeepEq(function f(){}, function g(){});
// Avoid setting name property.
var [f1, f2] = [function () {}, function () {}];
assertDeepEq(f1, f1);
assertDeepEq(f1, f2); // same text, close enough
f1.prop = 1;
assertNotDeepEq(f1, f2);
f2.prop = 1;
assertDeepEq(f1, f2);
// recursion
var a = [], b = [];
a[0] = a;
b[0] = b;
assertDeepEq(a, b);
a[0] = b;
assertNotDeepEq(a, b); // [#1=[#1#]] is not structurally equivalent to #1=[[#1#]]
b[0] = a;
assertDeepEq(a, b);
b[0] = [a]; // a[0] === b, b[0] === c, c[0] === a
assertDeepEq(a, b);
// objects that merge
var x = {};
assertDeepEq({x: x}, {x: x});
var y = [x];
assertDeepEq([y], [y]);
// cross-compartment
var g1 = newGlobal(), g2 = newGlobal();
assertDeepEq(g1, g2);
assertDeepEq(g1, g2, {strictEquivalence: true});
Object.preventExtensions(g2.Math.abs); // make some miniscule change
assertNotDeepEq(g1, g2);
```
vs
```js
load(libdir + "asserts.js");
function assertNotDeepEq(a, b, options) {
assertThrowsInstanceOf(() => assertDeepEq(a, b, options), Error);
}
assertDeepEq(undefined, undefined);
assertDeepEq("1", "1");
assertNotDeepEq(1, "1");
assertNotDeepEq(undefined, null);
assertNotDeepEq(({}), null);
assertDeepEq(Symbol(), Symbol());
assertNotDeepEq(Symbol(), Symbol(""));
assertDeepEq(Symbol("tweedledum"), Symbol("tweedledum"));
assertNotDeepEq(Symbol("tweedledum"), Symbol("alice"));
assertNotDeepEq(Symbol("what-its-called"), Symbol.for("what-its-called"));
assertNotDeepEq(Symbol.iterator, Symbol.for("Symbol.iterator"));
assertDeepEq([Symbol(), Symbol(), Symbol(),], [Symbol(), Symbol(), Symbol(),]);
var sym = Symbol();
assertDeepEq([sym, sym,], [sym, sym,]);
assertNotDeepEq([sym, sym,], [Symbol(), Symbol(),]);
assertNotDeepEq([sym, sym,], [Symbol(), sym,]);
var obj1 = ({}), obj2 = ({});
obj1[Symbol("x")] = "y";
obj2[Symbol("x")] = "y";
assertDeepEq(obj1, obj2);
assertDeepEq(({}), ({}));
assertDeepEq(({
one: 1,
two: 2,
}), ({
one: 1,
two: 2,
}));
assertNotDeepEq(Object.freeze(({})), ({}));
assertDeepEq(Object.create(null), Object.create(null));
assertNotDeepEq(Object.create(null, ({
a: ({
configurable: false,
value: 3,
}),
})), Object.create(null, ({
a: ({
configurable: true,
value: 3,
}),
})));
assertNotDeepEq(({
one: 1,
}), ({
one: 1,
two: 2,
}));
assertNotDeepEq(({
yes: true,
}), ({
oui: true,
}));
assertNotDeepEq(({
zero: 0,
}), ({
zero: "0",
}));
var x = ({}), y = ({}), ax = [x,];
assertDeepEq([ax, x,], [ax, y,]);
assertNotDeepEq([ax, x,], [ax, y,], ({
strictEquivalence: true,
}));
assertDeepEq([x, ax,], [y, ax,]);
assertNotDeepEq([x, ax,], [y, ax,], ({
strictEquivalence: true,
}));
assertNotDeepEq([x, y,], [x, x,]);
assertDeepEq([x, y,], [x, y,]);
assertDeepEq([y, x,], [x, y,]);
var x = ({});
assertDeepEq(Object.create(x), Object.create(x));
assertDeepEq(Object.create(({})), Object.create(({})));
assertDeepEq([], []);
assertNotDeepEq([], [1,]);
assertDeepEq([1,], [1,]);
assertNotDeepEq([0,], [1,]);
assertDeepEq([1, 2, 3,], [1, 2, 3,]);
assertNotDeepEq([1,, 3,], [1, undefined, 3,]);
var p = [], q = [];
p.prop = 1;
assertNotDeepEq(p, q);
assertNotDeepEq(q, p);
q.prop = 1;
assertDeepEq(q, p);
assertNotDeepEq(() => 1, () => 2);
assertNotDeepEq(x => 1, x => 1);
assertNotDeepEq((function f() { }), (function g() { }));
var [f1,f2,] = [(function() { }), (function() { }),];
assertDeepEq(f1, f1);
assertDeepEq(f1, f2);
f1.prop = 1;
assertNotDeepEq(f1, f2);
f2.prop = 1;
assertDeepEq(f1, f2);
var a = [], b = [];
a[0] = a;
b[0] = b;
assertDeepEq(a, b);
a[0] = b;
assertNotDeepEq(a, b);
b[0] = a;
assertDeepEq(a, b);
b[0] = [a,];
assertDeepEq(a, b);
var x = ({});
assertDeepEq(({
x: x,
}), ({
x: x,
}));
var y = [x,];
assertDeepEq([y,], [y,]);
var g1 = newGlobal(), g2 = newGlobal();
assertDeepEq(g1, g2);
assertDeepEq(g1, g2, ({
strictEquivalence: true,
}));
Object.preventExtensions(g2.Math.abs);
assertNotDeepEq(g1, g2);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/self-test/assertDeepEq.js)
<details>
```js
load(libdir + "asserts.js");
var LENGTH = 1024, SYMBOL_INDEX = 999;
var big = [];
for (var i = 0; i < LENGTH; i++)
big[i] = (i === SYMBOL_INDEX ? Symbol.for("comet") : i);
var progress;
function copy(arr, big) {
for (var i = 0; i < LENGTH; i++) {
arr[i] = big[i];
progress = i;
}
}
for (var T of [Uint8Array, Uint8ClampedArray, Int16Array, Float32Array]) {
// Typed array constructors convert symbols using ToNumber, which throws.
assertThrowsInstanceOf(() => new T(big), TypeError);
// Element assignment does the same.
var arr = new T(big.length);
for (var k = 0; k < 3; k++) {
progress = -1;
assertThrowsInstanceOf(() => copy(arr, big), TypeError);
assertEq(progress, SYMBOL_INDEX - 1);
assertEq(arr[SYMBOL_INDEX], 0);
}
}
```
vs
```js
load(libdir + "asserts.js");
var LENGTH = 1024, SYMBOL_INDEX = 999;
var big = [];
for (let i = 0;i < LENGTH;i++) big[i] = i === SYMBOL_INDEX ? Symbol.for("comet") : i;
var progress;
function copy(arr, big) {
for (let i = 0;i < LENGTH;i++) {
arr[i] = big[i];
progress = i;
}
}
for (T of [Uint8Array, Uint8ClampedArray, Int16Array, Float32Array,]) {
assertThrowsInstanceOf(() => new T(big), TypeError);
var arr = new T(big.length);
for (let k = 0;k < 3;k++) {
progress = -1;
assertThrowsInstanceOf(() => copy(arr, big), TypeError);
assertEq(progress, SYMBOL_INDEX - 1);
assertEq(arr[SYMBOL_INDEX], 0);
}
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/symbol/typed-arrays.js)
<details>
```js
g0 = function(i) {
this["g"+(i+1)] = g0;
return "g"+(i+1);
}
function f() {
a = eval("g0");
for(var i=0; i<40; i++) {
a = this[a(i)];
if (i === 30) {
gc();
}
assertEq(this["g" + i], g0);
}
}
f();
```
vs
```js
g0 = (function(i) {
this["g" + i + 1] = g0;
return "g" + i + 1;
});
function f() {
a = eval("g0");
for (let i = 0;i < 40;i++) {
a = this[a(i)];
if (i === 30) {
gc();
}
assertEq(this["g" + i], g0);
}
}
f();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/pic/callname-global2.js)
<details>
```js
// The Set constructor can take an argument that is an array.
var s = new Set([]);
assertEq(s.size, 0);
assertEq(s.has(undefined), false);
s = new Set(["one", "two", "three"]);
assertEq(s.size, 3);
assertEq(s.has("one"), true);
assertEq(s.has("eleventeen"), false);
var a = [{}, {}, {}];
s = new Set(a);
assertEq(s.size, 3);
for (let obj of a)
assertEq(s.has(obj), true);
assertEq(s.has({}), false);
assertEq(s.has("three"), false);
```
vs
```js
var s = new Set([]);
assertEq(s.size, 0);
assertEq(s.has(undefined), false);
s = new Set(["one", "two", "three",]);
assertEq(s.size, 3);
assertEq(s.has("one"), true);
assertEq(s.has("eleventeen"), false);
var a = [({}), ({}), ({}),];
s = new Set(a);
assertEq(s.size, 3);
for (obj of a) assertEq(s.has(obj), true);
assertEq(s.has(({})), false);
assertEq(s.has("three"), false);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-constructor-2.js)
<details>
```js
// Arrow functions can have primitive |this| values.
Number.prototype.foo = function() {
"use strict";
return () => this;
}
for (var i=0; i<5; i++) {
var n = i.foo()();
assertEq(typeof n, "number");
assertEq(n, i);
}
```
vs
```js
Number.prototype.foo = (function() {
'use strict';
return () => this;
});
for (let i = 0;i < 5;i++) {
var n = i.foo()();
assertEq(typeof n, "number");
assertEq(n, i);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/this-5.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/bug655508.js)
<details>
```js
// => binds tighter than ,
var f, g;
g = (f, h => h + 1); // sequence expression: (f, (h => h + 1))
assertEq(g.length, 1);
assertEq(g(37), 38);
```
vs
```js
var f, g;
g = f, h => h + 1;
assertEq(g.length, 1);
assertEq(g(37), 38);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/precedence-2.js)
<details>
```js
// |jit-test| error: ReferenceError
for (let a in [0])
a = e
for (let a in [0])
(function () {
a
})
```
vs
```js
for (a in [0,]) a = e;
for (a in [0,]) function() {
a;
};
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/bug580884.js)
<details>
```js
function toLatin1(s) {
assertEq(isLatin1(s), true);
return s;
}
function testLastIndexOf() {
var s1 = toLatin1("abcdefgh123456\u0081defg");
var s2 = toLatin1("456\u0081de");
// Latin1 + Latin1
assertEq(s1.lastIndexOf(s1), 0);
assertEq(s1.lastIndexOf(s2), 11);
assertEq(s1.lastIndexOf(s2, 10), -1);
assertEq(s2.lastIndexOf(s1), -1);
// Latin1 + TwoByte
assertEq(s1.lastIndexOf("abc\u1234"), -1);
assertEq(s1.lastIndexOf("def\u1234".substring(0, 3)), 15);
assertEq(s1.lastIndexOf("def\u1234".substring(0, 3), 9), 3);
// TwoByte + Latin1
var s3 = "123456\u0081defg\u1123a456\u0081defg";
assertEq(isLatin1(s2), true);
assertEq(s3.lastIndexOf(s2), 13);
assertEq(s3.lastIndexOf(s2, 12), 3);
assertEq(s3.lastIndexOf(toLatin1("defg7")), -1);
// TwoByte + TwoByte
assertEq(s3.lastIndexOf("\u1123a4"), 11);
assertEq(s3.lastIndexOf("\u1123a4", 10), -1);
assertEq(s3.lastIndexOf("\u1123a\u1098"), -1);
assertEq(s3.lastIndexOf(s3), 0);
}
testLastIndexOf();
function testIndexOf() {
var s1 = toLatin1("abcdefgh123456d\u00AAefghi");
var s2 = toLatin1("456d\u00AA");
// Latin1 + Latin1
assertEq(s1.indexOf(s1), 0);
assertEq(s1.indexOf(s2), 11);
assertEq(s1.indexOf(s2, 12), -1);
assertEq(s2.indexOf(s1), -1);
// Latin1 + TwoByte
assertEq(s1.indexOf("abc\u1234"), -1);
assertEq(s1.indexOf("def\u1234".substring(0, 3)), 3);
assertEq(s1.indexOf("d\u00AAef\u1234".substring(0, 3), 9), 14);
// TwoByte + Latin1
var s3 = "123456d\u00AAefg\u1123a456d\u00AAefg";
assertEq(isLatin1(s2), true);
assertEq(s3.indexOf(s2), 3);
assertEq(s3.indexOf(s2, 11), 13);
assertEq(s3.indexOf(toLatin1("d\u00AAefg7")), -1);
// TwoByte + TwoByte
assertEq(s3.indexOf("\u1123a4"), 11);
assertEq(s3.indexOf("\u1123a4", 12), -1);
assertEq(s3.indexOf("\u1123a\u1098"), -1);
assertEq(s3.indexOf(s3), 0);
}
testIndexOf();
function testincludes() {
var s1 = toLatin1("abcdefgh123456defghi\u00EEj");
var s2 = toLatin1("456defghi\u00EE");
// Latin1 + Latin1
assertEq(s1.includes(s1), true);
assertEq(s1.includes(s2), true);
assertEq(s1.includes(s2, 12), false);
assertEq(s2.includes(s1), false);
// Latin1 + TwoByte
assertEq(s1.includes("abc\u1234"), false);
assertEq(s1.includes("def\u1234".substring(0, 3)), true);
assertEq(s1.includes("def\u1234".substring(0, 3), 9), true);
// TwoByte + Latin1
var s3 = "123456defg\u1123a456defghi\u00EEj";
assertEq(isLatin1(s2), true);
assertEq(s3.includes(s2), true);
assertEq(s3.includes(s2, 13), false);
assertEq(s3.includes(toLatin1("defg8")), false);
// TwoByte + TwoByte
assertEq(s3.includes("\u1123a4"), true);
assertEq(s3.includes("\u1123a4", 11), false);
assertEq(s3.includes("\u1123a\u1098"), false);
assertEq(s3.includes(s3), true);
}
testincludes();
function testIndexOfBMH() {
// BoyerMooreHorspool algorithm is used for large strings.
var s = "012345678901234567890123456789".repeat(20);
var text = s + "abcdefghijklmnopqrst\u00C1uvwxyz";
text.indexOf("333");
var textL1 = toLatin1(text);
var patL1 = toLatin1("cdefghijklmnopqrst\u00C1uvwx");
// Latin1 + Latin1
assertEq(textL1.indexOf(patL1), 602);
assertEq(textL1.indexOf(patL1, 603), -1);
assertEq(textL1.indexOf(textL1), 0);
// Latin1 + TwoByte
assertEq(textL1.indexOf("cdefghijklmnopqrst\u00C1uvwxy"), 602);
assertEq(textL1.indexOf("cdefghijklmnopqrst\u00C1uvwxy", 603), -1);
assertEq(textL1.indexOf("cdefghijklmnopqrst\u00C1uvwxy\uaa00", -1), -1);
// TwoByte + Latin1
var textTB = s + "abcdefghijklmnopqrst\u00C1uvwxyz\u1200";
text.indexOf("333");
assertEq(textTB.indexOf(patL1), 602);
assertEq(textTB.indexOf(patL1, 603), -1);
// TwoByte + TwoByte
assertEq(textTB.indexOf("defghijklmnopqrst\u00C1uvwxyz\u1200"), 603);
assertEq(textTB.indexOf("defghijklmnopqrst\u00C1uvwxyz\u1200", 604), -1);
assertEq(textTB.indexOf("defghijklmnopqrst\u00C1uvwxyz\u1201"), -1);
}
testIndexOfBMH();
function testIndexOfLargePattern() {
// If the pattern length > 128, memcmp is used (text length has to be < 512
// or we'll use BoyerMooreHorspool). This is only valid if both
// strings have the same encoding.
var text = "012345678901234567890123456789".repeat(10) + "abcdefghijklmnopqrst\u00C1uvwxyz";
text.indexOf("333"); // flatten
var pat = "012345678901234567890123456789".repeat(5) + "abcdefghijklmnopqr";
pat.indexOf("333"); // flatten
// Latin1 + Latin1
text = toLatin1(text);
pat = toLatin1(pat);
assertEq(text.indexOf(pat), 150);
// Latin1 + TwoByte
assertEq(text.indexOf(pat + "\u1200"), -1);
assertEq(text.indexOf((pat + "\u1200").slice(0, -1)), 150);
// TwoByte + Latin1
text = text + "\u1100";
assertEq(isLatin1(pat), true);
assertEq(text.indexOf(pat), 150);
// TwoByte + TwoByte
pat = pat + "st\u00C1uvwxyz\u1100";
assertEq(text.indexOf(pat), 150);
assertEq(text.indexOf(pat + "\u2000"), -1);
}
testIndexOfLargePattern();
```
vs
```js
function toLatin1(s) {
assertEq(isLatin1(s), true);
return s;
}
function testLastIndexOf() {
var s1 = toLatin1("abcdefgh123456\u0081defg");
var s2 = toLatin1("456\u0081de");
assertEq(s1.lastIndexOf(s1), 0);
assertEq(s1.lastIndexOf(s2), 11);
assertEq(s1.lastIndexOf(s2, 10), -1);
assertEq(s2.lastIndexOf(s1), -1);
assertEq(s1.lastIndexOf("abc\u1234"), -1);
assertEq(s1.lastIndexOf("def\u1234".substring(0, 3)), 15);
assertEq(s1.lastIndexOf("def\u1234".substring(0, 3), 9), 3);
var s3 = "123456\u0081defg\u1123a456\u0081defg";
assertEq(isLatin1(s2), true);
assertEq(s3.lastIndexOf(s2), 13);
assertEq(s3.lastIndexOf(s2, 12), 3);
assertEq(s3.lastIndexOf(toLatin1("defg7")), -1);
assertEq(s3.lastIndexOf("\u1123a4"), 11);
assertEq(s3.lastIndexOf("\u1123a4", 10), -1);
assertEq(s3.lastIndexOf("\u1123a\u1098"), -1);
assertEq(s3.lastIndexOf(s3), 0);
}
testLastIndexOf();
function testIndexOf() {
var s1 = toLatin1("abcdefgh123456d\u00AAefghi");
var s2 = toLatin1("456d\u00AA");
assertEq(s1.indexOf(s1), 0);
assertEq(s1.indexOf(s2), 11);
assertEq(s1.indexOf(s2, 12), -1);
assertEq(s2.indexOf(s1), -1);
assertEq(s1.indexOf("abc\u1234"), -1);
assertEq(s1.indexOf("def\u1234".substring(0, 3)), 3);
assertEq(s1.indexOf("d\u00AAef\u1234".substring(0, 3), 9), 14);
var s3 = "123456d\u00AAefg\u1123a456d\u00AAefg";
assertEq(isLatin1(s2), true);
assertEq(s3.indexOf(s2), 3);
assertEq(s3.indexOf(s2, 11), 13);
assertEq(s3.indexOf(toLatin1("d\u00AAefg7")), -1);
assertEq(s3.indexOf("\u1123a4"), 11);
assertEq(s3.indexOf("\u1123a4", 12), -1);
assertEq(s3.indexOf("\u1123a\u1098"), -1);
assertEq(s3.indexOf(s3), 0);
}
testIndexOf();
function testincludes() {
var s1 = toLatin1("abcdefgh123456defghi\u00EEj");
var s2 = toLatin1("456defghi\u00EE");
assertEq(s1.includes(s1), true);
assertEq(s1.includes(s2), true);
assertEq(s1.includes(s2, 12), false);
assertEq(s2.includes(s1), false);
assertEq(s1.includes("abc\u1234"), false);
assertEq(s1.includes("def\u1234".substring(0, 3)), true);
assertEq(s1.includes("def\u1234".substring(0, 3), 9), true);
var s3 = "123456defg\u1123a456defghi\u00EEj";
assertEq(isLatin1(s2), true);
assertEq(s3.includes(s2), true);
assertEq(s3.includes(s2, 13), false);
assertEq(s3.includes(toLatin1("defg8")), false);
assertEq(s3.includes("\u1123a4"), true);
assertEq(s3.includes("\u1123a4", 11), false);
assertEq(s3.includes("\u1123a\u1098"), false);
assertEq(s3.includes(s3), true);
}
testincludes();
function testIndexOfBMH() {
var s = "012345678901234567890123456789".repeat(20);
var text = s + "abcdefghijklmnopqrst\u00C1uvwxyz";
text.indexOf("333");
var textL1 = toLatin1(text);
var patL1 = toLatin1("cdefghijklmnopqrst\u00C1uvwx");
assertEq(textL1.indexOf(patL1), 602);
assertEq(textL1.indexOf(patL1, 603), -1);
assertEq(textL1.indexOf(textL1), 0);
assertEq(textL1.indexOf("cdefghijklmnopqrst\u00C1uvwxy"), 602);
assertEq(textL1.indexOf("cdefghijklmnopqrst\u00C1uvwxy", 603), -1);
assertEq(textL1.indexOf("cdefghijklmnopqrst\u00C1uvwxy\uaa00", -1), -1);
var textTB = s + "abcdefghijklmnopqrst\u00C1uvwxyz\u1200";
text.indexOf("333");
assertEq(textTB.indexOf(patL1), 602);
assertEq(textTB.indexOf(patL1, 603), -1);
assertEq(textTB.indexOf("defghijklmnopqrst\u00C1uvwxyz\u1200"), 603);
assertEq(textTB.indexOf("defghijklmnopqrst\u00C1uvwxyz\u1200", 604), -1);
assertEq(textTB.indexOf("defghijklmnopqrst\u00C1uvwxyz\u1201"), -1);
}
testIndexOfBMH();
function testIndexOfLargePattern() {
var text = "012345678901234567890123456789".repeat(10) + "abcdefghijklmnopqrst\u00C1uvwxyz";
text.indexOf("333");
var pat = "012345678901234567890123456789".repeat(5) + "abcdefghijklmnopqr";
pat.indexOf("333");
text = toLatin1(text);
pat = toLatin1(pat);
assertEq(text.indexOf(pat), 150);
assertEq(text.indexOf(pat + "\u1200"), -1);
assertEq(text.indexOf(pat + "\u1200".slice(0, -1)), 150);
text = text + "\u1100";
assertEq(isLatin1(pat), true);
assertEq(text.indexOf(pat), 150);
pat = pat + "st\u00C1uvwxyz\u1100";
assertEq(text.indexOf(pat), 150);
assertEq(text.indexOf(pat + "\u2000"), -1);
}
testIndexOfLargePattern();
```
<details>
```js
function testUnaryImacros()
{
function checkArg(x)
{
return 1;
}
var o = { valueOf: checkArg, toString: null };
var count = 0;
var v = 0;
for (var i = 0; i < 5; i++)
v += +o + -(-o);
var results = [v === 10 ? "valueOf passed" : "valueOf failed"];
o.valueOf = null;
o.toString = checkArg;
for (var i = 0; i < 5; i++)
v += +o + -(-o);
results.push(v === 20 ? "toString passed" : "toString failed");
return results.join(", ");
}
assertEq(testUnaryImacros(), "valueOf passed, toString passed");
```
vs
```js
function testUnaryImacros() {
function checkArg(x) {
return 1;
}
var o = {
valueOf: checkArg,
toString: null,
};
var count = 0;
var v = 0;
for (let i = 0;i < 5;i++) v += +o + --o;
var results = [v === 10 ? "valueOf passed" : "valueOf failed",];
o.valueOf = null;
o.toString = checkArg;
for (let i = 0;i < 5;i++) v += +o + --o;
results.push(v === 20 ? "toString passed" : "toString failed");
return results.join(", ");
}
assertEq(testUnaryImacros(), "valueOf passed, toString passed");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/latin1/indexOf.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/testUnaryImacros.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/params-default-1.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/saved-stacks/caching-and-frame-count.js)
<details>
```js
load(libdir + "asserts.js");
function f(tag) { return {[tag](){return 1;}}; }
a = [];
for (var i = 0; i < 2000; i++)
a[i] = f("first");
for (var i = 0; i < 2000; i++)
assertEq(a[i].first(), 1);
for (var i = 0; i < 2000; i++)
a[i] = f("second");
for (var i = 0; i < 2000; i++)
assertEq(a[i].second(), 1);
```
vs
```js
load(libdir + "asserts.js");
function f(tag) {
return {
[tag]: function() {
return 1;
},
};
}
a = [];
for (let i = 0;i < 2000;i++) a[i] = f("first");
for (let i = 0;i < 2000;i++) assertEq(a[i].first(), 1);
for (let i = 0;i < 2000;i++) a[i] = f("second");
for (let i = 0;i < 2000;i++) assertEq(a[i].second(), 1);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/class/methDefn.js)
<details>
```js
load(libdir + "asserts.js");
assertThrowsInstanceOf(function () { readlineBuf() }, Error);
var testBuffers = [
"foo\nbar\nbaz\n",
"foo\nbar\nbaz",
"foo\n\nbar\nbaz",
"f",
"\n",
"\nf",
"",
"Ää\n\u{10ffff}",
];
var expected = [
[ "foo", "bar", "baz" ],
[ "foo", "bar", "baz" ],
[ "foo", "", "bar", "baz" ],
[ "f" ],
[ "" ],
[ "", "f" ],
[],
["Ää", "\u{10ffff}"],
];
for (var [idx, testValue] of testBuffers.entries()) {
readlineBuf(testValue);
var result = [];
while ((line = readlineBuf()) != null) {
result.push(line);
}
assertDeepEq(result, expected[idx]);
}
readlineBuf(testBuffers[0]);
readlineBuf();
readlineBuf();
readlineBuf(testBuffers[3]);
assertEq(readlineBuf(), expected[3][0]);
```
vs
```js
load(libdir + "asserts.js");
assertThrowsInstanceOf((function() {
readlineBuf();
}), Error);
var testBuffers = ["foo\nbar\nbaz\n", "foo\nbar\nbaz", "foo\n\nbar\nbaz", "f", "\n", "\nf", "", "Ää\n\u{10ffff}",];
var expected = [["foo", "bar", "baz",], ["foo", "bar", "baz",], ["foo", "", "bar", "baz",], ["f",], ["",], ["", "f",], [], ["Ää", "\u{10ffff}",],];
for ([idx,testValue,] of testBuffers.entries()) {
readlineBuf(testValue);
var result = [];
while (line = readlineBuf() != null) {
result.push(line);
}
assertDeepEq(result, expected[idx]);
}
readlineBuf(testBuffers[0]);
readlineBuf();
readlineBuf();
readlineBuf(testBuffers[3]);
assertEq(readlineBuf(), expected[3][0]);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/self-test/readlineBuf.js)
<details>
```js
// getprop, proto and self, 3 shapes
var expected = "22,202,99;202,99,22;99,22,202;22,202,99;202,99,22;99,22,202;22,202,99;202,99,22;99,22,202;";
var actual = '';
var protoB = { a: 11, b: 22, c: 33 };
function B() {
}
B.prototype = protoB;
var protoC = { a: 101, b: 202, c: 303 };
function C() {
}
C.prototype = protoC;
function f() {
var o1 = new B();
var o2 = new C();
var o3 = new C();
o3.b = 99;
var oa = [ o1, o2, o3 ];
for (var i = 0; i < 9; ++i) {
// Use 3 PICs so we start out with each type in one PIC.
var i1 = i % 3;
var i2 = (i+1) % 3;
var i3 = (i+2) % 3;
actual += oa[i1].b + ',';
actual += oa[i2].b + ',';
actual += oa[i3].b + ';';
}
}
f();
assertEq(actual, expected);
```
vs
```js
var expected = "22,202,99;202,99,22;99,22,202;22,202,99;202,99,22;99,22,202;22,202,99;202,99,22;99,22,202;";
var actual = '';
var protoB = ({
a: 11,
b: 22,
c: 33,
});
function B() { }
B.prototype = protoB;
var protoC = ({
a: 101,
b: 202,
c: 303,
});
function C() { }
C.prototype = protoC;
function f() {
var o1 = new B();
var o2 = new C();
var o3 = new C();
o3.b = 99;
var oa = [o1, o2, o3,];
for (let i = 0;i < 9;++i) {
var i1 = i % 3;
var i2 = i + 1 % 3;
var i3 = i + 2 % 3;
actual += oa[i1].b + ',';
actual += oa[i2].b + ',';
actual += oa[i3].b + ';';
}
}
f();
assertEq(actual, expected);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/pic/proto_self.js)
<details>
```js
g = newGlobal();
g.parent = this;
function installHook() {
let calledTimes = 0;
function hook() {
calledTimes++;
// Allow the new.target.prototype get to throw.
if (calledTimes === 1)
return undefined;
return {
return: undefined
};
}
Debugger(parent).onExceptionUnwind = hook;
}
g.eval("(" + installHook + ")()");
var handler = {
get(t, p) {
throw new TypeError;
}
};
var f = new Proxy(function(){}, handler);
new f();
```
vs
```js
g = newGlobal();
g.parent = this;
function installHook() {
let calledTimes = 0;
function hook() {
calledTimes++;
if (calledTimes === 1) return undefined;
return {
return: undefined,
};
}
Debugger(parent).onExceptionUnwind = hook;
}
g.eval("(" + installHook + ")()");
var handler = ({
get: (function(t, p) {
throw new TypeError();
}),
});
var f = new Proxy((function() { }), handler);
new f();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/prologueFailure-01.js)
<details>
```js
function test() {
var arr = new Int8Array(400);
var idx = "384";
arr[idx] = 9;
assertEq(arr[idx], 9);
arr[idx] = 10;
assertEq(arr[384], 10);
idx = "512";
assertEq(arr[idx], undefined);
assertEq(arr[(() => "byteLength")()], 400);
var o = {};
Object.defineProperty(o, idx, {value: 123});
assertEq(o[512], 123);
var propLatin1 = "foobar";
o[propLatin1] = 3;
assertEq(o.foobar, 3);
var propTwoByte = "foobar\u1200";
o[propTwoByte] = 4;
assertEq(o.foobar\u1200, 4);
}
test();
```
vs
```js
function test() {
var arr = new Int8Array(400);
var idx = "384";
arr[idx] = 9;
assertEq(arr[idx], 9);
arr[idx] = 10;
assertEq(arr[384], 10);
idx = "512";
assertEq(arr[idx], undefined);
assertEq(arr[() => "byteLength"()], 400);
var o = { };
Object.defineProperty(o, idx, {
value: 123,
});
assertEq(o[512], 123);
var propLatin1 = "foobar";
o[propLatin1] = 3;
assertEq(o.foobar, 3);
var propTwoByte = "foobar\u1200";
o[propTwoByte] = 4;
assertEq(o.foobar\u1200, 4);
}
test();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/latin1/index.js)
<details>
```js
// map.iterator() is live: entries added during iteration are visited.
var map = new Map();
function force(k) {
if (!map.has(k) && k >= 0)
map.set(k, k - 1);
}
force(5);
var log = '';
for (let [k, v] of map) {
log += k + ';';
force(v);
}
assertEq(log, '5;4;3;2;1;0;');
assertEq(map.size, 6);
```
vs
```js
var map = new Map();
function force(k) {
if (!map.has(k) && k >= 0) map.set(k, k - 1);
}
force(5);
var log = '';
for ([k,v,] of map) {
log += k + ';';
force(v);
}
assertEq(log, '5;4;3;2;1;0;');
assertEq(map.size, 6);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-iterator-add-1.js)
<details>
```js
// length, various types
var expected = "4,5,44,5,44,4,44,4,5,4,5,44,5,44,4,44,4,5,";
var actual = '';
function f() {
var a = [ "abcd", [1, 2, 3, 4, 5], { length: 44 } ];
for (var i = 0; i < 6; ++i) {
// Use 3 PICs so we start out with each type in one PIC.
var i1 = i % 3;
var i2 = (i+1) % 3;
var i3 = (i+2) % 3;
actual += a[i1].length + ',';
actual += a[i2].length + ',';
actual += a[i3].length + ',';
}
}
f();
assertEq(actual, expected);
```
vs
```js
var expected = "4,5,44,5,44,4,44,4,5,4,5,44,5,44,4,44,4,5,";
var actual = '';
function f() {
var a = ["abcd", [1, 2, 3, 4, 5,], {
length: 44,
},];
for (let i = 0;i < 6;++i) {
var i1 = i % 3;
var i2 = i + 1 % 3;
var i3 = i + 2 % 3;
actual += a[i1].length + ',';
actual += a[i2].length + ',';
actual += a[i3].length + ',';
}
}
f();
assertEq(actual, expected);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/pic/length_mix.js)
<details>
```js
load(libdir + "asserts.js");
var functionDeclarations = [
"function f(){}",
"function* f(){}",
"async function f(){}",
];
var varDeclarations = [
"var f",
"{ var f; }",
"for (var f in null);",
"for (var f of null);",
"for (var f; ;);",
];
var lexicalDeclarations = [
"let f;",
"const f = 0;",
"class f {};",
];
var imports = [
"import f from '';",
"import f, {} from '';",
"import d, {f} from '';",
"import d, {f as f} from '';",
"import d, {foo as f} from '';",
"import f, * as d from '';",
"import d, * as f from '';",
"import {f} from '';",
"import {f as f} from '';",
"import {foo as f} from '';",
"import* as f from '';",
];
var exports = [
"export var f;",
...functionDeclarations.map(fn => `export ${fn};`),
...lexicalDeclarations.map(ld => `export ${ld};`),
...functionDeclarations.map(fn => `export default ${fn};`),
"export default class f {};",
];
var redeclarations = [
...functionDeclarations,
...varDeclarations,
...lexicalDeclarations,
...imports,
...exports,
];
var noredeclarations = [
...functionDeclarations.map(fn => `{ ${fn} }`),
...lexicalDeclarations.map(ld => `{ ${ld} }`),
...["let", "const"].map(ld => `for (${ld} f in null);`),
...["let", "const"].map(ld => `for (${ld} f of null);`),
...["let", "const"].map(ld => `for (${ld} f = 0; ;);`),
"export {f};",
"export {f as f};",
"export {foo as f}; var foo;",
"export {f} from '';",
"export {f as f} from '';",
"export {foo as f} from '';",
];
for (var decl of functionDeclarations) {
for (var redecl of redeclarations) {
assertThrowsInstanceOf(() => {
parseModule(`
${decl}
${redecl}
`);
}, SyntaxError);
assertThrowsInstanceOf(() => {
parseModule(`
${redecl}
${decl}
`);
}, SyntaxError);
}
for (var redecl of noredeclarations) {
parseModule(`
${decl}
${redecl}
`);
parseModule(`
${redecl}
${decl}
`);
}
}
```
vs
```js
load(libdir + "asserts.js");
var functionDeclarations = ["function f(){}", "function* f(){}", "async function f(){}",];
var varDeclarations = ["var f", "{ var f; }", "for (var f in null);", "for (var f of null);", "for (var f; ;);",];
var lexicalDeclarations = ["let f;", "const f = 0;", "class f {};",];
var imports = ["import f from '';", "import f, {} from '';", "import d, {f} from '';", "import d, {f as f} from '';", "import d, {foo as f} from '';", "import f, * as d from '';", "import d, * as f from '';", "import {f} from '';", "import {f as f} from '';", "import {foo as f} from '';", "import* as f from '';",];
var exports = ["export var f;", ...functionDeclarations.map(fn => `export ${fn};`), ...lexicalDeclarations.map(ld => `export ${ld};`), ...functionDeclarations.map(fn => `export default ${fn};`), "export default class f {};",];
var redeclarations = [...functionDeclarations, ...varDeclarations, ...lexicalDeclarations, ...imports, ...exports,];
var noredeclarations = [...functionDeclarations.map(fn => `{ ${fn} }`), ...lexicalDeclarations.map(ld => `{ ${ld} }`), ...["let", "const",].map(ld => `for (${ld} f in null);`), ...["let", "const",].map(ld => `for (${ld} f of null);`), ...["let", "const",].map(ld => `for (${ld} f = 0; ;);`), "export {f};", "export {f as f};", "export {foo as f}; var foo;", "export {f} from '';", "export {f as f} from '';", "export {foo as f} from '';",];
for (decl of functionDeclarations) {
for (redecl of redeclarations) {
assertThrowsInstanceOf(() => {
parseModule(`
${decl}
{redecl}
`);
}, SyntaxError);
assertThrowsInstanceOf(() => {
parseModule(`
${redecl}
{decl}
`);
}, SyntaxError);
}
for (redecl of noredeclarations) {
parseModule(`
${decl}
{redecl}
`);
parseModule(`
${redecl}
{decl}
`);
}
}
```
<details>
```js
// In a debuggee with live objects, findObjects finds those objects.
var g = newGlobal();
let defObject = v => g.eval(`this.${v} = { toString: () => "[object ${v}]" }`);
defObject("a");
defObject("b");
defObject("c");
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
var aw = gw.makeDebuggeeValue(g.a);
var bw = gw.makeDebuggeeValue(g.b);
var cw = gw.makeDebuggeeValue(g.c);
assertEq(dbg.findObjects().indexOf(aw) != -1, true);
assertEq(dbg.findObjects().indexOf(bw) != -1, true);
assertEq(dbg.findObjects().indexOf(cw) != -1, true);
```
vs
```js
var g = newGlobal();
let defObject = v => g.eval(`this.${v} = { toString: () => "[object {v}]" }`);
defObject("a");
defObject("b");
defObject("c");
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
var aw = gw.makeDebuggeeValue(g.a);
var bw = gw.makeDebuggeeValue(g.b);
var cw = gw.makeDebuggeeValue(g.c);
assertEq(dbg.findObjects().indexOf(aw) != -1, true);
assertEq(dbg.findObjects().indexOf(bw) != -1, true);
assertEq(dbg.findObjects().indexOf(cw) != -1, true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/modules/function-redeclaration.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Debugger-findObjects-02.js)
<details>
```js
// Arguments with default parameters can shadow const locals.
"use strict";
function f() {
const x = 1;
return (x = 0) => x;
}
var g = f();
assertEq(g(), 0);
```
vs
```js
'use strict';
function f() {
const x = 1;
return x = 0 => x;
}
var g = f();
assertEq(g(), 0);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/const-1.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/strict-1.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
function testProperty(i)
{
actual = obj[String(i)];
}
var obj = {};
var index = [null, 1073741824, 1073741825];
for (var j in index)
testProperty(index[j]);
```
vs
```js
function testProperty(i) {
actual = obj[String(i)];
}
var obj = ({});
var index = [null, 1073741824, 1073741825,];
for (j in index) testProperty(index[j]);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/pic/getelem-large-index.js)
<details>
```js
// Rest parameters work in arrow functions
var f = (a, b, ...rest) => [a, b, rest];
assertEq(f().toSource(), "[(void 0), (void 0), []]");
assertEq(f(1, 2, 3, 4).toSource(), "[1, 2, [3, 4]]");
```
vs
```js
var f = (a, b, rest) => [a, b, rest,];
assertEq(f().toSource(), "[(void 0), (void 0), []]");
assertEq(f(1, 2, 3, 4).toSource(), "[1, 2, [3, 4]]");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/params-rest-2.js)
* [Unexpected Token at line: 13, column: 47: Expected `OpenBrace`; found Ident(Ident("f"))](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/class/bug1488385.js)
* [Unable to re-interpret from expression to pattern at line: 19, column: 57](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/WeakSet-error.js)
<details>
```js
// |jit-test| tz-pacific
function arrayExists(array, x) {
for (var i = 0; i < array.length; i++) {
if (array[i] == x) return true;
}
return false;
}
Date.prototype.formatDate = function (input,time) {
// formatDate :
// a PHP date like function, for formatting date strings
// See: http://www.php.net/date
//
// input : format string
// time : epoch time (seconds, and optional)
//
// if time is not passed, formatting is based on
// the current "this" date object's set time.
//
// supported:
// a, A, B, d, D, F, g, G, h, H, i, j, l (lowercase L), L,
// m, M, n, O, r, s, S, t, U, w, W, y, Y, z
//
// unsupported:
// I (capital i), T, Z
var switches = ["a", "A", "B", "d", "D", "F", "g", "G", "h", "H",
"i", "j", "l", "L", "m", "M", "n", "O", "r", "s",
"S", "t", "U", "w", "W", "y", "Y", "z"];
var daysLong = ["Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"];
var daysShort = ["Sun", "Mon", "Tue", "Wed",
"Thu", "Fri", "Sat"];
var monthsShort = ["Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"];
var monthsLong = ["January", "February", "March", "April",
"May", "June", "July", "August", "September",
"October", "November", "December"];
var daysSuffix = ["st", "nd", "rd", "th", "th", "th", "th", // 1st - 7th
"th", "th", "th", "th", "th", "th", "th", // 8th - 14th
"th", "th", "th", "th", "th", "th", "st", // 15th - 21st
"nd", "rd", "th", "th", "th", "th", "th", // 22nd - 28th
"th", "th", "st"]; // 29th - 31st
function a() {
// Lowercase Ante meridiem and Post meridiem
return self.getHours() > 11? "pm" : "am";
}
function A() {
// Uppercase Ante meridiem and Post meridiem
return self.getHours() > 11? "PM" : "AM";
}
function B(){
// Swatch internet time. code simply grabbed from ppk,
// since I was feeling lazy:
// http://www.xs4all.nl/~ppk/js/beat.html
var off = (self.getTimezoneOffset() + 60)*60;
var theSeconds = (self.getHours() * 3600) +
(self.getMinutes() * 60) +
self.getSeconds() + off;
var beat = Math.floor(theSeconds/86.4);
if (beat > 1000) beat -= 1000;
if (beat < 0) beat += 1000;
if ((""+beat).length == 1) beat = "00"+beat;
if ((""+beat).length == 2) beat = "0"+beat;
return beat;
}
function d() {
// Day of the month, 2 digits with leading zeros
return new String(self.getDate()).length == 1?
"0"+self.getDate() : self.getDate();
}
function D() {
// A textual representation of a day, three letters
return daysShort[self.getDay()];
}
function F() {
// A full textual representation of a month
return monthsLong[self.getMonth()];
}
function g() {
// 12-hour format of an hour without leading zeros
return self.getHours() > 12? self.getHours()-12 : self.getHours();
}
function G() {
// 24-hour format of an hour without leading zeros
return self.getHours();
}
function h() {
// 12-hour format of an hour with leading zeros
if (self.getHours() > 12) {
var s = new String(self.getHours()-12);
return s.length == 1?
"0"+ (self.getHours()-12) : self.getHours()-12;
} else {
var s = new String(self.getHours());
return s.length == 1?
"0"+self.getHours() : self.getHours();
}
}
function H() {
// 24-hour format of an hour with leading zeros
return new String(self.getHours()).length == 1?
"0"+self.getHours() : self.getHours();
}
function i() {
// Minutes with leading zeros
return new String(self.getMinutes()).length == 1?
"0"+self.getMinutes() : self.getMinutes();
}
function j() {
// Day of the month without leading zeros
return self.getDate();
}
function l() {
// A full textual representation of the day of the week
return daysLong[self.getDay()];
}
function L() {
// leap year or not. 1 if leap year, 0 if not.
// the logic should match iso's 8601 standard.
var y_ = Y();
if (
(y_ % 4 == 0 && y_ % 100 != 0) ||
(y_ % 4 == 0 && y_ % 100 == 0 && y_ % 400 == 0)
) {
return 1;
} else {
return 0;
}
}
function m() {
// Numeric representation of a month, with leading zeros
return self.getMonth() < 9?
"0"+(self.getMonth()+1) :
self.getMonth()+1;
}
function M() {
// A short textual representation of a month, three letters
return monthsShort[self.getMonth()];
}
function n() {
// Numeric representation of a month, without leading zeros
return self.getMonth()+1;
}
function O() {
// Difference to Greenwich time (GMT) in hours
var os = Math.abs(self.getTimezoneOffset());
var h = ""+Math.floor(os/60);
var m = ""+(os%60);
h.length == 1? h = "0"+h:1;
m.length == 1? m = "0"+m:1;
return self.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;
}
function r() {
// RFC 822 formatted date
var r; // result
// Thu , 21 Dec 2000
r = D() + ", " + j() + " " + M() + " " + Y() +
// 16 : 01 : 07 +0200
" " + H() + ":" + i() + ":" + s() + " " + O();
return r;
}
function S() {
// English ordinal suffix for the day of the month, 2 characters
return daysSuffix[self.getDate()-1];
}
function s() {
// Seconds, with leading zeros
return new String(self.getSeconds()).length == 1?
"0"+self.getSeconds() : self.getSeconds();
}
function t() {
// thanks to Matt Bannon for some much needed code-fixes here!
var daysinmonths = [null,31,28,31,30,31,30,31,31,30,31,30,31];
if (L()==1 && n()==2) return 29; // leap day
return daysinmonths[n()];
}
function U() {
// Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
return Math.round(self.getTime()/1000);
}
function W() {
// Weeknumber, as per ISO specification:
// http://www.cl.cam.ac.uk/~mgk25/iso-time.html
// if the day is three days before newyears eve,
// there's a chance it's "week 1" of next year.
// here we check for that.
var beforeNY = 364+L() - z();
var afterNY = z();
var weekday = w()!=0?w()-1:6; // makes sunday (0), into 6.
if (beforeNY <= 2 && weekday <= 2-beforeNY) {
return 1;
}
// similarly, if the day is within threedays of newyears
// there's a chance it belongs in the old year.
var ny = new Date("January 1 " + Y() + " 00:00:00");
var nyDay = ny.getDay()!=0?ny.getDay()-1:6;
if (
(afterNY <= 2) &&
(nyDay >=4) &&
(afterNY >= (6-nyDay))
) {
// Since I'm not sure we can just always return 53,
// i call the function here again, using the last day
// of the previous year, as the date, and then just
// return that week.
var prevNY = new Date("December 31 " + (Y()-1) + " 00:00:00");
return prevNY.formatDate("W");
}
// week 1, is the week that has the first thursday in it.
// note that this value is not zero index.
if (nyDay <= 3) {
// first day of the year fell on a thursday, or earlier.
return 1 + Math.floor( ( z() + nyDay ) / 7 );
} else {
// first day of the year fell on a friday, or later.
return 1 + Math.floor( ( z() - ( 7 - nyDay ) ) / 7 );
}
}
function w() {
// Numeric representation of the day of the week
return self.getDay();
}
function Y() {
// A full numeric representation of a year, 4 digits
// we first check, if getFullYear is supported. if it
// is, we just use that. ppks code is nice, but wont
// work with dates outside 1900-2038, or something like that
if (self.getFullYear) {
var newDate = new Date("January 1 2001 00:00:00 +0000");
var x = newDate .getFullYear();
if (x == 2001) {
// i trust the method now
return self.getFullYear();
}
}
// else, do this:
// codes thanks to ppk:
// http://www.xs4all.nl/~ppk/js/introdate.html
var x = self.getYear();
var y = x % 100;
y += (y < 38) ? 2000 : 1900;
return y;
}
function y() {
// A two-digit representation of a year
var y = Y()+"";
return y.substring(y.length-2,y.length);
}
function z() {
// The day of the year, zero indexed! 0 through 366
var t = new Date("January 1 " + Y() + " 00:00:00");
var diff = self.getTime() - t.getTime();
return Math.floor(diff/1000/60/60/24);
}
var self = this;
if (time) {
// save time
var prevTime = self.getTime();
self.setTime(time);
}
var ia = input.split("");
var ij = 0;
while (ia[ij]) {
if (ia[ij] == "\\") {
// this is our way of allowing users to escape stuff
ia.splice(ij,1);
} else {
if (arrayExists(switches,ia[ij])) {
ia[ij] = eval(ia[ij] + "()");
}
}
ij++;
}
// reset time, back to what it was
if (prevTime) {
self.setTime(prevTime);
}
return ia.join("");
}
var date = new Date("1/1/2007 1:11:11");
var ret = "";
for (i = 0; i < 500; ++i) {
var shortFormat = date.formatDate("Y-m-d");
var longFormat = date.formatDate("l, F d, Y g:i:s A");
ret += shortFormat + longFormat;
date.setTime(date.getTime() + 84266956);
}
var expected = "2007-01-01Monday, January 01, 2007 1:11:11 AM2007-01-02Tuesday, January 02, 2007 0:35:37 AM2007-01-03Wednesday, January 03, 2007 0:00:04 AM2007-01-03Wednesday, January 03, 2007 11:24:31 PM2007-01-04Thursday, January 04, 2007 10:48:58 PM2007-01-05Friday, January 05, 2007 10:13:25 PM2007-01-06Saturday, January 06, 2007 9:37:52 PM2007-01-07Sunday, January 07, 2007 9:02:19 PM2007-01-08Monday, January 08, 2007 8:26:46 PM2007-01-09Tuesday, January 09, 2007 7:51:13 PM2007-01-10Wednesday, January 10, 2007 7:15:40 PM2007-01-11Thursday, January 11, 2007 6:40:07 PM2007-01-12Friday, January 12, 2007 6:04:34 PM2007-01-13Saturday, January 13, 2007 5:29:01 PM2007-01-14Sunday, January 14, 2007 4:53:28 PM2007-01-15Monday, January 15, 2007 4:17:55 PM2007-01-16Tuesday, January 16, 2007 3:42:22 PM2007-01-17Wednesday, January 17, 2007 3:06:49 PM2007-01-18Thursday, January 18, 2007 2:31:16 PM2007-01-19Friday, January 19, 2007 1:55:43 PM2007-01-20Saturday, January 20, 2007 1:20:10 PM2007-01-21Sunday, January 21, 2007 12:44:37 PM2007-01-22Monday, January 22, 2007 12:09:04 PM2007-01-23Tuesday, January 23, 2007 11:33:30 AM2007-01-24Wednesday, January 24, 2007 10:57:57 AM2007-01-25Thursday, January 25, 2007 10:22:24 AM2007-01-26Friday, January 26, 2007 9:46:51 AM2007-01-27Saturday, January 27, 2007 9:11:18 AM2007-01-28Sunday, January 28, 2007 8:35:45 AM2007-01-29Monday, January 29, 2007 8:00:12 AM2007-01-30Tuesday, January 30, 2007 7:24:39 AM2007-01-31Wednesday, January 31, 2007 6:49:06 AM2007-02-01Thursday, February 01, 2007 6:13:33 AM2007-02-02Friday, February 02, 2007 5:38:00 AM2007-02-03Saturday, February 03, 2007 5:02:27 AM2007-02-04Sunday, February 04, 2007 4:26:54 AM2007-02-05Monday, February 05, 2007 3:51:21 AM2007-02-06Tuesday, February 06, 2007 3:15:48 AM2007-02-07Wednesday, February 07, 2007 2:40:15 AM2007-02-08Thursday, February 08, 2007 2:04:42 AM2007-02-09Friday, February 09, 2007 1:29:09 AM2007-02-10Saturday, February 10, 2007 0:53:36 AM2007-02-11Sunday, February 11, 2007 0:18:03 AM2007-02-11Sunday, February 11, 2007 11:42:30 PM2007-02-12Monday, February 12, 2007 11:06:57 PM2007-02-13Tuesday, February 13, 2007 10:31:24 PM2007-02-14Wednesday, February 14, 2007 9:55:50 PM2007-02-15Thursday, February 15, 2007 9:20:17 PM2007-02-16Friday, February 16, 2007 8:44:44 PM2007-02-17Saturday, February 17, 2007 8:09:11 PM2007-02-18Sunday, February 18, 2007 7:33:38 PM2007-02-19Monday, February 19, 2007 6:58:05 PM2007-02-20Tuesday, February 20, 2007 6:22:32 PM2007-02-21Wednesday, February 21, 2007 5:46:59 PM2007-02-22Thursday, February 22, 2007 5:11:26 PM2007-02-23Friday, February 23, 2007 4:35:53 PM2007-02-24Saturday, February 24, 2007 4:00:20 PM2007-02-25Sunday, February 25, 2007 3:24:47 PM2007-02-26Monday, February 26, 2007 2:49:14 PM2007-02-27Tuesday, February 27, 2007 2:13:41 PM2007-02-28Wednesday, February 28, 2007 1:38:08 PM2007-03-01Thursday, March 01, 2007 1:02:35 PM2007-03-02Friday, March 02, 2007 12:27:02 PM2007-03-03Saturday, March 03, 2007 11:51:29 AM2007-03-04Sunday, March 04, 2007 11:15:56 AM2007-03-05Monday, March 05, 2007 10:40:23 AM2007-03-06Tuesday, March 06, 2007 10:04:50 AM2007-03-07Wednesday, March 07, 2007 9:29:17 AM2007-03-08Thursday, March 08, 2007 8:53:44 AM2007-03-09Friday, March 09, 2007 8:18:10 AM2007-03-10Saturday, March 10, 2007 7:42:37 AM2007-03-11Sunday, March 11, 2007 8:07:04 AM2007-03-12Monday, March 12, 2007 7:31:31 AM2007-03-13Tuesday, March 13, 2007 6:55:58 AM2007-03-14Wednesday, March 14, 2007 6:20:25 AM2007-03-15Thursday, March 15, 2007 5:44:52 AM2007-03-16Friday, March 16, 2007 5:09:19 AM2007-03-17Saturday, March 17, 2007 4:33:46 AM2007-03-18Sunday, March 18, 2007 3:58:13 AM2007-03-19Monday, March 19, 2007 3:22:40 AM2007-03-20Tuesday, March 20, 2007 2:47:07 AM2007-03-21Wednesday, March 21, 2007 2:11:34 AM2007-03-22Thursday, March 22, 2007 1:36:01 AM2007-03-23Friday, March 23, 2007 1:00:28 AM2007-03-24Saturday, March 24, 2007 0:24:55 AM2007-03-24Saturday, March 24, 2007 11:49:22 PM2007-03-25Sunday, March 25, 2007 11:13:49 PM2007-03-26Monday, March 26, 2007 10:38:16 PM2007-03-27Tuesday, March 27, 2007 10:02:43 PM2007-03-28Wednesday, March 28, 2007 9:27:10 PM2007-03-29Thursday, March 29, 2007 8:51:37 PM2007-03-30Friday, March 30, 2007 8:16:03 PM2007-03-31Saturday, March 31, 2007 7:40:30 PM2007-04-01Sunday, April 01, 2007 7:04:57 PM2007-04-02Monday, April 02, 2007 6:29:24 PM2007-04-03Tuesday, April 03, 2007 5:53:51 PM2007-04-04Wednesday, April 04, 2007 5:18:18 PM2007-04-05Thursday, April 05, 2007 4:42:45 PM2007-04-06Friday, April 06, 2007 4:07:12 PM2007-04-07Saturday, April 07, 2007 3:31:39 PM2007-04-08Sunday, April 08, 2007 2:56:06 PM2007-04-09Monday, April 09, 2007 2:20:33 PM2007-04-10Tuesday, April 10, 2007 1:45:00 PM2007-04-11Wednesday, April 11, 2007 1:09:27 PM2007-04-12Thursday, April 12, 2007 12:33:54 PM2007-04-13Friday, April 13, 2007 11:58:21 AM2007-04-14Saturday, April 14, 2007 11:22:48 AM2007-04-15Sunday, April 15, 2007 10:47:15 AM2007-04-16Monday, April 16, 2007 10:11:42 AM2007-04-17Tuesday, April 17, 2007 9:36:09 AM2007-04-18Wednesday, April 18, 2007 9:00:36 AM2007-04-19Thursday, April 19, 2007 8:25:03 AM2007-04-20Friday, April 20, 2007 7:49:30 AM2007-04-21Saturday, April 21, 2007 7:13:57 AM2007-04-22Sunday, April 22, 2007 6:38:23 AM2007-04-23Monday, April 23, 2007 6:02:50 AM2007-04-24Tuesday, April 24, 2007 5:27:17 AM2007-04-25Wednesday, April 25, 2007 4:51:44 AM2007-04-26Thursday, April 26, 2007 4:16:11 AM2007-04-27Friday, April 27, 2007 3:40:38 AM2007-04-28Saturday, April 28, 2007 3:05:05 AM2007-04-29Sunday, April 29, 2007 2:29:32 AM2007-04-30Monday, April 30, 2007 1:53:59 AM2007-05-01Tuesday, May 01, 2007 1:18:26 AM2007-05-02Wednesday, May 02, 2007 0:42:53 AM2007-05-03Thursday, May 03, 2007 0:07:20 AM2007-05-03Thursday, May 03, 2007 11:31:47 PM2007-05-04Friday, May 04, 2007 10:56:14 PM2007-05-05Saturday, May 05, 2007 10:20:41 PM2007-05-06Sunday, May 06, 2007 9:45:08 PM2007-05-07Monday, May 07, 2007 9:09:35 PM2007-05-08Tuesday, May 08, 2007 8:34:02 PM2007-05-09Wednesday, May 09, 2007 7:58:29 PM2007-05-10Thursday, May 10, 2007 7:22:56 PM2007-05-11Friday, May 11, 2007 6:47:23 PM2007-05-12Saturday, May 12, 2007 6:11:50 PM2007-05-13Sunday, May 13, 2007 5:36:17 PM2007-05-14Monday, May 14, 2007 5:00:43 PM2007-05-15Tuesday, May 15, 2007 4:25:10 PM2007-05-16Wednesday, May 16, 2007 3:49:37 PM2007-05-17Thursday, May 17, 2007 3:14:04 PM2007-05-18Friday, May 18, 2007 2:38:31 PM2007-05-19Saturday, May 19, 2007 2:02:58 PM2007-05-20Sunday, May 20, 2007 1:27:25 PM2007-05-21Monday, May 21, 2007 12:51:52 PM2007-05-22Tuesday, May 22, 2007 12:16:19 PM2007-05-23Wednesday, May 23, 2007 11:40:46 AM2007-05-24Thursday, May 24, 2007 11:05:13 AM2007-05-25Friday, May 25, 2007 10:29:40 AM2007-05-26Saturday, May 26, 2007 9:54:07 AM2007-05-27Sunday, May 27, 2007 9:18:34 AM2007-05-28Monday, May 28, 2007 8:43:01 AM2007-05-29Tuesday, May 29, 2007 8:07:28 AM2007-05-30Wednesday, May 30, 2007 7:31:55 AM2007-05-31Thursday, May 31, 2007 6:56:22 AM2007-06-01Friday, June 01, 2007 6:20:49 AM2007-06-02Saturday, June 02, 2007 5:45:16 AM2007-06-03Sunday, June 03, 2007 5:09:43 AM2007-06-04Monday, June 04, 2007 4:34:10 AM2007-06-05Tuesday, June 05, 2007 3:58:37 AM2007-06-06Wednesday, June 06, 2007 3:23:03 AM2007-06-07Thursday, June 07, 2007 2:47:30 AM2007-06-08Friday, June 08, 2007 2:11:57 AM2007-06-09Saturday, June 09, 2007 1:36:24 AM2007-06-10Sunday, June 10, 2007 1:00:51 AM2007-06-11Monday, June 11, 2007 0:25:18 AM2007-06-11Monday, June 11, 2007 11:49:45 PM2007-06-12Tuesday, June 12, 2007 11:14:12 PM2007-06-13Wednesday, June 13, 2007 10:38:39 PM2007-06-14Thursday, June 14, 2007 10:03:06 PM2007-06-15Friday, June 15, 2007 9:27:33 PM2007-06-16Saturday, June 16, 2007 8:52:00 PM2007-06-17Sunday, June 17, 2007 8:16:27 PM2007-06-18Monday, June 18, 2007 7:40:54 PM2007-06-19Tuesday, June 19, 2007 7:05:21 PM2007-06-20Wednesday, June 20, 2007 6:29:48 PM2007-06-21Thursday, June 21, 2007 5:54:15 PM2007-06-22Friday, June 22, 2007 5:18:42 PM2007-06-23Saturday, June 23, 2007 4:43:09 PM2007-06-24Sunday, June 24, 2007 4:07:36 PM2007-06-25Monday, June 25, 2007 3:32:03 PM2007-06-26Tuesday, June 26, 2007 2:56:30 PM2007-06-27Wednesday, June 27, 2007 2:20:56 PM2007-06-28Thursday, June 28, 2007 1:45:23 PM2007-06-29Friday, June 29, 2007 1:09:50 PM2007-06-30Saturday, June 30, 2007 12:34:17 PM2007-07-01Sunday, July 01, 2007 11:58:44 AM2007-07-02Monday, July 02, 2007 11:23:11 AM2007-07-03Tuesday, July 03, 2007 10:47:38 AM2007-07-04Wednesday, July 04, 2007 10:12:05 AM2007-07-05Thursday, July 05, 2007 9:36:32 AM2007-07-06Friday, July 06, 2007 9:00:59 AM2007-07-07Saturday, July 07, 2007 8:25:26 AM2007-07-08Sunday, July 08, 2007 7:49:53 AM2007-07-09Monday, July 09, 2007 7:14:20 AM2007-07-10Tuesday, July 10, 2007 6:38:47 AM2007-07-11Wednesday, July 11, 2007 6:03:14 AM2007-07-12Thursday, July 12, 2007 5:27:41 AM2007-07-13Friday, July 13, 2007 4:52:08 AM2007-07-14Saturday, July 14, 2007 4:16:35 AM2007-07-15Sunday, July 15, 2007 3:41:02 AM2007-07-16Monday, July 16, 2007 3:05:29 AM2007-07-17Tuesday, July 17, 2007 2:29:56 AM2007-07-18Wednesday, July 18, 2007 1:54:23 AM2007-07-19Thursday, July 19, 2007 1:18:50 AM2007-07-20Friday, July 20, 2007 0:43:16 AM2007-07-21Saturday, July 21, 2007 0:07:43 AM2007-07-21Saturday, July 21, 2007 11:32:10 PM2007-07-22Sunday, July 22, 2007 10:56:37 PM2007-07-23Monday, July 23, 2007 10:21:04 PM2007-07-24Tuesday, July 24, 2007 9:45:31 PM2007-07-25Wednesday, July 25, 2007 9:09:58 PM2007-07-26Thursday, July 26, 2007 8:34:25 PM2007-07-27Friday, July 27, 2007 7:58:52 PM2007-07-28Saturday, July 28, 2007 7:23:19 PM2007-07-29Sunday, July 29, 2007 6:47:46 PM2007-07-30Monday, July 30, 2007 6:12:13 PM2007-07-31Tuesday, July 31, 2007 5:36:40 PM2007-08-01Wednesday, August 01, 2007 5:01:07 PM2007-08-02Thursday, August 02, 2007 4:25:34 PM2007-08-03Friday, August 03, 2007 3:50:01 PM2007-08-04Saturday, August 04, 2007 3:14:28 PM2007-08-05Sunday, August 05, 2007 2:38:55 PM2007-08-06Monday, August 06, 2007 2:03:22 PM2007-08-07Tuesday, August 07, 2007 1:27:49 PM2007-08-08Wednesday, August 08, 2007 12:52:16 PM2007-08-09Thursday, August 09, 2007 12:16:43 PM2007-08-10Friday, August 10, 2007 11:41:10 AM2007-08-11Saturday, August 11, 2007 11:05:36 AM2007-08-12Sunday, August 12, 2007 10:30:03 AM2007-08-13Monday, August 13, 2007 9:54:30 AM2007-08-14Tuesday, August 14, 2007 9:18:57 AM2007-08-15Wednesday, August 15, 2007 8:43:24 AM2007-08-16Thursday, August 16, 2007 8:07:51 AM2007-08-17Friday, August 17, 2007 7:32:18 AM2007-08-18Saturday, August 18, 2007 6:56:45 AM2007-08-19Sunday, August 19, 2007 6:21:12 AM2007-08-20Monday, August 20, 2007 5:45:39 AM2007-08-21Tuesday, August 21, 2007 5:10:06 AM2007-08-22Wednesday, August 22, 2007 4:34:33 AM2007-08-23Thursday, August 23, 2007 3:59:00 AM2007-08-24Friday, August 24, 2007 3:23:27 AM2007-08-25Saturday, August 25, 2007 2:47:54 AM2007-08-26Sunday, August 26, 2007 2:12:21 AM2007-08-27Monday, August 27, 2007 1:36:48 AM2007-08-28Tuesday, August 28, 2007 1:01:15 AM2007-08-29Wednesday, August 29, 2007 0:25:42 AM2007-08-29Wednesday, August 29, 2007 11:50:09 PM2007-08-30Thursday, August 30, 2007 11:14:36 PM2007-08-31Friday, August 31, 2007 10:39:03 PM2007-09-01Saturday, September 01, 2007 10:03:30 PM2007-09-02Sunday, September 02, 2007 9:27:56 PM2007-09-03Monday, September 03, 2007 8:52:23 PM2007-09-04Tuesday, September 04, 2007 8:16:50 PM2007-09-05Wednesday, September 05, 2007 7:41:17 PM2007-09-06Thursday, September 06, 2007 7:05:44 PM2007-09-07Friday, September 07, 2007 6:30:11 PM2007-09-08Saturday, September 08, 2007 5:54:38 PM2007-09-09Sunday, September 09, 2007 5:19:05 PM2007-09-10Monday, September 10, 2007 4:43:32 PM2007-09-11Tuesday, September 11, 2007 4:07:59 PM2007-09-12Wednesday, September 12, 2007 3:32:26 PM2007-09-13Thursday, September 13, 2007 2:56:53 PM2007-09-14Friday, September 14, 2007 2:21:20 PM2007-09-15Saturday, September 15, 2007 1:45:47 PM2007-09-16Sunday, September 16, 2007 1:10:14 PM2007-09-17Monday, September 17, 2007 12:34:41 PM2007-09-18Tuesday, September 18, 2007 11:59:08 AM2007-09-19Wednesday, September 19, 2007 11:23:35 AM2007-09-20Thursday, September 20, 2007 10:48:02 AM2007-09-21Friday, September 21, 2007 10:12:29 AM2007-09-22Saturday, September 22, 2007 9:36:56 AM2007-09-23Sunday, September 23, 2007 9:01:23 AM2007-09-24Monday, September 24, 2007 8:25:49 AM2007-09-25Tuesday, September 25, 2007 7:50:16 AM2007-09-26Wednesday, September 26, 2007 7:14:43 AM2007-09-27Thursday, September 27, 2007 6:39:10 AM2007-09-28Friday, September 28, 2007 6:03:37 AM2007-09-29Saturday, September 29, 2007 5:28:04 AM2007-09-30Sunday, September 30, 2007 4:52:31 AM2007-10-01Monday, October 01, 2007 4:16:58 AM2007-10-02Tuesday, October 02, 2007 3:41:25 AM2007-10-03Wednesday, October 03, 2007 3:05:52 AM2007-10-04Thursday, October 04, 2007 2:30:19 AM2007-10-05Friday, October 05, 2007 1:54:46 AM2007-10-06Saturday, October 06, 2007 1:19:13 AM2007-10-07Sunday, October 07, 2007 0:43:40 AM2007-10-08Monday, October 08, 2007 0:08:07 AM2007-10-08Monday, October 08, 2007 11:32:34 PM2007-10-09Tuesday, October 09, 2007 10:57:01 PM2007-10-10Wednesday, October 10, 2007 10:21:28 PM2007-10-11Thursday, October 11, 2007 9:45:55 PM2007-10-12Friday, October 12, 2007 9:10:22 PM2007-10-13Saturday, October 13, 2007 8:34:49 PM2007-10-14Sunday, October 14, 2007 7:59:16 PM2007-10-15Monday, October 15, 2007 7:23:43 PM2007-10-16Tuesday, October 16, 2007 6:48:09 PM2007-10-17Wednesday, October 17, 2007 6:12:36 PM2007-10-18Thursday, October 18, 2007 5:37:03 PM2007-10-19Friday, October 19, 2007 5:01:30 PM2007-10-20Saturday, October 20, 2007 4:25:57 PM2007-10-21Sunday, October 21, 2007 3:50:24 PM2007-10-22Monday, October 22, 2007 3:14:51 PM2007-10-23Tuesday, October 23, 2007 2:39:18 PM2007-10-24Wednesday, October 24, 2007 2:03:45 PM2007-10-25Thursday, October 25, 2007 1:28:12 PM2007-10-26Friday, October 26, 2007 12:52:39 PM2007-10-27Saturday, October 27, 2007 12:17:06 PM2007-10-28Sunday, October 28, 2007 11:41:33 AM2007-10-29Monday, October 29, 2007 11:06:00 AM2007-10-30Tuesday, October 30, 2007 10:30:27 AM2007-10-31Wednesday, October 31, 2007 9:54:54 AM2007-11-01Thursday, November 01, 2007 9:19:21 AM2007-11-02Friday, November 02, 2007 8:43:48 AM2007-11-03Saturday, November 03, 2007 8:08:15 AM2007-11-04Sunday, November 04, 2007 6:32:42 AM2007-11-05Monday, November 05, 2007 5:57:09 AM2007-11-06Tuesday, November 06, 2007 5:21:36 AM2007-11-07Wednesday, November 07, 2007 4:46:03 AM2007-11-08Thursday, November 08, 2007 4:10:29 AM2007-11-09Friday, November 09, 2007 3:34:56 AM2007-11-10Saturday, November 10, 2007 2:59:23 AM2007-11-11Sunday, November 11, 2007 2:23:50 AM2007-11-12Monday, November 12, 2007 1:48:17 AM2007-11-13Tuesday, November 13, 2007 1:12:44 AM2007-11-14Wednesday, November 14, 2007 0:37:11 AM2007-11-15Thursday, November 15, 2007 0:01:38 AM2007-11-15Thursday, November 15, 2007 11:26:05 PM2007-11-16Friday, November 16, 2007 10:50:32 PM2007-11-17Saturday, November 17, 2007 10:14:59 PM2007-11-18Sunday, November 18, 2007 9:39:26 PM2007-11-19Monday, November 19, 2007 9:03:53 PM2007-11-20Tuesday, November 20, 2007 8:28:20 PM2007-11-21Wednesday, November 21, 2007 7:52:47 PM2007-11-22Thursday, November 22, 2007 7:17:14 PM2007-11-23Friday, November 23, 2007 6:41:41 PM2007-11-24Saturday, November 24, 2007 6:06:08 PM2007-11-25Sunday, November 25, 2007 5:30:35 PM2007-11-26Monday, November 26, 2007 4:55:02 PM2007-11-27Tuesday, November 27, 2007 4:19:29 PM2007-11-28Wednesday, November 28, 2007 3:43:56 PM2007-11-29Thursday, November 29, 2007 3:08:22 PM2007-11-30Friday, November 30, 2007 2:32:49 PM2007-12-01Saturday, December 01, 2007 1:57:16 PM2007-12-02Sunday, December 02, 2007 1:21:43 PM2007-12-03Monday, December 03, 2007 12:46:10 PM2007-12-04Tuesday, December 04, 2007 12:10:37 PM2007-12-05Wednesday, December 05, 2007 11:35:04 AM2007-12-06Thursday, December 06, 2007 10:59:31 AM2007-12-07Friday, December 07, 2007 10:23:58 AM2007-12-08Saturday, December 08, 2007 9:48:25 AM2007-12-09Sunday, December 09, 2007 9:12:52 AM2007-12-10Monday, December 10, 2007 8:37:19 AM2007-12-11Tuesday, December 11, 2007 8:01:46 AM2007-12-12Wednesday, December 12, 2007 7:26:13 AM2007-12-13Thursday, December 13, 2007 6:50:40 AM2007-12-14Friday, December 14, 2007 6:15:07 AM2007-12-15Saturday, December 15, 2007 5:39:34 AM2007-12-16Sunday, December 16, 2007 5:04:01 AM2007-12-17Monday, December 17, 2007 4:28:28 AM2007-12-18Tuesday, December 18, 2007 3:52:55 AM2007-12-19Wednesday, December 19, 2007 3:17:22 AM2007-12-20Thursday, December 20, 2007 2:41:49 AM2007-12-21Friday, December 21, 2007 2:06:16 AM2007-12-22Saturday, December 22, 2007 1:30:42 AM2007-12-23Sunday, December 23, 2007 0:55:09 AM2007-12-24Monday, December 24, 2007 0:19:36 AM2007-12-24Monday, December 24, 2007 11:44:03 PM2007-12-25Tuesday, December 25, 2007 11:08:30 PM2007-12-26Wednesday, December 26, 2007 10:32:57 PM2007-12-27Thursday, December 27, 2007 9:57:24 PM2007-12-28Friday, December 28, 2007 9:21:51 PM2007-12-29Saturday, December 29, 2007 8:46:18 PM2007-12-30Sunday, December 30, 2007 8:10:45 PM2007-12-31Monday, December 31, 2007 7:35:12 PM2008-01-01Tuesday, January 01, 2008 6:59:39 PM2008-01-02Wednesday, January 02, 2008 6:24:06 PM2008-01-03Thursday, January 03, 2008 5:48:33 PM2008-01-04Friday, January 04, 2008 5:13:00 PM2008-01-05Saturday, January 05, 2008 4:37:27 PM2008-01-06Sunday, January 06, 2008 4:01:54 PM2008-01-07Monday, January 07, 2008 3:26:21 PM2008-01-08Tuesday, January 08, 2008 2:50:48 PM2008-01-09Wednesday, January 09, 2008 2:15:15 PM2008-01-10Thursday, January 10, 2008 1:39:42 PM2008-01-11Friday, January 11, 2008 1:04:09 PM2008-01-12Saturday, January 12, 2008 12:28:36 PM2008-01-13Sunday, January 13, 2008 11:53:02 AM2008-01-14Monday, January 14, 2008 11:17:29 AM2008-01-15Tuesday, January 15, 2008 10:41:56 AM2008-01-16Wednesday, January 16, 2008 10:06:23 AM2008-01-17Thursday, January 17, 2008 9:30:50 AM2008-01-18Friday, January 18, 2008 8:55:17 AM2008-01-19Saturday, January 19, 2008 8:19:44 AM2008-01-20Sunday, January 20, 2008 7:44:11 AM2008-01-21Monday, January 21, 2008 7:08:38 AM2008-01-22Tuesday, January 22, 2008 6:33:05 AM2008-01-23Wednesday, January 23, 2008 5:57:32 AM2008-01-24Thursday, January 24, 2008 5:21:59 AM2008-01-25Friday, January 25, 2008 4:46:26 AM2008-01-26Saturday, January 26, 2008 4:10:53 AM2008-01-27Sunday, January 27, 2008 3:35:20 AM2008-01-28Monday, January 28, 2008 2:59:47 AM2008-01-29Tuesday, January 29, 2008 2:24:14 AM2008-01-30Wednesday, January 30, 2008 1:48:41 AM2008-01-31Thursday, January 31, 2008 1:13:08 AM2008-02-01Friday, February 01, 2008 0:37:35 AM2008-02-02Saturday, February 02, 2008 0:02:02 AM2008-02-02Saturday, February 02, 2008 11:26:29 PM2008-02-03Sunday, February 03, 2008 10:50:56 PM2008-02-04Monday, February 04, 2008 10:15:22 PM2008-02-05Tuesday, February 05, 2008 9:39:49 PM2008-02-06Wednesday, February 06, 2008 9:04:16 PM2008-02-07Thursday, February 07, 2008 8:28:43 PM2008-02-08Friday, February 08, 2008 7:53:10 PM2008-02-09Saturday, February 09, 2008 7:17:37 PM2008-02-10Sunday, February 10, 2008 6:42:04 PM2008-02-11Monday, February 11, 2008 6:06:31 PM2008-02-12Tuesday, February 12, 2008 5:30:58 PM2008-02-13Wednesday, February 13, 2008 4:55:25 PM2008-02-14Thursday, February 14, 2008 4:19:52 PM2008-02-15Friday, February 15, 2008 3:44:19 PM2008-02-16Saturday, February 16, 2008 3:08:46 PM2008-02-17Sunday, February 17, 2008 2:33:13 PM2008-02-18Monday, February 18, 2008 1:57:40 PM2008-02-19Tuesday, February 19, 2008 1:22:07 PM2008-02-20Wednesday, February 20, 2008 12:46:34 PM2008-02-21Thursday, February 21, 2008 12:11:01 PM2008-02-22Friday, February 22, 2008 11:35:28 AM2008-02-23Saturday, February 23, 2008 10:59:55 AM2008-02-24Sunday, February 24, 2008 10:24:22 AM2008-02-25Monday, February 25, 2008 9:48:49 AM2008-02-26Tuesday, February 26, 2008 9:13:15 AM2008-02-27Wednesday, February 27, 2008 8:37:42 AM2008-02-28Thursday, February 28, 2008 8:02:09 AM2008-02-29Friday, February 29, 2008 7:26:36 AM2008-03-01Saturday, March 01, 2008 6:51:03 AM2008-03-02Sunday, March 02, 2008 6:15:30 AM2008-03-03Monday, March 03, 2008 5:39:57 AM2008-03-04Tuesday, March 04, 2008 5:04:24 AM2008-03-05Wednesday, March 05, 2008 4:28:51 AM2008-03-06Thursday, March 06, 2008 3:53:18 AM2008-03-07Friday, March 07, 2008 3:17:45 AM2008-03-08Saturday, March 08, 2008 2:42:12 AM2008-03-09Sunday, March 09, 2008 3:06:39 AM2008-03-10Monday, March 10, 2008 2:31:06 AM2008-03-11Tuesday, March 11, 2008 1:55:33 AM2008-03-12Wednesday, March 12, 2008 1:20:00 AM2008-03-13Thursday, March 13, 2008 0:44:27 AM2008-03-14Friday, March 14, 2008 0:08:54 AM2008-03-14Friday, March 14, 2008 11:33:21 PM2008-03-15Saturday, March 15, 2008 10:57:48 PM2008-03-16Sunday, March 16, 2008 10:22:15 PM2008-03-17Monday, March 17, 2008 9:46:42 PM2008-03-18Tuesday, March 18, 2008 9:11:09 PM2008-03-19Wednesday, March 19, 2008 8:35:35 PM2008-03-20Thursday, March 20, 2008 8:00:02 PM2008-03-21Friday, March 21, 2008 7:24:29 PM2008-03-22Saturday, March 22, 2008 6:48:56 PM2008-03-23Sunday, March 23, 2008 6:13:23 PM2008-03-24Monday, March 24, 2008 5:37:50 PM2008-03-25Tuesday, March 25, 2008 5:02:17 PM2008-03-26Wednesday, March 26, 2008 4:26:44 PM2008-03-27Thursday, March 27, 2008 3:51:11 PM2008-03-28Friday, March 28, 2008 3:15:38 PM2008-03-29Saturday, March 29, 2008 2:40:05 PM2008-03-30Sunday, March 30, 2008 2:04:32 PM2008-03-31Monday, March 31, 2008 1:28:59 PM2008-04-01Tuesday, April 01, 2008 12:53:26 PM2008-04-02Wednesday, April 02, 2008 12:17:53 PM2008-04-03Thursday, April 03, 2008 11:42:20 AM2008-04-04Friday, April 04, 2008 11:06:47 AM2008-04-05Saturday, April 05, 2008 10:31:14 AM2008-04-06Sunday, April 06, 2008 9:55:41 AM2008-04-07Monday, April 07, 2008 9:20:08 AM2008-04-08Tuesday, April 08, 2008 8:44:35 AM2008-04-09Wednesday, April 09, 2008 8:09:02 AM2008-04-10Thursday, April 10, 2008 7:33:29 AM2008-04-11Friday, April 11, 2008 6:57:55 AM2008-04-12Saturday, April 12, 2008 6:22:22 AM2008-04-13Sunday, April 13, 2008 5:46:49 AM2008-04-14Monday, April 14, 2008 5:11:16 AM2008-04-15Tuesday, April 15, 2008 4:35:43 AM2008-04-16Wednesday, April 16, 2008 4:00:10 AM2008-04-17Thursday, April 17, 2008 3:24:37 AM2008-04-18Friday, April 18, 2008 2:49:04 AM2008-04-19Saturday, April 19, 2008 2:13:31 AM2008-04-20Sunday, April 20, 2008 1:37:58 AM2008-04-21Monday, April 21, 2008 1:02:25 AM2008-04-22Tuesday, April 22, 2008 0:26:52 AM2008-04-22Tuesday, April 22, 2008 11:51:19 PM2008-04-23Wednesday, April 23, 2008 11:15:46 PM2008-04-24Thursday, April 24, 2008 10:40:13 PM2008-04-25Friday, April 25, 2008 10:04:40 PM2008-04-26Saturday, April 26, 2008 9:29:07 PM2008-04-27Sunday, April 27, 2008 8:53:34 PM2008-04-28Monday, April 28, 2008 8:18:01 PM2008-04-29Tuesday, April 29, 2008 7:42:28 PM2008-04-30Wednesday, April 30, 2008 7:06:55 PM2008-05-01Thursday, May 01, 2008 6:31:22 PM"
assertEq(ret, expected);
```
vs
```js
function arrayExists(array, x) {
for (let i = 0;i < array.length;i++) {
if (array[i] == x) return true;
}
return false;
}
Date.prototype.formatDate = (function(input, time) {
var switches = ["a", "A", "B", "d", "D", "F", "g", "G", "h", "H", "i", "j", "l", "L", "m", "M", "n", "O", "r", "s", "S", "t", "U", "w", "W", "y", "Y", "z",];
var daysLong = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday",];
var daysShort = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",];
var monthsShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",];
var monthsLong = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December",];
var daysSuffix = ["st", "nd", "rd", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th", "th", "st",];
function a() {
return self.getHours() > 11 ? "pm" : "am";
}
function A() {
return self.getHours() > 11 ? "PM" : "AM";
}
function B() {
var off = self.getTimezoneOffset() + 60 * 60;
var theSeconds = self.getHours() * 3600 + self.getMinutes() * 60 + self.getSeconds() + off;
var beat = Math.floor(theSeconds / 86.4);
if (beat > 1000) beat -= 1000;
if (beat < 0) beat += 1000;
if ("" + beat.length == 1) beat = "00" + beat;
if ("" + beat.length == 2) beat = "0" + beat;
return beat;
}
function d() {
return new String(self.getDate()).length == 1 ? "0" + self.getDate() : self.getDate();
}
function D() {
return daysShort[self.getDay()];
}
function F() {
return monthsLong[self.getMonth()];
}
function g() {
return self.getHours() > 12 ? self.getHours() - 12 : self.getHours();
}
function G() {
return self.getHours();
}
function h() {
if (self.getHours() > 12) {
var s = new String(self.getHours() - 12);
return s.length == 1 ? "0" + self.getHours() - 12 : self.getHours() - 12;
} else {
var s = new String(self.getHours());
return s.length == 1 ? "0" + self.getHours() : self.getHours();
}
}
function H() {
return new String(self.getHours()).length == 1 ? "0" + self.getHours() : self.getHours();
}
function i() {
return new String(self.getMinutes()).length == 1 ? "0" + self.getMinutes() : self.getMinutes();
}
function j() {
return self.getDate();
}
function l() {
return daysLong[self.getDay()];
}
function L() {
var y_ = Y();
if (y_ % 4 == 0 && y_ % 100 != 0 || y_ % 4 == 0 && y_ % 100 == 0 && y_ % 400 == 0) {
return 1;
} else {
return 0;
}
}
function m() {
return self.getMonth() < 9 ? "0" + self.getMonth() + 1 : self.getMonth() + 1;
}
function M() {
return monthsShort[self.getMonth()];
}
function n() {
return self.getMonth() + 1;
}
function O() {
var os = Math.abs(self.getTimezoneOffset());
var h = "" + Math.floor(os / 60);
var m = "" + os % 60;
h.length == 1 ? h = "0" + h : 1;
m.length == 1 ? m = "0" + m : 1;
return self.getTimezoneOffset() < 0 ? "+" + h + m : "-" + h + m;
}
function r() {
var r;
r = D() + ", " + j() + " " + M() + " " + Y() + " " + H() + ":" + i() + ":" + s() + " " + O();
return r;
}
function S() {
return daysSuffix[self.getDate() - 1];
}
function s() {
return new String(self.getSeconds()).length == 1 ? "0" + self.getSeconds() : self.getSeconds();
}
function t() {
var daysinmonths = [null, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,];
if (L() == 1 && n() == 2) return 29;
return daysinmonths[n()];
}
function U() {
return Math.round(self.getTime() / 1000);
}
function W() {
var beforeNY = 364 + L() - z();
var afterNY = z();
var weekday = w() != 0 ? w() - 1 : 6;
if (beforeNY <= 2 && weekday <= 2 - beforeNY) {
return 1;
}
var ny = new Date("January 1 " + Y() + " 00:00:00");
var nyDay = ny.getDay() != 0 ? ny.getDay() - 1 : 6;
if (afterNY <= 2 && nyDay >= 4 && afterNY >= 6 - nyDay) {
var prevNY = new Date("December 31 " + Y() - 1 + " 00:00:00");
return prevNY.formatDate("W");
}
if (nyDay <= 3) {
return 1 + Math.floor(z() + nyDay / 7);
} else {
return 1 + Math.floor(z() - 7 - nyDay / 7);
}
}
function w() {
return self.getDay();
}
function Y() {
if (self.getFullYear) {
var newDate = new Date("January 1 2001 00:00:00 +0000");
var x = newDate.getFullYear();
if (x == 2001) {
return self.getFullYear();
}
}
var x = self.getYear();
var y = x % 100;
y += y < 38 ? 2000 : 1900;
return y;
}
function y() {
var y = Y() + "";
return y.substring(y.length - 2, y.length);
}
function z() {
var t = new Date("January 1 " + Y() + " 00:00:00");
var diff = self.getTime() - t.getTime();
return Math.floor(diff / 1000 / 60 / 60 / 24);
}
var self = this;
if (time) {
var prevTime = self.getTime();
self.setTime(time);
}
var ia = input.split("");
var ij = 0;
while (ia[ij]) {
if (ia[ij] == "\\") {
ia.splice(ij, 1);
} else {
if (arrayExists(switches, ia[ij])) {
ia[ij] = eval(ia[ij] + "()");
}
}
ij++;
}
if (prevTime) {
self.setTime(prevTime);
}
return ia.join("");
});
var date = new Date("1/1/2007 1:11:11");
var ret = "";
for (i = 0;i < 500;++i) {
var shortFormat = date.formatDate("Y-m-d");
var longFormat = date.formatDate("l, F d, Y g:i:s A");
ret += shortFormat + longFormat;
date.setTime(date.getTime() + 84266956);
}
var expected = "2007-01-01Monday, January 01, 2007 1:11:11 AM2007-01-02Tuesday, January 02, 2007 0:35:37 AM2007-01-03Wednesday, January 03, 2007 0:00:04 AM2007-01-03Wednesday, January 03, 2007 11:24:31 PM2007-01-04Thursday, January 04, 2007 10:48:58 PM2007-01-05Friday, January 05, 2007 10:13:25 PM2007-01-06Saturday, January 06, 2007 9:37:52 PM2007-01-07Sunday, January 07, 2007 9:02:19 PM2007-01-08Monday, January 08, 2007 8:26:46 PM2007-01-09Tuesday, January 09, 2007 7:51:13 PM2007-01-10Wednesday, January 10, 2007 7:15:40 PM2007-01-11Thursday, January 11, 2007 6:40:07 PM2007-01-12Friday, January 12, 2007 6:04:34 PM2007-01-13Saturday, January 13, 2007 5:29:01 PM2007-01-14Sunday, January 14, 2007 4:53:28 PM2007-01-15Monday, January 15, 2007 4:17:55 PM2007-01-16Tuesday, January 16, 2007 3:42:22 PM2007-01-17Wednesday, January 17, 2007 3:06:49 PM2007-01-18Thursday, January 18, 2007 2:31:16 PM2007-01-19Friday, January 19, 2007 1:55:43 PM2007-01-20Saturday, January 20, 2007 1:20:10 PM2007-01-21Sunday, January 21, 2007 12:44:37 PM2007-01-22Monday, January 22, 2007 12:09:04 PM2007-01-23Tuesday, January 23, 2007 11:33:30 AM2007-01-24Wednesday, January 24, 2007 10:57:57 AM2007-01-25Thursday, January 25, 2007 10:22:24 AM2007-01-26Friday, January 26, 2007 9:46:51 AM2007-01-27Saturday, January 27, 2007 9:11:18 AM2007-01-28Sunday, January 28, 2007 8:35:45 AM2007-01-29Monday, January 29, 2007 8:00:12 AM2007-01-30Tuesday, January 30, 2007 7:24:39 AM2007-01-31Wednesday, January 31, 2007 6:49:06 AM2007-02-01Thursday, February 01, 2007 6:13:33 AM2007-02-02Friday, February 02, 2007 5:38:00 AM2007-02-03Saturday, February 03, 2007 5:02:27 AM2007-02-04Sunday, February 04, 2007 4:26:54 AM2007-02-05Monday, February 05, 2007 3:51:21 AM2007-02-06Tuesday, February 06, 2007 3:15:48 AM2007-02-07Wednesday, February 07, 2007 2:40:15 AM2007-02-08Thursday, February 08, 2007 2:04:42 AM2007-02-09Friday, February 09, 2007 1:29:09 AM2007-02-10Saturday, February 10, 2007 0:53:36 AM2007-02-11Sunday, February 11, 2007 0:18:03 AM2007-02-11Sunday, February 11, 2007 11:42:30 PM2007-02-12Monday, February 12, 2007 11:06:57 PM2007-02-13Tuesday, February 13, 2007 10:31:24 PM2007-02-14Wednesday, February 14, 2007 9:55:50 PM2007-02-15Thursday, February 15, 2007 9:20:17 PM2007-02-16Friday, February 16, 2007 8:44:44 PM2007-02-17Saturday, February 17, 2007 8:09:11 PM2007-02-18Sunday, February 18, 2007 7:33:38 PM2007-02-19Monday, February 19, 2007 6:58:05 PM2007-02-20Tuesday, February 20, 2007 6:22:32 PM2007-02-21Wednesday, February 21, 2007 5:46:59 PM2007-02-22Thursday, February 22, 2007 5:11:26 PM2007-02-23Friday, February 23, 2007 4:35:53 PM2007-02-24Saturday, February 24, 2007 4:00:20 PM2007-02-25Sunday, February 25, 2007 3:24:47 PM2007-02-26Monday, February 26, 2007 2:49:14 PM2007-02-27Tuesday, February 27, 2007 2:13:41 PM2007-02-28Wednesday, February 28, 2007 1:38:08 PM2007-03-01Thursday, March 01, 2007 1:02:35 PM2007-03-02Friday, March 02, 2007 12:27:02 PM2007-03-03Saturday, March 03, 2007 11:51:29 AM2007-03-04Sunday, March 04, 2007 11:15:56 AM2007-03-05Monday, March 05, 2007 10:40:23 AM2007-03-06Tuesday, March 06, 2007 10:04:50 AM2007-03-07Wednesday, March 07, 2007 9:29:17 AM2007-03-08Thursday, March 08, 2007 8:53:44 AM2007-03-09Friday, March 09, 2007 8:18:10 AM2007-03-10Saturday, March 10, 2007 7:42:37 AM2007-03-11Sunday, March 11, 2007 8:07:04 AM2007-03-12Monday, March 12, 2007 7:31:31 AM2007-03-13Tuesday, March 13, 2007 6:55:58 AM2007-03-14Wednesday, March 14, 2007 6:20:25 AM2007-03-15Thursday, March 15, 2007 5:44:52 AM2007-03-16Friday, March 16, 2007 5:09:19 AM2007-03-17Saturday, March 17, 2007 4:33:46 AM2007-03-18Sunday, March 18, 2007 3:58:13 AM2007-03-19Monday, March 19, 2007 3:22:40 AM2007-03-20Tuesday, March 20, 2007 2:47:07 AM2007-03-21Wednesday, March 21, 2007 2:11:34 AM2007-03-22Thursday, March 22, 2007 1:36:01 AM2007-03-23Friday, March 23, 2007 1:00:28 AM2007-03-24Saturday, March 24, 2007 0:24:55 AM2007-03-24Saturday, March 24, 2007 11:49:22 PM2007-03-25Sunday, March 25, 2007 11:13:49 PM2007-03-26Monday, March 26, 2007 10:38:16 PM2007-03-27Tuesday, March 27, 2007 10:02:43 PM2007-03-28Wednesday, March 28, 2007 9:27:10 PM2007-03-29Thursday, March 29, 2007 8:51:37 PM2007-03-30Friday, March 30, 2007 8:16:03 PM2007-03-31Saturday, March 31, 2007 7:40:30 PM2007-04-01Sunday, April 01, 2007 7:04:57 PM2007-04-02Monday, April 02, 2007 6:29:24 PM2007-04-03Tuesday, April 03, 2007 5:53:51 PM2007-04-04Wednesday, April 04, 2007 5:18:18 PM2007-04-05Thursday, April 05, 2007 4:42:45 PM2007-04-06Friday, April 06, 2007 4:07:12 PM2007-04-07Saturday, April 07, 2007 3:31:39 PM2007-04-08Sunday, April 08, 2007 2:56:06 PM2007-04-09Monday, April 09, 2007 2:20:33 PM2007-04-10Tuesday, April 10, 2007 1:45:00 PM2007-04-11Wednesday, April 11, 2007 1:09:27 PM2007-04-12Thursday, April 12, 2007 12:33:54 PM2007-04-13Friday, April 13, 2007 11:58:21 AM2007-04-14Saturday, April 14, 2007 11:22:48 AM2007-04-15Sunday, April 15, 2007 10:47:15 AM2007-04-16Monday, April 16, 2007 10:11:42 AM2007-04-17Tuesday, April 17, 2007 9:36:09 AM2007-04-18Wednesday, April 18, 2007 9:00:36 AM2007-04-19Thursday, April 19, 2007 8:25:03 AM2007-04-20Friday, April 20, 2007 7:49:30 AM2007-04-21Saturday, April 21, 2007 7:13:57 AM2007-04-22Sunday, April 22, 2007 6:38:23 AM2007-04-23Monday, April 23, 2007 6:02:50 AM2007-04-24Tuesday, April 24, 2007 5:27:17 AM2007-04-25Wednesday, April 25, 2007 4:51:44 AM2007-04-26Thursday, April 26, 2007 4:16:11 AM2007-04-27Friday, April 27, 2007 3:40:38 AM2007-04-28Saturday, April 28, 2007 3:05:05 AM2007-04-29Sunday, April 29, 2007 2:29:32 AM2007-04-30Monday, April 30, 2007 1:53:59 AM2007-05-01Tuesday, May 01, 2007 1:18:26 AM2007-05-02Wednesday, May 02, 2007 0:42:53 AM2007-05-03Thursday, May 03, 2007 0:07:20 AM2007-05-03Thursday, May 03, 2007 11:31:47 PM2007-05-04Friday, May 04, 2007 10:56:14 PM2007-05-05Saturday, May 05, 2007 10:20:41 PM2007-05-06Sunday, May 06, 2007 9:45:08 PM2007-05-07Monday, May 07, 2007 9:09:35 PM2007-05-08Tuesday, May 08, 2007 8:34:02 PM2007-05-09Wednesday, May 09, 2007 7:58:29 PM2007-05-10Thursday, May 10, 2007 7:22:56 PM2007-05-11Friday, May 11, 2007 6:47:23 PM2007-05-12Saturday, May 12, 2007 6:11:50 PM2007-05-13Sunday, May 13, 2007 5:36:17 PM2007-05-14Monday, May 14, 2007 5:00:43 PM2007-05-15Tuesday, May 15, 2007 4:25:10 PM2007-05-16Wednesday, May 16, 2007 3:49:37 PM2007-05-17Thursday, May 17, 2007 3:14:04 PM2007-05-18Friday, May 18, 2007 2:38:31 PM2007-05-19Saturday, May 19, 2007 2:02:58 PM2007-05-20Sunday, May 20, 2007 1:27:25 PM2007-05-21Monday, May 21, 2007 12:51:52 PM2007-05-22Tuesday, May 22, 2007 12:16:19 PM2007-05-23Wednesday, May 23, 2007 11:40:46 AM2007-05-24Thursday, May 24, 2007 11:05:13 AM2007-05-25Friday, May 25, 2007 10:29:40 AM2007-05-26Saturday, May 26, 2007 9:54:07 AM2007-05-27Sunday, May 27, 2007 9:18:34 AM2007-05-28Monday, May 28, 2007 8:43:01 AM2007-05-29Tuesday, May 29, 2007 8:07:28 AM2007-05-30Wednesday, May 30, 2007 7:31:55 AM2007-05-31Thursday, May 31, 2007 6:56:22 AM2007-06-01Friday, June 01, 2007 6:20:49 AM2007-06-02Saturday, June 02, 2007 5:45:16 AM2007-06-03Sunday, June 03, 2007 5:09:43 AM2007-06-04Monday, June 04, 2007 4:34:10 AM2007-06-05Tuesday, June 05, 2007 3:58:37 AM2007-06-06Wednesday, June 06, 2007 3:23:03 AM2007-06-07Thursday, June 07, 2007 2:47:30 AM2007-06-08Friday, June 08, 2007 2:11:57 AM2007-06-09Saturday, June 09, 2007 1:36:24 AM2007-06-10Sunday, June 10, 2007 1:00:51 AM2007-06-11Monday, June 11, 2007 0:25:18 AM2007-06-11Monday, June 11, 2007 11:49:45 PM2007-06-12Tuesday, June 12, 2007 11:14:12 PM2007-06-13Wednesday, June 13, 2007 10:38:39 PM2007-06-14Thursday, June 14, 2007 10:03:06 PM2007-06-15Friday, June 15, 2007 9:27:33 PM2007-06-16Saturday, June 16, 2007 8:52:00 PM2007-06-17Sunday, June 17, 2007 8:16:27 PM2007-06-18Monday, June 18, 2007 7:40:54 PM2007-06-19Tuesday, June 19, 2007 7:05:21 PM2007-06-20Wednesday, June 20, 2007 6:29:48 PM2007-06-21Thursday, June 21, 2007 5:54:15 PM2007-06-22Friday, June 22, 2007 5:18:42 PM2007-06-23Saturday, June 23, 2007 4:43:09 PM2007-06-24Sunday, June 24, 2007 4:07:36 PM2007-06-25Monday, June 25, 2007 3:32:03 PM2007-06-26Tuesday, June 26, 2007 2:56:30 PM2007-06-27Wednesday, June 27, 2007 2:20:56 PM2007-06-28Thursday, June 28, 2007 1:45:23 PM2007-06-29Friday, June 29, 2007 1:09:50 PM2007-06-30Saturday, June 30, 2007 12:34:17 PM2007-07-01Sunday, July 01, 2007 11:58:44 AM2007-07-02Monday, July 02, 2007 11:23:11 AM2007-07-03Tuesday, July 03, 2007 10:47:38 AM2007-07-04Wednesday, July 04, 2007 10:12:05 AM2007-07-05Thursday, July 05, 2007 9:36:32 AM2007-07-06Friday, July 06, 2007 9:00:59 AM2007-07-07Saturday, July 07, 2007 8:25:26 AM2007-07-08Sunday, July 08, 2007 7:49:53 AM2007-07-09Monday, July 09, 2007 7:14:20 AM2007-07-10Tuesday, July 10, 2007 6:38:47 AM2007-07-11Wednesday, July 11, 2007 6:03:14 AM2007-07-12Thursday, July 12, 2007 5:27:41 AM2007-07-13Friday, July 13, 2007 4:52:08 AM2007-07-14Saturday, July 14, 2007 4:16:35 AM2007-07-15Sunday, July 15, 2007 3:41:02 AM2007-07-16Monday, July 16, 2007 3:05:29 AM2007-07-17Tuesday, July 17, 2007 2:29:56 AM2007-07-18Wednesday, July 18, 2007 1:54:23 AM2007-07-19Thursday, July 19, 2007 1:18:50 AM2007-07-20Friday, July 20, 2007 0:43:16 AM2007-07-21Saturday, July 21, 2007 0:07:43 AM2007-07-21Saturday, July 21, 2007 11:32:10 PM2007-07-22Sunday, July 22, 2007 10:56:37 PM2007-07-23Monday, July 23, 2007 10:21:04 PM2007-07-24Tuesday, July 24, 2007 9:45:31 PM2007-07-25Wednesday, July 25, 2007 9:09:58 PM2007-07-26Thursday, July 26, 2007 8:34:25 PM2007-07-27Friday, July 27, 2007 7:58:52 PM2007-07-28Saturday, July 28, 2007 7:23:19 PM2007-07-29Sunday, July 29, 2007 6:47:46 PM2007-07-30Monday, July 30, 2007 6:12:13 PM2007-07-31Tuesday, July 31, 2007 5:36:40 PM2007-08-01Wednesday, August 01, 2007 5:01:07 PM2007-08-02Thursday, August 02, 2007 4:25:34 PM2007-08-03Friday, August 03, 2007 3:50:01 PM2007-08-04Saturday, August 04, 2007 3:14:28 PM2007-08-05Sunday, August 05, 2007 2:38:55 PM2007-08-06Monday, August 06, 2007 2:03:22 PM2007-08-07Tuesday, August 07, 2007 1:27:49 PM2007-08-08Wednesday, August 08, 2007 12:52:16 PM2007-08-09Thursday, August 09, 2007 12:16:43 PM2007-08-10Friday, August 10, 2007 11:41:10 AM2007-08-11Saturday, August 11, 2007 11:05:36 AM2007-08-12Sunday, August 12, 2007 10:30:03 AM2007-08-13Monday, August 13, 2007 9:54:30 AM2007-08-14Tuesday, August 14, 2007 9:18:57 AM2007-08-15Wednesday, August 15, 2007 8:43:24 AM2007-08-16Thursday, August 16, 2007 8:07:51 AM2007-08-17Friday, August 17, 2007 7:32:18 AM2007-08-18Saturday, August 18, 2007 6:56:45 AM2007-08-19Sunday, August 19, 2007 6:21:12 AM2007-08-20Monday, August 20, 2007 5:45:39 AM2007-08-21Tuesday, August 21, 2007 5:10:06 AM2007-08-22Wednesday, August 22, 2007 4:34:33 AM2007-08-23Thursday, August 23, 2007 3:59:00 AM2007-08-24Friday, August 24, 2007 3:23:27 AM2007-08-25Saturday, August 25, 2007 2:47:54 AM2007-08-26Sunday, August 26, 2007 2:12:21 AM2007-08-27Monday, August 27, 2007 1:36:48 AM2007-08-28Tuesday, August 28, 2007 1:01:15 AM2007-08-29Wednesday, August 29, 2007 0:25:42 AM2007-08-29Wednesday, August 29, 2007 11:50:09 PM2007-08-30Thursday, August 30, 2007 11:14:36 PM2007-08-31Friday, August 31, 2007 10:39:03 PM2007-09-01Saturday, September 01, 2007 10:03:30 PM2007-09-02Sunday, September 02, 2007 9:27:56 PM2007-09-03Monday, September 03, 2007 8:52:23 PM2007-09-04Tuesday, September 04, 2007 8:16:50 PM2007-09-05Wednesday, September 05, 2007 7:41:17 PM2007-09-06Thursday, September 06, 2007 7:05:44 PM2007-09-07Friday, September 07, 2007 6:30:11 PM2007-09-08Saturday, September 08, 2007 5:54:38 PM2007-09-09Sunday, September 09, 2007 5:19:05 PM2007-09-10Monday, September 10, 2007 4:43:32 PM2007-09-11Tuesday, September 11, 2007 4:07:59 PM2007-09-12Wednesday, September 12, 2007 3:32:26 PM2007-09-13Thursday, September 13, 2007 2:56:53 PM2007-09-14Friday, September 14, 2007 2:21:20 PM2007-09-15Saturday, September 15, 2007 1:45:47 PM2007-09-16Sunday, September 16, 2007 1:10:14 PM2007-09-17Monday, September 17, 2007 12:34:41 PM2007-09-18Tuesday, September 18, 2007 11:59:08 AM2007-09-19Wednesday, September 19, 2007 11:23:35 AM2007-09-20Thursday, September 20, 2007 10:48:02 AM2007-09-21Friday, September 21, 2007 10:12:29 AM2007-09-22Saturday, September 22, 2007 9:36:56 AM2007-09-23Sunday, September 23, 2007 9:01:23 AM2007-09-24Monday, September 24, 2007 8:25:49 AM2007-09-25Tuesday, September 25, 2007 7:50:16 AM2007-09-26Wednesday, September 26, 2007 7:14:43 AM2007-09-27Thursday, September 27, 2007 6:39:10 AM2007-09-28Friday, September 28, 2007 6:03:37 AM2007-09-29Saturday, September 29, 2007 5:28:04 AM2007-09-30Sunday, September 30, 2007 4:52:31 AM2007-10-01Monday, October 01, 2007 4:16:58 AM2007-10-02Tuesday, October 02, 2007 3:41:25 AM2007-10-03Wednesday, October 03, 2007 3:05:52 AM2007-10-04Thursday, October 04, 2007 2:30:19 AM2007-10-05Friday, October 05, 2007 1:54:46 AM2007-10-06Saturday, October 06, 2007 1:19:13 AM2007-10-07Sunday, October 07, 2007 0:43:40 AM2007-10-08Monday, October 08, 2007 0:08:07 AM2007-10-08Monday, October 08, 2007 11:32:34 PM2007-10-09Tuesday, October 09, 2007 10:57:01 PM2007-10-10Wednesday, October 10, 2007 10:21:28 PM2007-10-11Thursday, October 11, 2007 9:45:55 PM2007-10-12Friday, October 12, 2007 9:10:22 PM2007-10-13Saturday, October 13, 2007 8:34:49 PM2007-10-14Sunday, October 14, 2007 7:59:16 PM2007-10-15Monday, October 15, 2007 7:23:43 PM2007-10-16Tuesday, October 16, 2007 6:48:09 PM2007-10-17Wednesday, October 17, 2007 6:12:36 PM2007-10-18Thursday, October 18, 2007 5:37:03 PM2007-10-19Friday, October 19, 2007 5:01:30 PM2007-10-20Saturday, October 20, 2007 4:25:57 PM2007-10-21Sunday, October 21, 2007 3:50:24 PM2007-10-22Monday, October 22, 2007 3:14:51 PM2007-10-23Tuesday, October 23, 2007 2:39:18 PM2007-10-24Wednesday, October 24, 2007 2:03:45 PM2007-10-25Thursday, October 25, 2007 1:28:12 PM2007-10-26Friday, October 26, 2007 12:52:39 PM2007-10-27Saturday, October 27, 2007 12:17:06 PM2007-10-28Sunday, October 28, 2007 11:41:33 AM2007-10-29Monday, October 29, 2007 11:06:00 AM2007-10-30Tuesday, October 30, 2007 10:30:27 AM2007-10-31Wednesday, October 31, 2007 9:54:54 AM2007-11-01Thursday, November 01, 2007 9:19:21 AM2007-11-02Friday, November 02, 2007 8:43:48 AM2007-11-03Saturday, November 03, 2007 8:08:15 AM2007-11-04Sunday, November 04, 2007 6:32:42 AM2007-11-05Monday, November 05, 2007 5:57:09 AM2007-11-06Tuesday, November 06, 2007 5:21:36 AM2007-11-07Wednesday, November 07, 2007 4:46:03 AM2007-11-08Thursday, November 08, 2007 4:10:29 AM2007-11-09Friday, November 09, 2007 3:34:56 AM2007-11-10Saturday, November 10, 2007 2:59:23 AM2007-11-11Sunday, November 11, 2007 2:23:50 AM2007-11-12Monday, November 12, 2007 1:48:17 AM2007-11-13Tuesday, November 13, 2007 1:12:44 AM2007-11-14Wednesday, November 14, 2007 0:37:11 AM2007-11-15Thursday, November 15, 2007 0:01:38 AM2007-11-15Thursday, November 15, 2007 11:26:05 PM2007-11-16Friday, November 16, 2007 10:50:32 PM2007-11-17Saturday, November 17, 2007 10:14:59 PM2007-11-18Sunday, November 18, 2007 9:39:26 PM2007-11-19Monday, November 19, 2007 9:03:53 PM2007-11-20Tuesday, November 20, 2007 8:28:20 PM2007-11-21Wednesday, November 21, 2007 7:52:47 PM2007-11-22Thursday, November 22, 2007 7:17:14 PM2007-11-23Friday, November 23, 2007 6:41:41 PM2007-11-24Saturday, November 24, 2007 6:06:08 PM2007-11-25Sunday, November 25, 2007 5:30:35 PM2007-11-26Monday, November 26, 2007 4:55:02 PM2007-11-27Tuesday, November 27, 2007 4:19:29 PM2007-11-28Wednesday, November 28, 2007 3:43:56 PM2007-11-29Thursday, November 29, 2007 3:08:22 PM2007-11-30Friday, November 30, 2007 2:32:49 PM2007-12-01Saturday, December 01, 2007 1:57:16 PM2007-12-02Sunday, December 02, 2007 1:21:43 PM2007-12-03Monday, December 03, 2007 12:46:10 PM2007-12-04Tuesday, December 04, 2007 12:10:37 PM2007-12-05Wednesday, December 05, 2007 11:35:04 AM2007-12-06Thursday, December 06, 2007 10:59:31 AM2007-12-07Friday, December 07, 2007 10:23:58 AM2007-12-08Saturday, December 08, 2007 9:48:25 AM2007-12-09Sunday, December 09, 2007 9:12:52 AM2007-12-10Monday, December 10, 2007 8:37:19 AM2007-12-11Tuesday, December 11, 2007 8:01:46 AM2007-12-12Wednesday, December 12, 2007 7:26:13 AM2007-12-13Thursday, December 13, 2007 6:50:40 AM2007-12-14Friday, December 14, 2007 6:15:07 AM2007-12-15Saturday, December 15, 2007 5:39:34 AM2007-12-16Sunday, December 16, 2007 5:04:01 AM2007-12-17Monday, December 17, 2007 4:28:28 AM2007-12-18Tuesday, December 18, 2007 3:52:55 AM2007-12-19Wednesday, December 19, 2007 3:17:22 AM2007-12-20Thursday, December 20, 2007 2:41:49 AM2007-12-21Friday, December 21, 2007 2:06:16 AM2007-12-22Saturday, December 22, 2007 1:30:42 AM2007-12-23Sunday, December 23, 2007 0:55:09 AM2007-12-24Monday, December 24, 2007 0:19:36 AM2007-12-24Monday, December 24, 2007 11:44:03 PM2007-12-25Tuesday, December 25, 2007 11:08:30 PM2007-12-26Wednesday, December 26, 2007 10:32:57 PM2007-12-27Thursday, December 27, 2007 9:57:24 PM2007-12-28Friday, December 28, 2007 9:21:51 PM2007-12-29Saturday, December 29, 2007 8:46:18 PM2007-12-30Sunday, December 30, 2007 8:10:45 PM2007-12-31Monday, December 31, 2007 7:35:12 PM2008-01-01Tuesday, January 01, 2008 6:59:39 PM2008-01-02Wednesday, January 02, 2008 6:24:06 PM2008-01-03Thursday, January 03, 2008 5:48:33 PM2008-01-04Friday, January 04, 2008 5:13:00 PM2008-01-05Saturday, January 05, 2008 4:37:27 PM2008-01-06Sunday, January 06, 2008 4:01:54 PM2008-01-07Monday, January 07, 2008 3:26:21 PM2008-01-08Tuesday, January 08, 2008 2:50:48 PM2008-01-09Wednesday, January 09, 2008 2:15:15 PM2008-01-10Thursday, January 10, 2008 1:39:42 PM2008-01-11Friday, January 11, 2008 1:04:09 PM2008-01-12Saturday, January 12, 2008 12:28:36 PM2008-01-13Sunday, January 13, 2008 11:53:02 AM2008-01-14Monday, January 14, 2008 11:17:29 AM2008-01-15Tuesday, January 15, 2008 10:41:56 AM2008-01-16Wednesday, January 16, 2008 10:06:23 AM2008-01-17Thursday, January 17, 2008 9:30:50 AM2008-01-18Friday, January 18, 2008 8:55:17 AM2008-01-19Saturday, January 19, 2008 8:19:44 AM2008-01-20Sunday, January 20, 2008 7:44:11 AM2008-01-21Monday, January 21, 2008 7:08:38 AM2008-01-22Tuesday, January 22, 2008 6:33:05 AM2008-01-23Wednesday, January 23, 2008 5:57:32 AM2008-01-24Thursday, January 24, 2008 5:21:59 AM2008-01-25Friday, January 25, 2008 4:46:26 AM2008-01-26Saturday, January 26, 2008 4:10:53 AM2008-01-27Sunday, January 27, 2008 3:35:20 AM2008-01-28Monday, January 28, 2008 2:59:47 AM2008-01-29Tuesday, January 29, 2008 2:24:14 AM2008-01-30Wednesday, January 30, 2008 1:48:41 AM2008-01-31Thursday, January 31, 2008 1:13:08 AM2008-02-01Friday, February 01, 2008 0:37:35 AM2008-02-02Saturday, February 02, 2008 0:02:02 AM2008-02-02Saturday, February 02, 2008 11:26:29 PM2008-02-03Sunday, February 03, 2008 10:50:56 PM2008-02-04Monday, February 04, 2008 10:15:22 PM2008-02-05Tuesday, February 05, 2008 9:39:49 PM2008-02-06Wednesday, February 06, 2008 9:04:16 PM2008-02-07Thursday, February 07, 2008 8:28:43 PM2008-02-08Friday, February 08, 2008 7:53:10 PM2008-02-09Saturday, February 09, 2008 7:17:37 PM2008-02-10Sunday, February 10, 2008 6:42:04 PM2008-02-11Monday, February 11, 2008 6:06:31 PM2008-02-12Tuesday, February 12, 2008 5:30:58 PM2008-02-13Wednesday, February 13, 2008 4:55:25 PM2008-02-14Thursday, February 14, 2008 4:19:52 PM2008-02-15Friday, February 15, 2008 3:44:19 PM2008-02-16Saturday, February 16, 2008 3:08:46 PM2008-02-17Sunday, February 17, 2008 2:33:13 PM2008-02-18Monday, February 18, 2008 1:57:40 PM2008-02-19Tuesday, February 19, 2008 1:22:07 PM2008-02-20Wednesday, February 20, 2008 12:46:34 PM2008-02-21Thursday, February 21, 2008 12:11:01 PM2008-02-22Friday, February 22, 2008 11:35:28 AM2008-02-23Saturday, February 23, 2008 10:59:55 AM2008-02-24Sunday, February 24, 2008 10:24:22 AM2008-02-25Monday, February 25, 2008 9:48:49 AM2008-02-26Tuesday, February 26, 2008 9:13:15 AM2008-02-27Wednesday, February 27, 2008 8:37:42 AM2008-02-28Thursday, February 28, 2008 8:02:09 AM2008-02-29Friday, February 29, 2008 7:26:36 AM2008-03-01Saturday, March 01, 2008 6:51:03 AM2008-03-02Sunday, March 02, 2008 6:15:30 AM2008-03-03Monday, March 03, 2008 5:39:57 AM2008-03-04Tuesday, March 04, 2008 5:04:24 AM2008-03-05Wednesday, March 05, 2008 4:28:51 AM2008-03-06Thursday, March 06, 2008 3:53:18 AM2008-03-07Friday, March 07, 2008 3:17:45 AM2008-03-08Saturday, March 08, 2008 2:42:12 AM2008-03-09Sunday, March 09, 2008 3:06:39 AM2008-03-10Monday, March 10, 2008 2:31:06 AM2008-03-11Tuesday, March 11, 2008 1:55:33 AM2008-03-12Wednesday, March 12, 2008 1:20:00 AM2008-03-13Thursday, March 13, 2008 0:44:27 AM2008-03-14Friday, March 14, 2008 0:08:54 AM2008-03-14Friday, March 14, 2008 11:33:21 PM2008-03-15Saturday, March 15, 2008 10:57:48 PM2008-03-16Sunday, March 16, 2008 10:22:15 PM2008-03-17Monday, March 17, 2008 9:46:42 PM2008-03-18Tuesday, March 18, 2008 9:11:09 PM2008-03-19Wednesday, March 19, 2008 8:35:35 PM2008-03-20Thursday, March 20, 2008 8:00:02 PM2008-03-21Friday, March 21, 2008 7:24:29 PM2008-03-22Saturday, March 22, 2008 6:48:56 PM2008-03-23Sunday, March 23, 2008 6:13:23 PM2008-03-24Monday, March 24, 2008 5:37:50 PM2008-03-25Tuesday, March 25, 2008 5:02:17 PM2008-03-26Wednesday, March 26, 2008 4:26:44 PM2008-03-27Thursday, March 27, 2008 3:51:11 PM2008-03-28Friday, March 28, 2008 3:15:38 PM2008-03-29Saturday, March 29, 2008 2:40:05 PM2008-03-30Sunday, March 30, 2008 2:04:32 PM2008-03-31Monday, March 31, 2008 1:28:59 PM2008-04-01Tuesday, April 01, 2008 12:53:26 PM2008-04-02Wednesday, April 02, 2008 12:17:53 PM2008-04-03Thursday, April 03, 2008 11:42:20 AM2008-04-04Friday, April 04, 2008 11:06:47 AM2008-04-05Saturday, April 05, 2008 10:31:14 AM2008-04-06Sunday, April 06, 2008 9:55:41 AM2008-04-07Monday, April 07, 2008 9:20:08 AM2008-04-08Tuesday, April 08, 2008 8:44:35 AM2008-04-09Wednesday, April 09, 2008 8:09:02 AM2008-04-10Thursday, April 10, 2008 7:33:29 AM2008-04-11Friday, April 11, 2008 6:57:55 AM2008-04-12Saturday, April 12, 2008 6:22:22 AM2008-04-13Sunday, April 13, 2008 5:46:49 AM2008-04-14Monday, April 14, 2008 5:11:16 AM2008-04-15Tuesday, April 15, 2008 4:35:43 AM2008-04-16Wednesday, April 16, 2008 4:00:10 AM2008-04-17Thursday, April 17, 2008 3:24:37 AM2008-04-18Friday, April 18, 2008 2:49:04 AM2008-04-19Saturday, April 19, 2008 2:13:31 AM2008-04-20Sunday, April 20, 2008 1:37:58 AM2008-04-21Monday, April 21, 2008 1:02:25 AM2008-04-22Tuesday, April 22, 2008 0:26:52 AM2008-04-22Tuesday, April 22, 2008 11:51:19 PM2008-04-23Wednesday, April 23, 2008 11:15:46 PM2008-04-24Thursday, April 24, 2008 10:40:13 PM2008-04-25Friday, April 25, 2008 10:04:40 PM2008-04-26Saturday, April 26, 2008 9:29:07 PM2008-04-27Sunday, April 27, 2008 8:53:34 PM2008-04-28Monday, April 28, 2008 8:18:01 PM2008-04-29Tuesday, April 29, 2008 7:42:28 PM2008-04-30Wednesday, April 30, 2008 7:06:55 PM2008-05-01Thursday, May 01, 2008 6:31:22 PM";
assertEq(ret, expected);
```
<details>
```js
// Tests that NX disallows debuggee execution for all debuggees.
load(libdir + "asserts.js");
load(libdir + "debuggerNXHelper.js");
var g1 = newGlobal();
var g2 = newGlobal();
var dbg = new Debugger;
dbg.addDebuggee(g1);
dbg.addDebuggee(g2);
g1.eval(`
function f() { }
var o = {
get p() { },
set p(x) { }
};
`);
g2.eval(`
function f() { }
var o = {
get p() { },
set p(x) { }
};
`);
var handlers = [() => { g1.f(); },
() => { g1.o.p } ,
() => { g1.o.p = 42; },
() => { g2.f(); },
() => { g2.o.p } ,
() => { g2.o.p = 42; } ];
function testHook(hookName) {
for (var h of handlers) {
assertThrowsInstanceOf(h, Debugger.DebuggeeWouldRun);
}
}
testDebuggerHooksNX(dbg, g1, testHook);
testDebuggerHooksNX(dbg, g2, testHook);
```
vs
```js
load(libdir + "asserts.js");
load(libdir + "debuggerNXHelper.js");
var g1 = newGlobal();
var g2 = newGlobal();
var dbg = new Debugger();
dbg.addDebuggee(g1);
dbg.addDebuggee(g2);
g1.eval(`
function f() { }
var o = {
get p() { },
set p(x) { }
};
`);
g2.eval(`
function f() { }
var o = {
get p() { },
set p(x) { }
};
`);
var handlers = [() => {
g1.f();
}, () => {
g1.o.p;
}, () => {
g1.o.p = 42;
}, () => {
g2.f();
}, () => {
g2.o.p;
}, () => {
g2.o.p = 42;
},];
function testHook(hookName) {
for (h of handlers) {
assertThrowsInstanceOf(h, Debugger.DebuggeeWouldRun);
}
}
testDebuggerHooksNX(dbg, g1, testHook);
testDebuggerHooksNX(dbg, g2, testHook);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/noExecute-05.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-date-format-tofte.js)
<details>
```js
// Basic functional tests for the Atomics primitives.
//
// These do not test atomicity, just that calling and coercions and
// indexing and exception behavior all work right.
//
// These do not test the wait/wake operations.
load(libdir + "asserts.js");
var DEBUG = false; // Set to true for useful printouts
function dprint(...xs) {
if (!DEBUG)
return;
var s = "";
for ( var x in xs )
s += String(xs[x]);
print(s);
}
// Clone a function so that we get reliable inlining of primitives with --ion-eager.
// For eg testMethod and testFunction that are polymorphic in the array a,
// the inliner gets confused and stops inlining after Int8 -- not what we want.
function CLONE(f) {
return this.eval("(" + f.toSource() + ")");
}
function testMethod(a, ...indices) {
dprint("Method: " + a.constructor.name);
var poison;
switch (a.BYTES_PER_ELEMENT) {
case 1: poison = 0x5A; break;
case 2: poison = 0x5A5A; break;
case 4: poison = 0x5A5A5A5A; break;
}
for ( var i=0 ; i < indices.length ; i++ ) {
var x = indices[i];
if (x > 0)
a[x-1] = poison;
if (x < a.length-1)
a[x+1] = poison;
// val = 0
assertEq(Atomics.compareExchange(a, x, 0, 37), 0);
// val = 37
assertEq(Atomics.compareExchange(a, x, 37, 5), 37);
// val = 5
assertEq(Atomics.compareExchange(a, x, 7, 8), 5); // ie should fail
// val = 5
assertEq(Atomics.compareExchange(a, x, 5, 9), 5);
// val = 9
assertEq(Atomics.compareExchange(a, x, 5, 0), 9); // should also fail
// val = 9
assertEq(Atomics.exchange(a, x, 4), 9);
// val = 4
assertEq(Atomics.exchange(a, x, 9), 4);
// val = 9
assertEq(Atomics.load(a, x), 9);
// val = 9
assertEq(Atomics.store(a, x, 14), 14); // What about coercion?
// val = 14
assertEq(Atomics.load(a, x), 14);
// val = 14
Atomics.store(a, x, 0);
// val = 0
// val = 0
assertEq(Atomics.add(a, x, 3), 0);
// val = 3
assertEq(Atomics.sub(a, x, 2), 3);
// val = 1
assertEq(Atomics.or(a, x, 6), 1);
// val = 7
assertEq(Atomics.and(a, x, 14), 7);
// val = 6
assertEq(Atomics.xor(a, x, 5), 6);
// val = 3
assertEq(Atomics.load(a, x), 3);
// val = 3
Atomics.store(a, x, 0);
// val = 0
// Check adjacent elements were not affected
if (x > 0) {
assertEq(a[x-1], poison);
a[x-1] = 0;
}
if (x < a.length-1) {
assertEq(a[x+1], poison);
a[x+1] = 0;
}
}
}
function testFunction(a, ...indices) {
dprint("Function: " + a.constructor.name);
var poison;
switch (a.BYTES_PER_ELEMENT) {
case 1: poison = 0x5A; break;
case 2: poison = 0x5A5A; break;
case 4: poison = 0x5A5A5A5A; break;
}
for ( var i=0 ; i < indices.length ; i++ ) {
var x = indices[i];
if (x > 0)
a[x-1] = poison;
if (x < a.length-1)
a[x+1] = poison;
// val = 0
assertEq(gAtomics_compareExchange(a, x, 0, 37), 0);
// val = 37
assertEq(gAtomics_compareExchange(a, x, 37, 5), 37);
// val = 5
assertEq(gAtomics_compareExchange(a, x, 7, 8), 5); // ie should fail
// val = 5
assertEq(gAtomics_compareExchange(a, x, 5, 9), 5);
// val = 9
assertEq(gAtomics_compareExchange(a, x, 5, 0), 9); // should also fail
// val = 9
assertEq(gAtomics_exchange(a, x, 4), 9);
// val = 4
assertEq(gAtomics_exchange(a, x, 9), 4);
// val = 9
assertEq(gAtomics_load(a, x), 9);
// val = 9
assertEq(gAtomics_store(a, x, 14), 14); // What about coercion?
// val = 14
assertEq(gAtomics_load(a, x), 14);
// val = 14
gAtomics_store(a, x, 0);
// val = 0
// val = 0
assertEq(gAtomics_add(a, x, 3), 0);
// val = 3
assertEq(gAtomics_sub(a, x, 2), 3);
// val = 1
assertEq(gAtomics_or(a, x, 6), 1);
// val = 7
assertEq(gAtomics_and(a, x, 14), 7);
// val = 6
assertEq(gAtomics_xor(a, x, 5), 6);
// val = 3
assertEq(gAtomics_load(a, x), 3);
// val = 3
gAtomics_store(a, x, 0);
// val = 0
// Check adjacent elements were not affected
if (x > 0) {
assertEq(a[x-1], poison);
a[x-1] = 0;
}
if (x < a.length-1) {
assertEq(a[x+1], poison);
a[x+1] = 0;
}
}
}
function testTypeCAS(a) {
dprint("Type: " + a.constructor.name);
var thrown = false;
try {
Atomics.compareExchange([0], 0, 0, 1);
}
catch (e) {
thrown = true;
assertEq(e instanceof TypeError, true);
}
assertEq(thrown, true);
// All these variants should be OK
Atomics.compareExchange(a, 0, 0.7, 1.8);
Atomics.compareExchange(a, 0, "0", 1);
Atomics.compareExchange(a, 0, 0, "1");
Atomics.compareExchange(a, 0, 0);
}
function testTypeBinop(a, op) {
dprint("Type: " + a.constructor.name);
var thrown = false;
try {
op([0], 0, 1);
}
catch (e) {
thrown = true;
assertEq(e instanceof TypeError, true);
}
assertEq(thrown, true);
// These are all OK
op(a, 0, 0.7);
op(a, 0, "0");
op(a, 0);
}
var globlength = 0; // Will be set later
function testRangeCAS(a) {
dprint("Range: " + a.constructor.name);
var msg = /out-of-range index/; // A generic message
assertErrorMessage(() => Atomics.compareExchange(a, -1, 0, 1), RangeError, msg);
assertEq(a[0], 0);
// Converted to 0
assertEq(Atomics.compareExchange(a, "hi", 0, 33), 0);
assertEq(a[0], 33);
a[0] = 0;
assertErrorMessage(() => Atomics.compareExchange(a, a.length + 5, 0, 1), RangeError, msg);
assertEq(a[0], 0);
assertErrorMessage(() => Atomics.compareExchange(a, globlength, 0, 1), RangeError, msg);
assertEq(a[0], 0);
}
// Ad-hoc tests for extreme and out-of-range values.
// None of these should throw
function testInt8Extremes(a) {
dprint("Int8 extremes");
a[10] = 0;
a[11] = 0;
Atomics.store(a, 10, 255);
assertEq(a[10], -1);
assertEq(Atomics.load(a, 10), -1);
Atomics.add(a, 10, 255); // should coerce to -1
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.add(a, 10, -1);
assertEq(a[10], -3);
assertEq(Atomics.load(a, 10), -3);
Atomics.sub(a, 10, 255); // should coerce to -1
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.sub(a, 10, 256); // should coerce to 0
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.and(a, 10, -1); // Preserve all
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.and(a, 10, 256); // Preserve none
assertEq(a[10], 0);
assertEq(Atomics.load(a, 10), 0);
Atomics.store(a, 10, 255);
assertEq(Atomics.exchange(a, 10, 0), -1);
assertEq(a[11], 0);
}
function testUint8Extremes(a) {
dprint("Uint8 extremes");
a[10] = 0;
a[11] = 0;
Atomics.store(a, 10, 255);
assertEq(a[10], 255);
assertEq(Atomics.load(a, 10), 255);
Atomics.add(a, 10, 255);
assertEq(a[10], 254);
assertEq(Atomics.load(a, 10), 254);
Atomics.add(a, 10, -1);
assertEq(a[10], 253);
assertEq(Atomics.load(a, 10), 253);
Atomics.sub(a, 10, 255);
assertEq(a[10], 254);
assertEq(Atomics.load(a, 10), 254);
Atomics.and(a, 10, -1); // Preserve all
assertEq(a[10], 254);
assertEq(Atomics.load(a, 10), 254);
Atomics.and(a, 10, 256); // Preserve none
assertEq(a[10], 0);
assertEq(Atomics.load(a, 10), 0);
Atomics.store(a, 10, 255);
assertEq(Atomics.exchange(a, 10, 0), 255);
assertEq(a[11], 0);
}
function testInt16Extremes(a) {
dprint("Int16 extremes");
a[10] = 0;
a[11] = 0;
Atomics.store(a, 10, 65535);
assertEq(a[10], -1);
assertEq(Atomics.load(a, 10), -1);
Atomics.add(a, 10, 65535); // should coerce to -1
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.add(a, 10, -1);
assertEq(a[10], -3);
assertEq(Atomics.load(a, 10), -3);
Atomics.sub(a, 10, 65535); // should coerce to -1
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.sub(a, 10, 65536); // should coerce to 0
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.and(a, 10, -1); // Preserve all
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.and(a, 10, 65536); // Preserve none
assertEq(a[10], 0);
assertEq(Atomics.load(a, 10), 0);
assertEq(a[11], 0);
}
function testUint32(a) {
var k = 0;
for ( var i=0 ; i < 20 ; i++ ) {
a[i] = i+5;
k += a[i];
}
var sum = 0;
for ( var i=0 ; i < 20 ; i++ )
sum += Atomics.add(a, i, 1);
assertEq(sum, k);
}
// This test is a reliable test of sign extension in the JIT where
// testInt8Extremes is not (because there may not be enough type
// information without a loop - see bug 1181062 for a description
// of the general problem).
function exchangeLoop(ta) {
var sum = 0;
for ( var i=0 ; i < 100000 ; i++ )
sum += Atomics.exchange(ta, i & 15, 255);
return sum;
}
function adHocExchange() {
var a = new Int8Array(new SharedArrayBuffer(16));
for ( var i=0 ; i < a.length ; i++ )
a[i] = 255;
assertEq(exchangeLoop(a), -100000);
}
// isLockFree(n) may return true only if there is an integer array
// on which atomic operations is allowed whose byte size is n,
// ie, it must return false for n=8.
//
// SpiderMonkey has isLockFree(1), isLockFree(2), isLockFree(4) on all
// supported platforms, only the last is guaranteed by the spec.
var sizes = [ 1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12];
var answers = [ true, true, false, true, false, false, false, false,
false, false, false, false];
function testIsLockFree() {
// This ought to defeat most compile-time resolution.
for ( var i=0 ; i < sizes.length ; i++ ) {
var v = Atomics.isLockFree(sizes[i]);
var a = answers[i];
assertEq(typeof v, 'boolean');
assertEq(v, a);
}
// This ought to be optimizable.
assertEq(Atomics.isLockFree(1), true);
assertEq(Atomics.isLockFree(2), true);
assertEq(Atomics.isLockFree(3), false);
assertEq(Atomics.isLockFree(4), true);
assertEq(Atomics.isLockFree(5), false);
assertEq(Atomics.isLockFree(6), false);
assertEq(Atomics.isLockFree(7), false);
assertEq(Atomics.isLockFree(8), false);
assertEq(Atomics.isLockFree(9), false);
assertEq(Atomics.isLockFree(10), false);
assertEq(Atomics.isLockFree(11), false);
assertEq(Atomics.isLockFree(12), false);
}
function testIsLockFree2() {
assertEq(Atomics.isLockFree(0), false);
assertEq(Atomics.isLockFree(0/-1), false);
assertEq(Atomics.isLockFree(3.5), false);
assertEq(Atomics.isLockFree(Number.NaN), false); // NaN => +0
assertEq(Atomics.isLockFree(Number.POSITIVE_INFINITY), false);
assertEq(Atomics.isLockFree(Number.NEGATIVE_INFINITY), false);
assertEq(Atomics.isLockFree(-4), false);
assertEq(Atomics.isLockFree('4'), true);
assertEq(Atomics.isLockFree('-4'), false);
assertEq(Atomics.isLockFree('4.5'), true);
assertEq(Atomics.isLockFree('5.5'), false);
assertEq(Atomics.isLockFree(new Number(4)), true);
assertEq(Atomics.isLockFree(new String('4')), true);
assertEq(Atomics.isLockFree(new Boolean(true)), true);
var thrown = false;
try {
Atomics.isLockFree(Symbol('1'));
} catch (e) {
thrown = e;
}
assertEq(thrown instanceof TypeError, true);
assertEq(Atomics.isLockFree(true), true);
assertEq(Atomics.isLockFree(false), false);
assertEq(Atomics.isLockFree(undefined), false);
assertEq(Atomics.isLockFree(null), false);
assertEq(Atomics.isLockFree({toString: () => '4'}), true);
assertEq(Atomics.isLockFree({valueOf: () => 4}), true);
assertEq(Atomics.isLockFree({valueOf: () => 5}), false);
assertEq(Atomics.isLockFree({password: "qumquat"}), false);
}
function testUint8Clamped(sab) {
var ta = new Uint8ClampedArray(sab);
var thrown = false;
try {
CLONE(testMethod)(ta, 0);
}
catch (e) {
thrown = true;
assertEq(e instanceof TypeError, true);
}
assertEq(thrown, true);
}
function testWeirdIndices() {
var a = new Int8Array(new SharedArrayBuffer(16));
a[3] = 10;
assertEq(Atomics.load(a, "0x03"), 10);
assertEq(Atomics.load(a, {valueOf: () => 3}), 10);
}
function isLittleEndian() {
var xxx = new ArrayBuffer(2);
var xxa = new Int16Array(xxx);
var xxb = new Int8Array(xxx);
xxa[0] = 37;
var is_little = xxb[0] == 37;
return is_little;
}
function runTests() {
var is_little = isLittleEndian();
// Currently the SharedArrayBuffer needs to be a multiple of 4K bytes in size.
var sab = new SharedArrayBuffer(4096);
// Test that two arrays created on the same storage alias
var t1 = new Int8Array(sab);
var t2 = new Uint16Array(sab);
assertEq(t1[0], 0);
assertEq(t2[0], 0);
t1[0] = 37;
if (is_little)
assertEq(t2[0], 37);
else
assertEq(t2[0], 37 << 8);
t1[0] = 0;
// Test that invoking as Atomics.whatever() works, on correct arguments.
CLONE(testMethod)(new Int8Array(sab), 0, 42, 4095);
CLONE(testMethod)(new Uint8Array(sab), 0, 42, 4095);
CLONE(testMethod)(new Int16Array(sab), 0, 42, 2047);
CLONE(testMethod)(new Uint16Array(sab), 0, 42, 2047);
CLONE(testMethod)(new Int32Array(sab), 0, 42, 1023);
CLONE(testMethod)(new Uint32Array(sab), 0, 42, 1023);
// Test that invoking as v = Atomics.whatever; v() works, on correct arguments.
gAtomics_compareExchange = Atomics.compareExchange;
gAtomics_exchange = Atomics.exchange;
gAtomics_load = Atomics.load;
gAtomics_store = Atomics.store;
gAtomics_add = Atomics.add;
gAtomics_sub = Atomics.sub;
gAtomics_and = Atomics.and;
gAtomics_or = Atomics.or;
gAtomics_xor = Atomics.xor;
CLONE(testFunction)(new Int8Array(sab), 0, 42, 4095);
CLONE(testFunction)(new Uint8Array(sab), 0, 42, 4095);
CLONE(testFunction)(new Int16Array(sab), 0, 42, 2047);
CLONE(testFunction)(new Uint16Array(sab), 0, 42, 2047);
CLONE(testFunction)(new Int32Array(sab), 0, 42, 1023);
CLONE(testFunction)(new Uint32Array(sab), 0, 42, 1023);
// Test various range and type conditions
var v8 = new Int8Array(sab);
var v32 = new Int32Array(sab);
CLONE(testTypeCAS)(v8);
CLONE(testTypeCAS)(v32);
CLONE(testTypeBinop)(v8, Atomics.add);
CLONE(testTypeBinop)(v8, Atomics.sub);
CLONE(testTypeBinop)(v8, Atomics.and);
CLONE(testTypeBinop)(v8, Atomics.or);
CLONE(testTypeBinop)(v8, Atomics.xor);
CLONE(testTypeBinop)(v32, Atomics.add);
CLONE(testTypeBinop)(v32, Atomics.sub);
CLONE(testTypeBinop)(v32, Atomics.and);
CLONE(testTypeBinop)(v32, Atomics.or);
CLONE(testTypeBinop)(v32, Atomics.xor);
// Test out-of-range references
globlength = v8.length + 5;
CLONE(testRangeCAS)(v8);
globlength = v32.length + 5;
CLONE(testRangeCAS)(v32);
// Test extreme values
testInt8Extremes(new Int8Array(sab));
testUint8Extremes(new Uint8Array(sab));
testInt16Extremes(new Int16Array(sab));
testUint32(new Uint32Array(sab));
// Test that Uint8ClampedArray is not accepted.
testUint8Clamped(sab);
// Misc ad-hoc tests
adHocExchange();
// Misc
testIsLockFree();
testIsLockFree2();
testWeirdIndices();
assertEq(Atomics[Symbol.toStringTag], "Atomics");
}
runTests();
```
vs
```js
load(libdir + "asserts.js");
var DEBUG = false;
function dprint(xs) {
if (!DEBUG) return;
var s = "";
for (x in xs) s += String(xs[x]);
print(s);
}
function CLONE(f) {
return this.eval("(" + f.toSource() + ")");
}
function testMethod(a, indices) {
dprint("Method: " + a.constructor.name);
var poison;
switch (a.BYTES_PER_ELEMENT) {
case 1:
poison = 0x5A;
break;
case 2:
poison = 0x5A5A;
break;
case 4:
poison = 0x5A5A5A5A;
break;
}
for (let i = 0;i < indices.length;i++) {
var x = indices[i];
if (x > 0) a[x - 1] = poison;
if (x < a.length - 1) a[x + 1] = poison;
assertEq(Atomics.compareExchange(a, x, 0, 37), 0);
assertEq(Atomics.compareExchange(a, x, 37, 5), 37);
assertEq(Atomics.compareExchange(a, x, 7, 8), 5);
assertEq(Atomics.compareExchange(a, x, 5, 9), 5);
assertEq(Atomics.compareExchange(a, x, 5, 0), 9);
assertEq(Atomics.exchange(a, x, 4), 9);
assertEq(Atomics.exchange(a, x, 9), 4);
assertEq(Atomics.load(a, x), 9);
assertEq(Atomics.store(a, x, 14), 14);
assertEq(Atomics.load(a, x), 14);
Atomics.store(a, x, 0);
assertEq(Atomics.add(a, x, 3), 0);
assertEq(Atomics.sub(a, x, 2), 3);
assertEq(Atomics.or(a, x, 6), 1);
assertEq(Atomics.and(a, x, 14), 7);
assertEq(Atomics.xor(a, x, 5), 6);
assertEq(Atomics.load(a, x), 3);
Atomics.store(a, x, 0);
if (x > 0) {
assertEq(a[x - 1], poison);
a[x - 1] = 0;
}
if (x < a.length - 1) {
assertEq(a[x + 1], poison);
a[x + 1] = 0;
}
}
}
function testFunction(a, indices) {
dprint("Function: " + a.constructor.name);
var poison;
switch (a.BYTES_PER_ELEMENT) {
case 1:
poison = 0x5A;
break;
case 2:
poison = 0x5A5A;
break;
case 4:
poison = 0x5A5A5A5A;
break;
}
for (let i = 0;i < indices.length;i++) {
var x = indices[i];
if (x > 0) a[x - 1] = poison;
if (x < a.length - 1) a[x + 1] = poison;
assertEq(gAtomics_compareExchange(a, x, 0, 37), 0);
assertEq(gAtomics_compareExchange(a, x, 37, 5), 37);
assertEq(gAtomics_compareExchange(a, x, 7, 8), 5);
assertEq(gAtomics_compareExchange(a, x, 5, 9), 5);
assertEq(gAtomics_compareExchange(a, x, 5, 0), 9);
assertEq(gAtomics_exchange(a, x, 4), 9);
assertEq(gAtomics_exchange(a, x, 9), 4);
assertEq(gAtomics_load(a, x), 9);
assertEq(gAtomics_store(a, x, 14), 14);
assertEq(gAtomics_load(a, x), 14);
gAtomics_store(a, x, 0);
assertEq(gAtomics_add(a, x, 3), 0);
assertEq(gAtomics_sub(a, x, 2), 3);
assertEq(gAtomics_or(a, x, 6), 1);
assertEq(gAtomics_and(a, x, 14), 7);
assertEq(gAtomics_xor(a, x, 5), 6);
assertEq(gAtomics_load(a, x), 3);
gAtomics_store(a, x, 0);
if (x > 0) {
assertEq(a[x - 1], poison);
a[x - 1] = 0;
}
if (x < a.length - 1) {
assertEq(a[x + 1], poison);
a[x + 1] = 0;
}
}
}
function testTypeCAS(a) {
dprint("Type: " + a.constructor.name);
var thrown = false;
try {
Atomics.compareExchange([0,], 0, 0, 1);
} catch (e) {
thrown = true;
assertEq(e instanceof TypeError, true);
}
assertEq(thrown, true);
Atomics.compareExchange(a, 0, 0.7, 1.8);
Atomics.compareExchange(a, 0, "0", 1);
Atomics.compareExchange(a, 0, 0, "1");
Atomics.compareExchange(a, 0, 0);
}
function testTypeBinop(a, op) {
dprint("Type: " + a.constructor.name);
var thrown = false;
try {
op([0,], 0, 1);
} catch (e) {
thrown = true;
assertEq(e instanceof TypeError, true);
}
assertEq(thrown, true);
op(a, 0, 0.7);
op(a, 0, "0");
op(a, 0);
}
var globlength = 0;
function testRangeCAS(a) {
dprint("Range: " + a.constructor.name);
var msg = /out-of-range index/;
assertErrorMessage(() => Atomics.compareExchange(a, -1, 0, 1), RangeError, msg);
assertEq(a[0], 0);
assertEq(Atomics.compareExchange(a, "hi", 0, 33), 0);
assertEq(a[0], 33);
a[0] = 0;
assertErrorMessage(() => Atomics.compareExchange(a, a.length + 5, 0, 1), RangeError, msg);
assertEq(a[0], 0);
assertErrorMessage(() => Atomics.compareExchange(a, globlength, 0, 1), RangeError, msg);
assertEq(a[0], 0);
}
function testInt8Extremes(a) {
dprint("Int8 extremes");
a[10] = 0;
a[11] = 0;
Atomics.store(a, 10, 255);
assertEq(a[10], -1);
assertEq(Atomics.load(a, 10), -1);
Atomics.add(a, 10, 255);
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.add(a, 10, -1);
assertEq(a[10], -3);
assertEq(Atomics.load(a, 10), -3);
Atomics.sub(a, 10, 255);
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.sub(a, 10, 256);
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.and(a, 10, -1);
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.and(a, 10, 256);
assertEq(a[10], 0);
assertEq(Atomics.load(a, 10), 0);
Atomics.store(a, 10, 255);
assertEq(Atomics.exchange(a, 10, 0), -1);
assertEq(a[11], 0);
}
function testUint8Extremes(a) {
dprint("Uint8 extremes");
a[10] = 0;
a[11] = 0;
Atomics.store(a, 10, 255);
assertEq(a[10], 255);
assertEq(Atomics.load(a, 10), 255);
Atomics.add(a, 10, 255);
assertEq(a[10], 254);
assertEq(Atomics.load(a, 10), 254);
Atomics.add(a, 10, -1);
assertEq(a[10], 253);
assertEq(Atomics.load(a, 10), 253);
Atomics.sub(a, 10, 255);
assertEq(a[10], 254);
assertEq(Atomics.load(a, 10), 254);
Atomics.and(a, 10, -1);
assertEq(a[10], 254);
assertEq(Atomics.load(a, 10), 254);
Atomics.and(a, 10, 256);
assertEq(a[10], 0);
assertEq(Atomics.load(a, 10), 0);
Atomics.store(a, 10, 255);
assertEq(Atomics.exchange(a, 10, 0), 255);
assertEq(a[11], 0);
}
function testInt16Extremes(a) {
dprint("Int16 extremes");
a[10] = 0;
a[11] = 0;
Atomics.store(a, 10, 65535);
assertEq(a[10], -1);
assertEq(Atomics.load(a, 10), -1);
Atomics.add(a, 10, 65535);
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.add(a, 10, -1);
assertEq(a[10], -3);
assertEq(Atomics.load(a, 10), -3);
Atomics.sub(a, 10, 65535);
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.sub(a, 10, 65536);
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.and(a, 10, -1);
assertEq(a[10], -2);
assertEq(Atomics.load(a, 10), -2);
Atomics.and(a, 10, 65536);
assertEq(a[10], 0);
assertEq(Atomics.load(a, 10), 0);
assertEq(a[11], 0);
}
function testUint32(a) {
var k = 0;
for (let i = 0;i < 20;i++) {
a[i] = i + 5;
k += a[i];
}
var sum = 0;
for (let i = 0;i < 20;i++) sum += Atomics.add(a, i, 1);
assertEq(sum, k);
}
function exchangeLoop(ta) {
var sum = 0;
for (let i = 0;i < 100000;i++) sum += Atomics.exchange(ta, i & 15, 255);
return sum;
}
function adHocExchange() {
var a = new Int8Array(new SharedArrayBuffer(16));
for (let i = 0;i < a.length;i++) a[i] = 255;
assertEq(exchangeLoop(a), -100000);
}
var sizes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,];
var answers = [true, true, false, true, false, false, false, false, false, false, false, false,];
function testIsLockFree() {
for (let i = 0;i < sizes.length;i++) {
var v = Atomics.isLockFree(sizes[i]);
var a = answers[i];
assertEq(typeof v, 'boolean');
assertEq(v, a);
}
assertEq(Atomics.isLockFree(1), true);
assertEq(Atomics.isLockFree(2), true);
assertEq(Atomics.isLockFree(3), false);
assertEq(Atomics.isLockFree(4), true);
assertEq(Atomics.isLockFree(5), false);
assertEq(Atomics.isLockFree(6), false);
assertEq(Atomics.isLockFree(7), false);
assertEq(Atomics.isLockFree(8), false);
assertEq(Atomics.isLockFree(9), false);
assertEq(Atomics.isLockFree(10), false);
assertEq(Atomics.isLockFree(11), false);
assertEq(Atomics.isLockFree(12), false);
}
function testIsLockFree2() {
assertEq(Atomics.isLockFree(0), false);
assertEq(Atomics.isLockFree(0 / -1), false);
assertEq(Atomics.isLockFree(3.5), false);
assertEq(Atomics.isLockFree(Number.NaN), false);
assertEq(Atomics.isLockFree(Number.POSITIVE_INFINITY), false);
assertEq(Atomics.isLockFree(Number.NEGATIVE_INFINITY), false);
assertEq(Atomics.isLockFree(-4), false);
assertEq(Atomics.isLockFree('4'), true);
assertEq(Atomics.isLockFree('-4'), false);
assertEq(Atomics.isLockFree('4.5'), true);
assertEq(Atomics.isLockFree('5.5'), false);
assertEq(Atomics.isLockFree(new Number(4)), true);
assertEq(Atomics.isLockFree(new String('4')), true);
assertEq(Atomics.isLockFree(new Boolean(true)), true);
var thrown = false;
try {
Atomics.isLockFree(Symbol('1'));
} catch (e) {
thrown = e;
}
assertEq(thrown instanceof TypeError, true);
assertEq(Atomics.isLockFree(true), true);
assertEq(Atomics.isLockFree(false), false);
assertEq(Atomics.isLockFree(undefined), false);
assertEq(Atomics.isLockFree(null), false);
assertEq(Atomics.isLockFree({
toString: () => '4',
}), true);
assertEq(Atomics.isLockFree({
valueOf: () => 4,
}), true);
assertEq(Atomics.isLockFree({
valueOf: () => 5,
}), false);
assertEq(Atomics.isLockFree({
password: "qumquat",
}), false);
}
function testUint8Clamped(sab) {
var ta = new Uint8ClampedArray(sab);
var thrown = false;
try {
CLONE(testMethod)(ta, 0);
} catch (e) {
thrown = true;
assertEq(e instanceof TypeError, true);
}
assertEq(thrown, true);
}
function testWeirdIndices() {
var a = new Int8Array(new SharedArrayBuffer(16));
a[3] = 10;
assertEq(Atomics.load(a, "0x03"), 10);
assertEq(Atomics.load(a, {
valueOf: () => 3,
}), 10);
}
function isLittleEndian() {
var xxx = new ArrayBuffer(2);
var xxa = new Int16Array(xxx);
var xxb = new Int8Array(xxx);
xxa[0] = 37;
var is_little = xxb[0] == 37;
return is_little;
}
function runTests() {
var is_little = isLittleEndian();
var sab = new SharedArrayBuffer(4096);
var t1 = new Int8Array(sab);
var t2 = new Uint16Array(sab);
assertEq(t1[0], 0);
assertEq(t2[0], 0);
t1[0] = 37;
if (is_little) assertEq(t2[0], 37);
else assertEq(t2[0], 37 << 8);
t1[0] = 0;
CLONE(testMethod)(new Int8Array(sab), 0, 42, 4095);
CLONE(testMethod)(new Uint8Array(sab), 0, 42, 4095);
CLONE(testMethod)(new Int16Array(sab), 0, 42, 2047);
CLONE(testMethod)(new Uint16Array(sab), 0, 42, 2047);
CLONE(testMethod)(new Int32Array(sab), 0, 42, 1023);
CLONE(testMethod)(new Uint32Array(sab), 0, 42, 1023);
gAtomics_compareExchange = Atomics.compareExchange;
gAtomics_exchange = Atomics.exchange;
gAtomics_load = Atomics.load;
gAtomics_store = Atomics.store;
gAtomics_add = Atomics.add;
gAtomics_sub = Atomics.sub;
gAtomics_and = Atomics.and;
gAtomics_or = Atomics.or;
gAtomics_xor = Atomics.xor;
CLONE(testFunction)(new Int8Array(sab), 0, 42, 4095);
CLONE(testFunction)(new Uint8Array(sab), 0, 42, 4095);
CLONE(testFunction)(new Int16Array(sab), 0, 42, 2047);
CLONE(testFunction)(new Uint16Array(sab), 0, 42, 2047);
CLONE(testFunction)(new Int32Array(sab), 0, 42, 1023);
CLONE(testFunction)(new Uint32Array(sab), 0, 42, 1023);
var v8 = new Int8Array(sab);
var v32 = new Int32Array(sab);
CLONE(testTypeCAS)(v8);
CLONE(testTypeCAS)(v32);
CLONE(testTypeBinop)(v8, Atomics.add);
CLONE(testTypeBinop)(v8, Atomics.sub);
CLONE(testTypeBinop)(v8, Atomics.and);
CLONE(testTypeBinop)(v8, Atomics.or);
CLONE(testTypeBinop)(v8, Atomics.xor);
CLONE(testTypeBinop)(v32, Atomics.add);
CLONE(testTypeBinop)(v32, Atomics.sub);
CLONE(testTypeBinop)(v32, Atomics.and);
CLONE(testTypeBinop)(v32, Atomics.or);
CLONE(testTypeBinop)(v32, Atomics.xor);
globlength = v8.length + 5;
CLONE(testRangeCAS)(v8);
globlength = v32.length + 5;
CLONE(testRangeCAS)(v32);
testInt8Extremes(new Int8Array(sab));
testUint8Extremes(new Uint8Array(sab));
testInt16Extremes(new Int16Array(sab));
testUint32(new Uint32Array(sab));
testUint8Clamped(sab);
adHocExchange();
testIsLockFree();
testIsLockFree2();
testWeirdIndices();
assertEq(Atomics[Symbol.toStringTag], "Atomics");
}
runTests();
```
<details>
```js
load(libdir + "asserts.js");
var oldOpts = getJitCompilerOptions();
for (var k in oldOpts)
setJitCompilerOption(k, oldOpts[k]);
var newOpts = getJitCompilerOptions();
assertDeepEq(oldOpts, newOpts);
```
vs
```js
load(libdir + "asserts.js");
var oldOpts = getJitCompilerOptions();
for (k in oldOpts) setJitCompilerOption(k, oldOpts[k]);
var newOpts = getJitCompilerOptions();
assertDeepEq(oldOpts, newOpts);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/bug1165905.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/atomics/basic-tests.js)
<details>
```js
// Clearing a Set after deleting some entries works.
var s = new Set(["a", "b", "c", "d"]);
for (var v of s)
if (v !== "c")
s.delete(v);
s.clear();
assertEq(s.size, 0);
assertEq(s.has("c"), false);
assertEq(s.has("d"), false);
```
vs
```js
var s = new Set(["a", "b", "c", "d",]);
for (v of s) if (v !== "c") s.delete(v);
s.clear();
assertEq(s.size, 0);
assertEq(s.has("c"), false);
assertEq(s.has("d"), false);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-clear-4.js)
<details>
```js
// set.iterator() is live: entries added during iteration are visited.
var set = new Set([5]);
var log = '';
for (let x of set) {
log += x + ';';
if (x > 0)
set.add(x - 1);
}
assertEq(log, '5;4;3;2;1;0;');
assertEq(set.size, 6);
```
vs
```js
var set = new Set([5,]);
var log = '';
for (x of set) {
log += x + ';';
if (x > 0) set.add(x - 1);
}
assertEq(log, '5;4;3;2;1;0;');
assertEq(set.size, 6);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-iterator-add-1.js)
<details>
```js
// Arrow functions have a .length property like ordinary functions.
assertEq((a => a).hasOwnProperty("length"), true);
assertEq((a => a).length, 1);
assertEq((() => 0).length, 0);
assertEq(((a) => 0).length, 1);
assertEq(((a, b) => 0).length, 2);
assertEq(((...arr) => arr).length, 0);
assertEq(((a=1, b=2) => 0).length, 0);
```
vs
```js
assertEq(a => a.hasOwnProperty("length"), true);
assertEq(a => a.length, 1);
assertEq(() => 0.length, 0);
assertEq(a => 0.length, 1);
assertEq((a, b) => 0.length, 2);
assertEq(arr => arr.length, 0);
assertEq((a = 1, b = 2) => 0.length, 0);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/length.js)
<details>
```js
// Nested for-of loops can iterate over a Set.
var map = new Set(['a', 'b']);
var log = '';
for (let x of map) {
log += x + ':'
for (let y of map)
log += y;
log += ';'
};
assertEq(log, 'a:ab;b:ab;');
```
vs
```js
var map = new Set(['a', 'b',]);
var log = '';
for (x of map) {
log += x + ':';
for (y of map) log += y;
log += ';';
}
;
assertEq(log, 'a:ab;b:ab;');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-iterator-2.js)
<details>
```js
(function() {
a = (b => eval("0; [arguments]"))();
})();
```
vs
```js
(function() {
a = b => eval("0; [arguments]")();
})();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/bug-885067-1.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/prototype-2.js)
<details>
```js
// for-of on an Array consults the prototype chain when it encounters a hole.
load(libdir + "iteration.js");
var m = {1: 'peek'};
var a = [0, , 2, 3];
a.__proto__ = m;
var log = [];
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
for (var x of a)
log.push(x);
assertEq(log[1], 'peek');
assertEq(log.join(), "0,peek,2,3");
```
vs
```js
load(libdir + "iteration.js");
var m = ({
1: 'peek',
});
var a = [0,, 2, 3,];
a.__proto__ = m;
var log = [];
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
for (x of a) log.push(x);
assertEq(log[1], 'peek');
assertEq(log.join(), "0,peek,2,3");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/array-holes-4.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrow-functions/strict-3.js)
<details>
```js
// for-of visits each hole in an array full of holes.
var n = 0;
for (var x of Array(5)) {
assertEq(x, undefined);
n++;
}
assertEq(n, 5);
```
vs
```js
var n = 0;
for (x of Array(5)) {
assertEq(x, undefined);
n++;
}
assertEq(n, 5);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/array-holes-6.js)
<details>
```js
// Replacing Array.prototype.iterator with something non-callable makes for-of throw.
load(libdir + "asserts.js");
load(libdir + "iteration.js");
function test(v) {
Array.prototype[Symbol.iterator] = v;
assertThrowsInstanceOf(function () { for (var x of []) ; }, TypeError);
}
test(undefined);
test(null);
test({});
```
vs
```js
load(libdir + "asserts.js");
load(libdir + "iteration.js");
function test(v) {
Array.prototype[Symbol.iterator] = v;
assertThrowsInstanceOf(function() {
for (x of []) ;
}, TypeError);
}
test(undefined);
test(null);
test(({}));
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/semantics-02.js)
<details>
```js
// A set iterator can cope with removing the current entry.
function test(letters, toRemove) {
var set = new Set(letters);
toRemove = new Set(toRemove);
var leftovers = [...set].filter(x => !toRemove.has(x)).join("");
var log = "";
for (let x of set) {
log += x;
if (toRemove.has(x))
set.delete(x);
}
assertEq(log, letters);
var remaining = [...set].join("");
assertEq(remaining, leftovers);
}
test('a', 'a'); // removing the only entry
test('abc', 'a'); // removing the first entry
test('abc', 'b'); // removing a middle entry
test('abc', 'c'); // removing the last entry
test('abc', 'abc') // removing all entries
```
vs
```js
function test(letters, toRemove) {
var set = new Set(letters);
toRemove = new Set(toRemove);
var leftovers = [...set,].filter(x => !toRemove.has(x)).join("");
var log = "";
for (x of set) {
log += x;
if (toRemove.has(x)) set.delete(x);
}
assertEq(log, letters);
var remaining = [...set,].join("");
assertEq(remaining, leftovers);
}
test('a', 'a');
test('abc', 'a');
test('abc', 'b');
test('abc', 'c');
test('abc', 'abc');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-iterator-remove-1.js)
<details>
```js
// Control can exit a for-of loop via throw.
function f() {
for (var a of [1, 2, 3]) {
for (var b of [1, 2, 3]) {
for (var c of [1, 2, 3]) {
if (a !== b && b !== c && c !== a)
throw [a, b, c];
}
}
}
}
var x = null;
try {
f();
} catch (exc) {
x = exc.join("");
}
assertEq(x, "123");
```
vs
```js
function f() {
for (a of [1, 2, 3,]) {
for (b of [1, 2, 3,]) {
for (c of [1, 2, 3,]) {
if (a !== b && b !== c && c !== a) throw [a, b, c,];
}
}
}
}
var x = null;
try {
f();
} catch (exc) {
x = exc.join("");
}
assertEq(x, "123");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/throw.js)
<details>
```js
// for-of can iterate arguments objects for other active frames.
load(libdir + "iteration.js");
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var s;
function g(obj) {
for (var v of obj)
s += v;
}
function f() {
g(arguments);
}
s = '';
f(1, 2, 3);
assertEq(s, '123');
```
vs
```js
load(libdir + "iteration.js");
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var s;
function g(obj) {
for (v of obj) s += v;
}
function f() {
g(arguments);
}
s = '';
f(1, 2, 3);
assertEq(s, '123');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arguments-4.js)
<details>
```js
// Basic for-of test with Proxy whose iterator method is a generator.
var arr = ['a', 'b', 'c', 'd'];
var proxy = new Proxy(arr, {
get(target, property, receiver) {
if (property === Symbol.iterator) {
return function* () {
for (var i = 0; i < arr.length; i++)
yield arr[i];
}
}
return Reflect.get(target, property, receiver);
}
});
for (var i = 0; i < 2; i++)
assertEq([...proxy].join(","), "a,b,c,d");
```
vs
```js
var arr = ['a', 'b', 'c', 'd',];
var proxy = new Proxy(arr, ({
get: (function(target, property, receiver) {
if (property === Symbol.iterator) {
return function*() {
for (let i = 0;i < arr.length;i++) yield arr[i];
};
}
return Reflect.get(target, property, receiver);
}),
}));
for (let i = 0;i < 2;i++) assertEq([...proxy,].join(","), "a,b,c,d");
```
<details>
```js
// |jit-test| error: ReferenceError
for (let b in [0]) {
let b = b ? 0 : 1
}
```
vs
```js
for (b in [0,]) {
let b = b ? 0 : 1;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/proxy-2.js)
<details>
```js
var called = false;
var a = [/* hole */, undefined, {
toString() {
if (!called) {
called = true;
a.length = 3;
Object.defineProperty(a, "length", {writable:false});
}
return 0;
}
}, 0];
a.sort();
assertEq(a.length, 3);
assertEq(a[1], 0);
assertEq(a[2], undefined);
```
vs
```js
var called = false;
var a = [, undefined, ({
toString: (function() {
if (!called) {
called = true;
a.length = 3;
Object.defineProperty(a, "length", {
writable: false,
});
}
return 0;
}),
}), 0,];
a.sort();
assertEq(a.length, 3);
assertEq(a[1], 0);
assertEq(a[2], undefined);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-1.js)
<details>
```js
// Tests that NX works through the enabled toggle and adding/removing the
// global.
load(libdir + "asserts.js");
load(libdir + "debuggerNXHelper.js");
var g = newGlobal();
var dbg = new Debugger(g);
g.eval(`
function f() { }
var o = {
get p() { },
set p(x) { }
};
`);
var handlers = [() => { g.f(); },
() => { g.o.p } ,
() => { g.o.p = 42; }];
function testHookEnabled(hookName, trigger) {
for (var h of handlers) {
assertThrowsInstanceOf(h, Debugger.DebuggeeWouldRun);
dbg.enabled = false;
h();
dbg.enabled = true;
assertThrowsInstanceOf(h, Debugger.DebuggeeWouldRun);
}
}
function testHookRemoval(hookName, trigger) {
for (var h of handlers) {
assertThrowsInstanceOf(h, Debugger.DebuggeeWouldRun);
dbg.removeDebuggee(g);
h();
dbg.addDebuggee(g);
assertThrowsInstanceOf(h, Debugger.DebuggeeWouldRun);
}
}
testDebuggerHooksNX(dbg, g, testHookEnabled);
testDebuggerHooksNX(dbg, g, testHookRemoval);
```
vs
```js
load(libdir + "asserts.js");
load(libdir + "debuggerNXHelper.js");
var g = newGlobal();
var dbg = new Debugger(g);
g.eval(`
function f() { }
var o = {
get p() { },
set p(x) { }
};
`);
var handlers = [() => {
g.f();
}, () => {
g.o.p;
}, () => {
g.o.p = 42;
},];
function testHookEnabled(hookName, trigger) {
for (h of handlers) {
assertThrowsInstanceOf(h, Debugger.DebuggeeWouldRun);
dbg.enabled = false;
h();
dbg.enabled = true;
assertThrowsInstanceOf(h, Debugger.DebuggeeWouldRun);
}
}
function testHookRemoval(hookName, trigger) {
for (h of handlers) {
assertThrowsInstanceOf(h, Debugger.DebuggeeWouldRun);
dbg.removeDebuggee(g);
h();
dbg.addDebuggee(g);
assertThrowsInstanceOf(h, Debugger.DebuggeeWouldRun);
}
}
testDebuggerHooksNX(dbg, g, testHookEnabled);
testDebuggerHooksNX(dbg, g, testHookRemoval);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arrays/fillwithundefined-length-nonwriteable.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/noExecute-04.js)
<details>
```js
// When resuming a generator triggers one Debugger's onEnterFrame handler,
// all Debuggers' Debugger.Frames become usable at once.
let g = newGlobal();
g.eval(`
function* f() {
yield 1;
}
`);
let dbg1 = new Debugger(g);
let dbg2 = new Debugger(g);
let hits = 0;
let savedFrame1;
let savedFrame2;
dbg1.onEnterFrame = frame => {
if (savedFrame1 === undefined) {
savedFrame1 = frame;
savedFrame2 = dbg2.getNewestFrame();
} else {
hits++;
assertEq(savedFrame1, frame);
for (let f of [savedFrame2, savedFrame1]) {
assertEq(f.type, "call");
assertEq(f.callee.name, "f");
}
}
};
let values = [...g.f()];
assertEq(hits, 2);
assertEq(values.toSource(), "[1]");
```
vs
```js
let g = newGlobal();
g.eval(`
function* f() {
yield 1;
}
`);
let dbg1 = new Debugger(g);
let dbg2 = new Debugger(g);
let hits = 0;
let savedFrame1;
let savedFrame2;
dbg1.onEnterFrame = frame => {
if (savedFrame1 === undefined) {
savedFrame1 = frame;
savedFrame2 = dbg2.getNewestFrame();
} else {
hits++;
assertEq(savedFrame1, frame);
for (f of [savedFrame2, savedFrame1,]) {
assertEq(f.type, "call");
assertEq(f.callee.name, "f");
}
}
};
let values = [...g.f(),];
assertEq(hits, 2);
assertEq(values.toSource(), "[1]");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/onEnterFrame-generator-05.js)
<details>
```js
// Clearing a Map removes its entries; the Map remains usable afterwards.
var m = new Map([["a", "b"], ["b", "c"]]);
assertEq(m.size, 2);
m.clear();
assertEq(m.size, 0);
assertEq(m.has("a"), false);
assertEq(m.get("a"), undefined);
assertEq(m.delete("a"), false);
assertEq(m.has("b"), false);
for (var pair of m)
throw "FAIL"; // shouldn't be any pairs
m.set("c", "d");
assertEq(m.size, 1);
assertEq(m.has("a"), false);
assertEq(m.has("b"), false);
```
vs
```js
var m = new Map([["a", "b",], ["b", "c",],]);
assertEq(m.size, 2);
m.clear();
assertEq(m.size, 0);
assertEq(m.has("a"), false);
assertEq(m.get("a"), undefined);
assertEq(m.delete("a"), false);
assertEq(m.has("b"), false);
for (pair of m) throw "FAIL";
m.set("c", "d");
assertEq(m.size, 1);
assertEq(m.has("a"), false);
assertEq(m.has("b"), false);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-clear-2.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/testCallApply.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-41.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-47.js)
<details>
```js
var x = 2;
x = -(x == 3);
var y = "";
typeof(z) + typeof(eval("z = y"));
```
vs
```js
var x = 2;
x = -x == 3;
var y = "";
typeof z + typeof eval("z = y");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug639882.js)
<details>
```js
// Eval-in-frame with different type on non-youngest Ion frame.
load(libdir + "jitopts.js");
if (!jitTogglesMatch(Opts_Ion2NoOffthreadCompilation))
quit(0);
withJitOptions(Opts_Ion2NoOffthreadCompilation, function () {
function test(shadow) {
var g = newGlobal();
var dbg = new Debugger;
// Note that we depend on CCW scripted functions being opaque to Ion
// optimization for this test.
g.h = function h(d) {
if (d) {
dbg.addDebuggee(g);
var f = dbg.getNewestFrame().older;
assertEq(f.implementation, "ion");
assertEq(f.environment.getVariable("foo"), 42);
// EIF of a different type too.
f.eval((shadow ? "var " : "") + "foo = 'string of 42'");
g.expected = shadow ? 42 : "string of 42";
}
}
g.eval("" + function f(d) {
var foo = 42;
g(d);
return foo;
});
g.eval("" + function g(d) {
h(d);
});
g.eval("(" + function () {
for (i = 0; i < 5; i++)
f(false);
assertEq(f(true), "string of 42");
} + ")();");
}
test(false);
test(true);
});
```
vs
```js
load(libdir + "jitopts.js");
if (!jitTogglesMatch(Opts_Ion2NoOffthreadCompilation)) quit(0);
withJitOptions(Opts_Ion2NoOffthreadCompilation, (function() {
function test(shadow) {
var g = newGlobal();
var dbg = new Debugger();
g.h = function h(d) {
if (d) {
dbg.addDebuggee(g);
var f = dbg.getNewestFrame().older;
assertEq(f.implementation, "ion");
assertEq(f.environment.getVariable("foo"), 42);
f.eval(shadow ? "var " : "" + "foo = 'string of 42'");
g.expected = shadow ? 42 : "string of 42";
}
};
g.eval("" + function f(d) {
var foo = 42;
g(d);
return foo;
});
g.eval("" + function g(d) {
h(d);
});
g.eval("(" + function() {
for (i = 0;i < 5;i++) f(false);
assertEq(f(true), "string of 42");
} + ")();");
}
test(false);
test(true);
}));
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Frame-eval-20.js)
<details>
```js
// Test importing module namespaces
"use strict";
load(libdir + "asserts.js");
load(libdir + "iteration.js");
load(libdir + "dummyModuleResolveHook.js");
function parseAndEvaluate(source) {
let m = parseModule(source);
m.declarationInstantiation();
return m.evaluation();
}
function testHasNames(names, expected) {
assertEq(names.length, expected.length);
expected.forEach(function(name) {
assertEq(names.includes(name), true);
});
}
function testEqualArrays(actual, expected) {
assertEq(Array.isArray(actual), true);
assertEq(Array.isArray(expected), true);
assertEq(actual.length, expected.length);
for (let i = 0; i < expected.length; i++) {
assertEq(actual[i], expected[i]);
}
}
let a = moduleRepo['a'] = parseModule(
`// Reflection methods should return these exports alphabetically sorted.
export var b = 2;
export var a = 1;`
);
let b = moduleRepo['b'] = parseModule(
`import * as ns from 'a';
export { ns };
export var x = ns.a + ns.b;`
);
b.declarationInstantiation();
b.evaluation();
testHasNames(getModuleEnvironmentNames(b), ["ns", "x"]);
let ns = getModuleEnvironmentValue(b, "ns");
testHasNames(Object.keys(ns), ["a", "b"]);
assertEq(ns.a, 1);
assertEq(ns.b, 2);
assertEq(ns.c, undefined);
assertEq(getModuleEnvironmentValue(b, "x"), 3);
// Test module namespace internal methods as defined in 9.4.6
assertEq(Object.getPrototypeOf(ns), null);
assertEq(Reflect.setPrototypeOf(ns, null), true);
assertEq(Reflect.setPrototypeOf(ns, Object.prototype), false);
assertThrowsInstanceOf(() => Object.setPrototypeOf(ns, {}), TypeError);
assertThrowsInstanceOf(function() { ns.foo = 1; }, TypeError);
assertEq(Object.isExtensible(ns), false);
Object.preventExtensions(ns);
let desc = Object.getOwnPropertyDescriptor(ns, "a");
assertEq(desc.value, 1);
assertEq(desc.writable, true);
assertEq(desc.enumerable, true);
assertEq(desc.configurable, false);
assertEq(typeof desc.get, "undefined");
assertEq(typeof desc.set, "undefined");
assertThrowsInstanceOf(function() { ns.a = 1; }, TypeError);
delete ns.foo;
assertThrowsInstanceOf(function() { delete ns.a; }, TypeError);
// Test @@toStringTag property
desc = Object.getOwnPropertyDescriptor(ns, Symbol.toStringTag);
assertEq(desc.value, "Module");
assertEq(desc.writable, false);
assertEq(desc.enumerable, false);
assertEq(desc.configurable, false);
assertEq(typeof desc.get, "undefined");
assertEq(typeof desc.set, "undefined");
assertEq(Object.prototype.toString.call(ns), "[object Module]");
// Test [[OwnPropertyKeys]] internal method.
testEqualArrays(Reflect.ownKeys(ns), ["a", "b", Symbol.toStringTag]);
testEqualArrays(Object.getOwnPropertyNames(ns), ["a", "b"]);
testEqualArrays(Object.getOwnPropertySymbols(ns), [Symbol.toStringTag]);
// Test cyclic namespace import and access in module evaluation.
let c = moduleRepo['c'] =
parseModule("export let c = 1; import * as ns from 'd'; let d = ns.d;");
let d = moduleRepo['d'] =
parseModule("export let d = 2; import * as ns from 'c'; let c = ns.c;");
c.declarationInstantiation();
d.declarationInstantiation();
assertThrowsInstanceOf(() => c.evaluation(), ReferenceError);
// Test cyclic namespace import.
let e = moduleRepo['e'] =
parseModule("export let e = 1; import * as ns from 'f'; export function f() { return ns.f }");
let f = moduleRepo['f'] =
parseModule("export let f = 2; import * as ns from 'e'; export function e() { return ns.e }");
e.declarationInstantiation();
f.declarationInstantiation();
e.evaluation();
f.evaluation();
assertEq(e.namespace.f(), 2);
assertEq(f.namespace.e(), 1);
```
vs
```js
'use strict';
load(libdir + "asserts.js");
load(libdir + "iteration.js");
load(libdir + "dummyModuleResolveHook.js");
function parseAndEvaluate(source) {
let m = parseModule(source);
m.declarationInstantiation();
return m.evaluation();
}
function testHasNames(names, expected) {
assertEq(names.length, expected.length);
expected.forEach(function(name) {
assertEq(names.includes(name), true);
});
}
function testEqualArrays(actual, expected) {
assertEq(Array.isArray(actual), true);
assertEq(Array.isArray(expected), true);
assertEq(actual.length, expected.length);
for (let i = 0;i < expected.length;i++) {
assertEq(actual[i], expected[i]);
}
}
let a = moduleRepo['a'] = parseModule(`// Reflection methods should return these exports alphabetically sorted.
export var b = 2;
export var a = 1;`);
let b = moduleRepo['b'] = parseModule(`import * as ns from 'a';
export { ns };
export var x = ns.a + ns.b;`);
b.declarationInstantiation();
b.evaluation();
testHasNames(getModuleEnvironmentNames(b), ["ns", "x",]);
let ns = getModuleEnvironmentValue(b, "ns");
testHasNames(Object.keys(ns), ["a", "b",]);
assertEq(ns.a, 1);
assertEq(ns.b, 2);
assertEq(ns.c, undefined);
assertEq(getModuleEnvironmentValue(b, "x"), 3);
assertEq(Object.getPrototypeOf(ns), null);
assertEq(Reflect.setPrototypeOf(ns, null), true);
assertEq(Reflect.setPrototypeOf(ns, Object.prototype), false);
assertThrowsInstanceOf(() => Object.setPrototypeOf(ns, {}), TypeError);
assertThrowsInstanceOf((function() {
ns.foo = 1;
}), TypeError);
assertEq(Object.isExtensible(ns), false);
Object.preventExtensions(ns);
let desc = Object.getOwnPropertyDescriptor(ns, "a");
assertEq(desc.value, 1);
assertEq(desc.writable, true);
assertEq(desc.enumerable, true);
assertEq(desc.configurable, false);
assertEq(typeof desc.get, "undefined");
assertEq(typeof desc.set, "undefined");
assertThrowsInstanceOf((function() {
ns.a = 1;
}), TypeError);
delete ns.foo;
assertThrowsInstanceOf((function() {
delete ns.a;
}), TypeError);
desc = Object.getOwnPropertyDescriptor(ns, Symbol.toStringTag);
assertEq(desc.value, "Module");
assertEq(desc.writable, false);
assertEq(desc.enumerable, false);
assertEq(desc.configurable, false);
assertEq(typeof desc.get, "undefined");
assertEq(typeof desc.set, "undefined");
assertEq(Object.prototype.toString.call(ns), "[object Module]");
testEqualArrays(Reflect.ownKeys(ns), ["a", "b", Symbol.toStringTag,]);
testEqualArrays(Object.getOwnPropertyNames(ns), ["a", "b",]);
testEqualArrays(Object.getOwnPropertySymbols(ns), [Symbol.toStringTag,]);
let c = moduleRepo['c'] = parseModule("export let c = 1; import * as ns from 'd'; let d = ns.d;");
let d = moduleRepo['d'] = parseModule("export let d = 2; import * as ns from 'c'; let c = ns.c;");
c.declarationInstantiation();
d.declarationInstantiation();
assertThrowsInstanceOf(() => c.evaluation(), ReferenceError);
let e = moduleRepo['e'] = parseModule("export let e = 1; import * as ns from 'f'; export function f() { return ns.f }");
let f = moduleRepo['f'] = parseModule("export let f = 2; import * as ns from 'e'; export function e() { return ns.e }");
e.declarationInstantiation();
f.declarationInstantiation();
e.evaluation();
f.evaluation();
assertEq(e.namespace.f(), 2);
assertEq(f.namespace.e(), 1);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/modules/import-namespace.js)
<details>
```js
// Nested for-of loops on the same array get distinct iterators.
var a = [1, 2, 3];
var s = '';
for (var x of a)
for (var y of a)
s += '' + x + y + ',';
assertEq(s, '11,12,13,21,22,23,31,32,33,');
```
vs
```js
var a = [1, 2, 3,];
var s = '';
for (x of a) for (y of a) s += '' + x + y + ',';
assertEq(s, '11,12,13,21,22,23,31,32,33,');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-4.js)
<details>
```js
// Check superficial features of Array.of.
load(libdir + "asserts.js");
var desc = Object.getOwnPropertyDescriptor(Array, "of");
assertEq(desc.configurable, true);
assertEq(desc.enumerable, false);
assertEq(desc.writable, true);
assertEq(Array.of.length, 0);
assertThrowsInstanceOf(() => new Array.of(), TypeError); // not a constructor
// When the this-value passed in is not a constructor, the result is an array.
for (let v of [undefined, null, false, "cow"])
assertEq(Array.isArray(Array.of.call(v)), true);
```
vs
```js
load(libdir + "asserts.js");
var desc = Object.getOwnPropertyDescriptor(Array, "of");
assertEq(desc.configurable, true);
assertEq(desc.enumerable, false);
assertEq(desc.writable, true);
assertEq(Array.of.length, 0);
assertThrowsInstanceOf(() => new Array.of(), TypeError);
for (v of [undefined, null, false, "cow",]) assertEq(Array.isArray(Array.of.call(v)), true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Array-of-surfaces.js)
<details>
```js
// Test cases when a SavedFrame or one of its ancestors have a principal that is
// not subsumed by the caller's principal, when async parents are present.
function checkVisibleStack(stackFrame, expectedFrames) {
// We check toString separately from properties like asyncCause to check that
// it walks the physical SavedFrame chain consistently with the properties.
var stringFrames = stackFrame.toString().split("\n");
while (expectedFrames.length) {
let expectedFrame = expectedFrames.shift();
let stringFrame = stringFrames.shift();
// Check the frame properties.
assertEq(stackFrame.functionDisplayName, expectedFrame.name);
assertEq(stackFrame.asyncCause, expectedFrame.asyncCause);
// Check the stringified version.
let expectedStart =
(expectedFrame.asyncCause ? expectedFrame.asyncCause + "*" : "") +
expectedFrame.name;
assertEq(stringFrame.replace(/@.*$/, ""), expectedStart);
// If the next frame has an asyncCause, it should be an asyncParent.
if (expectedFrames.length && expectedFrames[0].asyncCause) {
assertEq(stackFrame.parent, null);
stackFrame = stackFrame.asyncParent;
} else {
assertEq(stackFrame.asyncParent, null);
stackFrame = stackFrame.parent;
}
}
}
var low = newGlobal({ principal: 0 });
var high = newGlobal({ principal: 0xfffff });
// Test with synchronous cross-compartment calls.
//
// With arrows representing child-to-parent links, and fat arrows representing
// child-to-async-parent links, create a SavedFrame stack like this:
//
// low.e -> high.d => high.c => high.b -> low.a
//
// This stack captured in function `e` would be seen in its complete version if
// accessed by `high`'s compartment, while in `low`'s compartment it would look
// like this:
//
// low.e => low.a
//
// The asyncCause seen on `low.a` above should not leak information about the
// real asyncCause on `high.c` and `high.d`.
//
// The stack captured in function `d` would be seen in its complete version if
// accessed by `high`'s compartment, while in `low`'s compartment it would look
// like this:
//
// low.a
// We'll move these functions into the right globals below before invoking them.
function a() {
b();
}
function b() {
callFunctionWithAsyncStack(c, saveStack(), "BtoC");
}
function c() {
callFunctionWithAsyncStack(d, saveStack(), "CtoD");
}
function d() {
let stackD = saveStack();
print("high.checkVisibleStack(stackD)");
checkVisibleStack(stackD, [
{ name: "d", asyncCause: null },
{ name: "c", asyncCause: "CtoD" },
{ name: "b", asyncCause: "BtoC" },
{ name: "a", asyncCause: null },
]);
let stackE = e(saveStack(0, low));
print("high.checkVisibleStack(stackE)");
checkVisibleStack(stackE, [
{ name: "e", asyncCause: null },
{ name: "d", asyncCause: null },
{ name: "c", asyncCause: "CtoD" },
{ name: "b", asyncCause: "BtoC" },
{ name: "a", asyncCause: null },
]);
}
function e(stackD) {
print("low.checkVisibleStack(stackD)");
checkVisibleStack(stackD, [
{ name: "a", asyncCause: "Async" },
]);
let stackE = saveStack();
print("low.checkVisibleStack(stackE)");
checkVisibleStack(stackE, [
{ name: "e", asyncCause: null },
{ name: "a", asyncCause: "Async" },
]);
return saveStack(0, high);
}
// Test with asynchronous cross-compartment calls and shared frames.
//
// With arrows representing child-to-parent links, and fat arrows representing
// child-to-async-parent links, create a SavedFrame stack like this:
//
// low.x => high.v => low.u
// low.y -> high.v => low.u
// low.z => high.w -> low.u
//
// This stack captured in functions `x`, `y`, and `z` would be seen in its
// complete version if accessed by `high`'s compartment, while in `low`'s
// compartment it would look like this:
//
// low.x => low.u
// low.y => low.u
// low.z => low.u
//
// The stack captured in function `v` would be seen in its complete version if
// accessed by `high`'s compartment, while in `low`'s compartment it would look
// like this:
//
// low.u
// We'll move these functions into the right globals below before invoking them.
function u() {
callFunctionWithAsyncStack(v, saveStack(), "UtoV");
w();
}
function v() {
let stackV = saveStack();
print("high.checkVisibleStack(stackV)");
checkVisibleStack(stackV, [
{ name: "v", asyncCause: null },
{ name: "u", asyncCause: "UtoV" },
]);
let stack = saveStack(0, low);
function xToCall() { return x(stack);};
let stackX = callFunctionWithAsyncStack(xToCall, saveStack(), "VtoX");
print("high.checkVisibleStack(stackX)");
checkVisibleStack(stackX, [
{ name: "x", asyncCause: null },
{ name: "xToCall", asyncCause: null },
{ name: "v", asyncCause: "VtoX" },
{ name: "u", asyncCause: "UtoV" },
]);
let stackY = y();
print("high.checkVisibleStack(stackY)");
checkVisibleStack(stackY, [
{ name: "y", asyncCause: null },
{ name: "v", asyncCause: null },
{ name: "u", asyncCause: "UtoV" },
]);
}
function w() {
let stackZ = callFunctionWithAsyncStack(z, saveStack(), "WtoZ");
print("high.checkVisibleStack(stackZ)");
checkVisibleStack(stackZ, [
{ name: "z", asyncCause: null },
{ name: "w", asyncCause: "WtoZ" },
{ name: "u", asyncCause: null },
]);
}
function x(stackV) {
print("low.checkVisibleStack(stackV)");
checkVisibleStack(stackV, [
{ name: "u", asyncCause: "UtoV" },
]);
let stackX = saveStack();
print("low.checkVisibleStack(stackX)");
checkVisibleStack(stackX, [
{ name: "x", asyncCause: null },
{ name: "u", asyncCause: "UtoV" },
]);
return saveStack(0, high);
}
function y() {
let stackY = saveStack();
print("low.checkVisibleStack(stackY)");
checkVisibleStack(stackY, [
{ name: "y", asyncCause: null },
{ name: "u", asyncCause: "UtoV" },
]);
return saveStack(0, high);
}
function z() {
let stackZ = saveStack();
print("low.checkVisibleStack(stackZ)");
checkVisibleStack(stackZ, [
{ name: "z", asyncCause: null },
{ name: "u", asyncCause: "Async" },
]);
return saveStack(0, high);
}
// Split the functions in their respective globals.
low .eval(a.toSource());
high.eval(b.toSource());
high.eval(c.toSource());
high.eval(d.toSource());
low .eval(e.toSource());
low .b = high.b;
high.e = low .e;
low .eval(u.toSource());
high.eval(v.toSource());
high.eval(w.toSource());
low .eval(x.toSource());
low .eval(y.toSource());
low .eval(z.toSource());
low .v = high.v;
low .w = high.w;
high.x = low .x;
high.y = low .y;
high.z = low .z;
low .high = high;
high.low = low;
low .eval(checkVisibleStack.toSource());
high.eval(checkVisibleStack.toSource());
// Execute the tests.
low.a();
low.u();
```
vs
```js
function checkVisibleStack(stackFrame, expectedFrames) {
var stringFrames = stackFrame.toString().split("\n");
while (expectedFrames.length) {
let expectedFrame = expectedFrames.shift();
let stringFrame = stringFrames.shift();
assertEq(stackFrame.functionDisplayName, expectedFrame.name);
assertEq(stackFrame.asyncCause, expectedFrame.asyncCause);
let expectedStart = expectedFrame.asyncCause ? expectedFrame.asyncCause + "*" : "" + expectedFrame.name;
assertEq(stringFrame.replace(/@.*$/, ""), expectedStart);
if (expectedFrames.length && expectedFrames[0].asyncCause) {
assertEq(stackFrame.parent, null);
stackFrame = stackFrame.asyncParent;
} else {
assertEq(stackFrame.asyncParent, null);
stackFrame = stackFrame.parent;
}
}
}
var low = newGlobal(({
principal: 0,
}));
var high = newGlobal(({
principal: 0xfffff,
}));
function a() {
b();
}
function b() {
callFunctionWithAsyncStack(c, saveStack(), "BtoC");
}
function c() {
callFunctionWithAsyncStack(d, saveStack(), "CtoD");
}
function d() {
let stackD = saveStack();
print("high.checkVisibleStack(stackD)");
checkVisibleStack(stackD, [{
name: "d",
asyncCause: null,
}, {
name: "c",
asyncCause: "CtoD",
}, {
name: "b",
asyncCause: "BtoC",
}, {
name: "a",
asyncCause: null,
},]);
let stackE = e(saveStack(0, low));
print("high.checkVisibleStack(stackE)");
checkVisibleStack(stackE, [{
name: "e",
asyncCause: null,
}, {
name: "d",
asyncCause: null,
}, {
name: "c",
asyncCause: "CtoD",
}, {
name: "b",
asyncCause: "BtoC",
}, {
name: "a",
asyncCause: null,
},]);
}
function e(stackD) {
print("low.checkVisibleStack(stackD)");
checkVisibleStack(stackD, [{
name: "a",
asyncCause: "Async",
},]);
let stackE = saveStack();
print("low.checkVisibleStack(stackE)");
checkVisibleStack(stackE, [{
name: "e",
asyncCause: null,
}, {
name: "a",
asyncCause: "Async",
},]);
return saveStack(0, high);
}
function u() {
callFunctionWithAsyncStack(v, saveStack(), "UtoV");
w();
}
function v() {
let stackV = saveStack();
print("high.checkVisibleStack(stackV)");
checkVisibleStack(stackV, [{
name: "v",
asyncCause: null,
}, {
name: "u",
asyncCause: "UtoV",
},]);
let stack = saveStack(0, low);
function xToCall() {
return x(stack);
}
;
let stackX = callFunctionWithAsyncStack(xToCall, saveStack(), "VtoX");
print("high.checkVisibleStack(stackX)");
checkVisibleStack(stackX, [{
name: "x",
asyncCause: null,
}, {
name: "xToCall",
asyncCause: null,
}, {
name: "v",
asyncCause: "VtoX",
}, {
name: "u",
asyncCause: "UtoV",
},]);
let stackY = y();
print("high.checkVisibleStack(stackY)");
checkVisibleStack(stackY, [{
name: "y",
asyncCause: null,
}, {
name: "v",
asyncCause: null,
}, {
name: "u",
asyncCause: "UtoV",
},]);
}
function w() {
let stackZ = callFunctionWithAsyncStack(z, saveStack(), "WtoZ");
print("high.checkVisibleStack(stackZ)");
checkVisibleStack(stackZ, [{
name: "z",
asyncCause: null,
}, {
name: "w",
asyncCause: "WtoZ",
}, {
name: "u",
asyncCause: null,
},]);
}
function x(stackV) {
print("low.checkVisibleStack(stackV)");
checkVisibleStack(stackV, [{
name: "u",
asyncCause: "UtoV",
},]);
let stackX = saveStack();
print("low.checkVisibleStack(stackX)");
checkVisibleStack(stackX, [{
name: "x",
asyncCause: null,
}, {
name: "u",
asyncCause: "UtoV",
},]);
return saveStack(0, high);
}
function y() {
let stackY = saveStack();
print("low.checkVisibleStack(stackY)");
checkVisibleStack(stackY, [{
name: "y",
asyncCause: null,
}, {
name: "u",
asyncCause: "UtoV",
},]);
return saveStack(0, high);
}
function z() {
let stackZ = saveStack();
print("low.checkVisibleStack(stackZ)");
checkVisibleStack(stackZ, [{
name: "z",
asyncCause: null,
}, {
name: "u",
asyncCause: "Async",
},]);
return saveStack(0, high);
}
low.eval(a.toSource());
high.eval(b.toSource());
high.eval(c.toSource());
high.eval(d.toSource());
low.eval(e.toSource());
low.b = high.b;
high.e = low.e;
low.eval(u.toSource());
high.eval(v.toSource());
high.eval(w.toSource());
low.eval(x.toSource());
low.eval(y.toSource());
low.eval(z.toSource());
low.v = high.v;
low.w = high.w;
high.x = low.x;
high.y = low.y;
high.z = low.z;
low.high = high;
high.low = low;
low.eval(checkVisibleStack.toSource());
high.eval(checkVisibleStack.toSource());
low.a();
low.u();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/saved-stacks/async-principals.js)
<details>
```js
// for-of works on strings and String objects.
load(libdir + "string.js");
function test(s, expectedCodePoints) {
var copy = '';
var codepoints = 0;
var singleHighSurrogate = false;
for (var v of s) {
assertEq(typeof v, 'string');
assertEq(v.length, isSurrogatePair(v) ? 2 : 1);
assertEq(false, singleHighSurrogate && isLowSurrogate(v));
copy += v;
codepoints += 1;
singleHighSurrogate = !isSurrogatePair(v) && isHighSurrogate(v);
}
assertEq(copy, String(s));
assertEq(codepoints, expectedCodePoints);
}
test('', 0);
test('abc', 3);
test('a \0 \ufffe \ufeff', 7);
// Non-BMP characters are generally passed to JS in UTF-16, as surrogate pairs.
// ES6 requires that such pairs be treated as a single code point in for-of.
test('\ud808\udf45', 1);
// Also test invalid surrogate pairs:
// (1) High surrogate not followed by low surrogate
test('\ud808', 1);
test('\ud808\u0000', 2);
// (2) Low surrogate not preceded by high surrogate
test('\udf45', 1);
test('\u0000\udf45', 2);
// (3) Low surrogate followed by high surrogate
test('\udf45\ud808', 2);
test(new String(''), 0);
test(new String('abc'), 3);
test(new String('a \0 \ufffe \ufeff'), 7);
test(new String('\ud808\udf45'), 1);
test(new String('\ud808'), 1);
test(new String('\ud808\u0000'), 2);
test(new String('\udf45'), 1);
test(new String('\u0000\udf45'), 2);
test(new String('\udf45\ud808'), 2);
```
vs
```js
load(libdir + "string.js");
function test(s, expectedCodePoints) {
var copy = '';
var codepoints = 0;
var singleHighSurrogate = false;
for (v of s) {
assertEq(typeof v, 'string');
assertEq(v.length, isSurrogatePair(v) ? 2 : 1);
assertEq(false, singleHighSurrogate && isLowSurrogate(v));
copy += v;
codepoints += 1;
singleHighSurrogate = !isSurrogatePair(v) && isHighSurrogate(v);
}
assertEq(copy, String(s));
assertEq(codepoints, expectedCodePoints);
}
test('', 0);
test('abc', 3);
test('a \0 \ufffe \ufeff', 7);
test('\ud808\udf45', 1);
test('\ud808', 1);
test('\ud808\u0000', 2);
test('\udf45', 1);
test('\u0000\udf45', 2);
test('\udf45\ud808', 2);
test(new String(''), 0);
test(new String('abc'), 3);
test(new String('a \0 \ufffe \ufeff'), 7);
test(new String('\ud808\udf45'), 1);
test(new String('\ud808'), 1);
test(new String('\ud808\u0000'), 2);
test(new String('\udf45'), 1);
test(new String('\u0000\udf45'), 2);
test(new String('\udf45\ud808'), 2);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/strings.js)
<details>
```js
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
/*
* Perform a simple self-test to see if the VM is working
*/
function md5_vm_test()
{
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length
*/
function core_md5(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return Array(a, b, c, d);
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5_cmn(q, a, b, x, s, t)
{
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Calculate the HMAC-MD5, of a key and some data
*/
function core_hmac_md5(key, data)
{
var bkey = str2binl(key);
if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
return core_md5(opad.concat(hash), 512 + 128);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function bit_rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert a string to an array of little-endian words
* If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
*/
function str2binl(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
return bin;
}
/*
* Convert an array of little-endian words to a string
*/
function binl2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
return str;
}
/*
* Convert an array of little-endian words to a hex string.
*/
function binl2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of little-endian words to a base-64 string
*/
function binl2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
var plainText = "Rebellious subjects, enemies to peace,\n\
Profaners of this neighbour-stained steel,--\n\
Will they not hear? What, ho! you men, you beasts,\n\
That quench the fire of your pernicious rage\n\
With purple fountains issuing from your veins,\n\
On pain of torture, from those bloody hands\n\
Throw your mistemper'd weapons to the ground,\n\
And hear the sentence of your moved prince.\n\
Three civil brawls, bred of an airy word,\n\
By thee, old Capulet, and Montague,\n\
Have thrice disturb'd the quiet of our streets,\n\
And made Verona's ancient citizens\n\
Cast by their grave beseeming ornaments,\n\
To wield old partisans, in hands as old,\n\
Canker'd with peace, to part your canker'd hate:\n\
If ever you disturb our streets again,\n\
Your lives shall pay the forfeit of the peace.\n\
For this time, all the rest depart away:\n\
You Capulet; shall go along with me:\n\
And, Montague, come you this afternoon,\n\
To know our further pleasure in this case,\n\
To old Free-town, our common judgment-place.\n\
Once more, on pain of death, all men depart."
for (var i = 0; i <4; i++) {
plainText += plainText;
}
var md5Output = hex_md5(plainText);
assertEq(md5Output, "a831e91e0f70eddcb70dc61c6f82f6cd")
```
vs
```js
var hexcase = 0;
var b64pad = "";
var chrsz = 8;
function hex_md5(s) {
return binl2hex(core_md5(str2binl(s), s.length * chrsz));
}
function b64_md5(s) {
return binl2b64(core_md5(str2binl(s), s.length * chrsz));
}
function str_md5(s) {
return binl2str(core_md5(str2binl(s), s.length * chrsz));
}
function hex_hmac_md5(key, data) {
return binl2hex(core_hmac_md5(key, data));
}
function b64_hmac_md5(key, data) {
return binl2b64(core_hmac_md5(key, data));
}
function str_hmac_md5(key, data) {
return binl2str(core_hmac_md5(key, data));
}
function md5_vm_test() {
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}
function core_md5(x, len) {
x[len >> 5] |= 0x80 << len % 32;
x[len + 64 >>> 9 << 4 + 14] = len;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
for (let i = 0;i < x.length;i += 16) {
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return Array(a, b, c, d);
}
function md5_cmn(q, a, b, x, s, t) {
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
}
function md5_ff(a, b, c, d, x, s, t) {
return md5_cmn(b & c | ~b & d, a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t) {
return md5_cmn(b & d | c & ~d, a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t) {
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t) {
return md5_cmn(c ^ b | ~d, a, b, x, s, t);
}
function core_hmac_md5(key, data) {
var bkey = str2binl(key);
if (bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for (let i = 0;i < 16;i++) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
return core_md5(opad.concat(hash), 512 + 128);
}
function safe_add(x, y) {
var lsw = x & 0xFFFF + y & 0xFFFF;
var msw = x >> 16 + y >> 16 + lsw >> 16;
return msw << 16 | lsw & 0xFFFF;
}
function bit_rol(num, cnt) {
return num << cnt | num >>> 32 - cnt;
}
function str2binl(str) {
var bin = Array();
var mask = 1 << chrsz - 1;
for (let i = 0;i < str.length * chrsz;i += chrsz) bin[i >> 5] |= str.charCodeAt(i / chrsz) & mask << i % 32;
return bin;
}
function binl2str(bin) {
var str = "";
var mask = 1 << chrsz - 1;
for (let i = 0;i < bin.length * 32;i += chrsz) str += String.fromCharCode(bin[i >> 5] >>> i % 32 & mask);
return str;
}
function binl2hex(binarray) {
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for (let i = 0;i < binarray.length * 4;i++) {
str += hex_tab.charAt(binarray[i >> 2] >> i % 4 * 8 + 4 & 0xF) + hex_tab.charAt(binarray[i >> 2] >> i % 4 * 8 & 0xF);
}
return str;
}
function binl2b64(binarray) {
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for (let i = 0;i < binarray.length * 4;i += 3) {
var triplet = binarray[i >> 2] >> 8 * i % 4 & 0xFF << 16 | binarray[i + 1 >> 2] >> 8 * i + 1 % 4 & 0xFF << 8 | binarray[i + 2 >> 2] >> 8 * i + 2 % 4 & 0xFF;
for (let j = 0;j < 4;j++) {
if (i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt(triplet >> 6 * 3 - j & 0x3F);
}
}
return str;
}
var plainText = "Rebellious subjects, enemies to peace,\nProfaners of this neighbour-stained steel,--\nWill they not hear? What, ho! you men, you beasts,\nThat quench the fire of your pernicious rage\nWith purple fountains issuing from your veins,\nOn pain of torture, from those bloody hands\nThrow your mistemper'd weapons to the ground,\nAnd hear the sentence of your moved prince.\nThree civil brawls, bred of an airy word,\nBy thee, old Capulet, and Montague,\nHave thrice disturb'd the quiet of our streets,\nAnd made Verona's ancient citizens\nCast by their grave beseeming ornaments,\nTo wield old partisans, in hands as old,\nCanker'd with peace, to part your canker'd hate:\nIf ever you disturb our streets again,\nYour lives shall pay the forfeit of the peace.\nFor this time, all the rest depart away:\nYou Capulet; shall go along with me:\nAnd, Montague, come you this afternoon,\nTo know our further pleasure in this case,\nTo old Free-town, our common judgment-place.\nOnce more, on pain of death, all men depart.";
for (let i = 0;i < 4;i++) {
plainText += plainText;
}
var md5Output = hex_md5(plainText);
assertEq(md5Output, "a831e91e0f70eddcb70dc61c6f82f6cd");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-crypto-md5.js)
<details>
```js
var e = new Error();
function test() {
var arr = new Float32Array(1);
for (var Number in e) {}
var a = arr [0];
switch (a) {}
} test();
```
vs
```js
var e = new Error();
function test() {
var arr = new Float32Array(1);
for (Number in e) {
}
var a = arr[0];
switch (a) { }
}
test();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/bug916712.js)
<details>
```js
// Test that each yield* loop just checks "done", and "value" is only
// fetched once at the end.
load(libdir + 'iteration.js');
var log = "";
function Iter(val, count) {
function next() {
return {
get done() { log += "d"; return count-- == 0; },
get value() { log += "v"; return val; }
}
}
this[Symbol.iterator] = function() { return this; };
this.next = next;
}
for (var x of new Iter(42, 5))
assertEq(x, 42);
assertEq(log, "dvdvdvdvdvd");
```
vs
```js
load(libdir + 'iteration.js');
var log = "";
function Iter(val, count) {
function next() {
return {
get done() {
log += "d";
return count-- == 0;
},
get value() {
log += "v";
return val;
},
};
}
this[Symbol.iterator] = function() {
return this;
};
this.next = next;
}
for (x of new Iter(42, 5)) assertEq(x, 42);
assertEq(log, "dvdvdvdvdvd");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/value-done-access.js)
<details>
```js
// Test that you can't call the SavedFrame constructor and can only use
// SavedFrame's getters on SavedFrame instances.
load(libdir + "asserts.js");
let proto = Object.getPrototypeOf(saveStack());
// Can't create new SavedFrame instances by hand.
print("Testing constructor");
assertThrowsInstanceOf(() => {
new proto.constructor();
}, TypeError);
for (let p of ["source", "line", "column", "functionDisplayName", "parent"]) {
print("Testing getter: " + p);
// The getters shouldn't work on the prototype.
assertThrowsInstanceOf(() => proto[p], TypeError);
// Nor should they work on random objects.
let o = {};
Object.defineProperty(o, p, Object.getOwnPropertyDescriptor(proto, p));
assertThrowsInstanceOf(() => o[p], TypeError);
}
```
vs
```js
load(libdir + "asserts.js");
let proto = Object.getPrototypeOf(saveStack());
print("Testing constructor");
assertThrowsInstanceOf(() => {
new proto.constructor();
}, TypeError);
for (p of ["source", "line", "column", "functionDisplayName", "parent",]) {
print("Testing getter: " + p);
assertThrowsInstanceOf(() => proto[p], TypeError);
let o = { };
Object.defineProperty(o, p, Object.getOwnPropertyDescriptor(proto, p));
assertThrowsInstanceOf(() => o[p], TypeError);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/saved-stacks/getters-on-invalid-objects.js)
<details>
```js
var x;
-(x === null);
```
vs
```js
var x;
-x === null;
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug617592.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
load(libdir + "asserts.js");
const objects = [
{},
{a: 1, b: 2},
{0: 1, 1: 2},
{0: 1, 1: 2, a: 1},
{0: 1, 1: 2, a: 1, b: 2},
{1000000: 0, 1000001: 1},
{0: 0, 1: 0, 1000000: 0, 1000001: 1},
[],
[0, 1, 2],
[0, 15, 16],
[{a: 0, b: 0}, {b: 0, a: 0}],
[0, , , 1, 2],
[, 1],
[0,,],
[,,],
]
for (const obj of objects) {
assertDeepEq(deserialize(serialize(obj)), obj);
assertDeepEq(deserialize(serialize(wrapWithProto(obj, null))), obj);
}
```
vs
```js
load(libdir + "asserts.js");
const objects = [({}), ({
a: 1,
b: 2,
}), ({
0: 1,
1: 2,
}), ({
0: 1,
1: 2,
a: 1,
}), ({
0: 1,
1: 2,
a: 1,
b: 2,
}), ({
1000000: 0,
1000001: 1,
}), ({
0: 0,
1: 0,
1000000: 0,
1000001: 1,
}), [], [0, 1, 2,], [0, 15, 16,], [({
a: 0,
b: 0,
}), ({
b: 0,
a: 0,
}),], [0,,, 1, 2,], [, 1,], [0,,], [,,],];
for (obj of objects) {
assertDeepEq(deserialize(serialize(obj)), obj);
assertDeepEq(deserialize(serialize(wrapWithProto(obj, null))), obj);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/structured-clone/roundtrip.js)
<details>
```js
// Test drainAllocationsLog() and constructor names.
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root);
root.eval(
`
function Ctor() {}
var nested = {};
nested.Ctor = function () {};
function makeInstance() {
let LexicalCtor = function () {};
return new LexicalCtor;
}
function makeObject() {
let object = {};
return object;
}
this.tests = [
{ name: "Ctor", fn: () => new Ctor },
{ name: "nested.Ctor", fn: () => new nested.Ctor },
{ name: "LexicalCtor", fn: () => makeInstance() },
{ name: null, fn: () => ({}) },
{ name: null, fn: () => (nested.object = {}) },
{ name: null, fn: () => makeObject() },
];
`
);
for (let { name, fn } of root.tests) {
print(name);
dbg.memory.trackingAllocationSites = true;
fn();
let entries = dbg.memory.drainAllocationsLog();
let ctors = entries.map(e => e.constructor);
assertEq(ctors.some(ctor => ctor === name), true);
dbg.memory.trackingAllocationSites = false;
}
```
vs
```js
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root);
root.eval(`
function Ctor() {}
var nested = {};
nested.Ctor = function () {};
function makeInstance() {
let LexicalCtor = function () {};
return new LexicalCtor;
}
function makeObject() {
let object = {};
return object;
}
this.tests = [
{ name: "Ctor", fn: () => new Ctor },
{ name: "nested.Ctor", fn: () => new nested.Ctor },
{ name: "LexicalCtor", fn: () => makeInstance() },
{ name: null, fn: () => ({}) },
{ name: null, fn: () => (nested.object = {}) },
{ name: null, fn: () => makeObject() },
];
`);
for ({name, fn,} of root.tests) {
print(name);
dbg.memory.trackingAllocationSites = true;
fn();
let entries = dbg.memory.drainAllocationsLog();
let ctors = entries.map(e => e.constructor);
assertEq(ctors.some(ctor => ctor === name), true);
dbg.memory.trackingAllocationSites = false;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Memory-drainAllocationsLog-16.js)
<details>
```js
// Test that new.target is acceptably usable in RematerializedFrames.
gczeal(0);
load(libdir + "jitopts.js");
if (!jitTogglesMatch(Opts_Ion2NoOffthreadCompilation))
quit();
withJitOptions(Opts_Ion2NoOffthreadCompilation, function () {
var g = newGlobal();
var dbg = new Debugger;
g.toggle = function toggle(d, expected) {
if (d) {
dbg.addDebuggee(g);
var frame = dbg.getNewestFrame();
assertEq(frame.implementation, "ion");
// the arrow function will not be constructing, even though it has a
// new.target value.
assertEq(frame.constructing, false);
// CONGRATS IF THIS FAILS! You, proud saviour, have made new.target parse
// in debug frame evals (presumably by hooking up static scope walks).
// Uncomment the assert below for efaust's undying gratitude.
// Note that we use .name here because of CCW nonsense.
assertEq(frame.eval('new.target').throw.unsafeDereference().name, "SyntaxError");
// assertEq(frame.eval('new.target').return.unsafeDereference(), expected);
}
};
g.eval("" + function f(d) { new g(d, g, 15); });
g.eval("" + function g(d, expected) { (() => toggle(d, expected))(); });
g.eval("(" + function test() {
for (var i = 0; i < 5; i++)
f(false);
f(true);
} + ")();");
});
```
vs
```js
gczeal(0);
load(libdir + "jitopts.js");
if (!jitTogglesMatch(Opts_Ion2NoOffthreadCompilation)) quit();
withJitOptions(Opts_Ion2NoOffthreadCompilation, (function() {
var g = newGlobal();
var dbg = new Debugger();
g.toggle = function toggle(d, expected) {
if (d) {
dbg.addDebuggee(g);
var frame = dbg.getNewestFrame();
assertEq(frame.implementation, "ion");
assertEq(frame.constructing, false);
assertEq(frame.eval('new.target').throw.unsafeDereference().name, "SyntaxError");
}
};
g.eval("" + function f(d) {
new g(d, g, 15);
});
g.eval("" + function g(d, expected) {
() => toggle(d, expected)();
});
g.eval("(" + function test() {
for (let i = 0;i < 5;i++) f(false);
f(true);
} + ")();");
}));
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Frame-newTargetEval-02.js)
<details>
```js
// |jit-test| skip-if: helperThreadCount() === 0
// Test multiple concurrent off-thread parse jobs.
function assertFails(f) {
let failed = false;
try {
f();
} catch (e) {
failed = true;
}
assertEq(failed, true);
}
function encodeScript(source)
{
let entry = cacheEntry(source);
let global = newGlobal({ cloneSingletons: true });
evaluate(entry, { global: global, saveBytecode: true });
return entry;
}
let a, b, c;
// Calling run functions without arguments assumes a single off-thread job.
// Test run functions fail when no jobs exist.
assertFails(() => runOffThreadScript());
assertFails(() => finishOffThreadModule());
assertFails(() => runOffThreadDecodedScript());
// Test run functions fail when multiple jobs exist and no ID specified.
a = offThreadCompileScript("");
b = offThreadCompileScript("");
assertFails(() => runOffThreadScript());
runOffThreadScript(a);
runOffThreadScript(b);
a = offThreadCompileModule("");
b = offThreadCompileModule("");
assertFails(() => finishOffThreadModule());
finishOffThreadModule(a);
finishOffThreadModule(b);
a = offThreadDecodeScript(encodeScript(""));
b = offThreadDecodeScript(encodeScript(""));
assertFails(() => runOffThreadScript());
runOffThreadDecodedScript(a);
runOffThreadDecodedScript(b);
// Test fun functions succeed when a single job exist and no ID specified.
offThreadCompileScript("42");
assertEq(runOffThreadScript(), 42);
offThreadCompileModule("");
assertEq(typeof finishOffThreadModule(), "object");
offThreadDecodeScript(encodeScript("23"));
assertEq(runOffThreadDecodedScript(), 23);
// Run functions take an ID argument returned from the compile function.
// Test bad ID type and unknown ID.
offThreadCompileScript("");
assertFails(() => runOffThreadScript("foo"));
assertFails(() => runOffThreadScript(42));
runOffThreadScript();
offThreadCompileModule("");
assertFails(() => finishOffThreadModule("foo"));
assertFails(() => finishOffThreadModule(42));
finishOffThreadModule();
offThreadDecodeScript(encodeScript(""));
assertFails(() => runOffThreadDecodedScript("foo"));
assertFails(() => runOffThreadDecodedScript(42));
runOffThreadDecodedScript();
// Test stale ID.
a = offThreadCompileScript("");
runOffThreadScript(a);
assertFails(() => runOffThreadScript(a));
a = offThreadCompileModule("");
finishOffThreadModule(a);
assertFails(() => finishOffThreadModule(a));
a = offThreadDecodeScript(encodeScript(""));
runOffThreadDecodedScript(a);
assertFails(() => runOffThreadDecodedScript(a));
// Test wrong job kind.
a = offThreadCompileScript("");
b = offThreadCompileModule("");
c = offThreadDecodeScript(encodeScript(""));
assertFails(() => runOffThreadScript(b));
assertFails(() => runOffThreadScript(c));
assertFails(() => finishOffThreadModule(a));
assertFails(() => finishOffThreadModule(c));
assertFails(() => runOffThreadDecodedScript(a));
assertFails(() => runOffThreadDecodedScript(b));
runOffThreadScript(a);
finishOffThreadModule(b);
runOffThreadDecodedScript(c);
// Test running multiple jobs.
a = offThreadCompileScript("1");
b = offThreadCompileScript("2");
assertEq(runOffThreadScript(a), 1);
assertEq(runOffThreadScript(b), 2);
a = offThreadCompileModule("");
b = offThreadCompileModule("");
assertEq(typeof finishOffThreadModule(a), "object");
assertEq(typeof finishOffThreadModule(b), "object");
a = offThreadDecodeScript(encodeScript("3"));
b = offThreadDecodeScript(encodeScript("4"));
assertEq(runOffThreadDecodedScript(a), 3);
assertEq(runOffThreadDecodedScript(b), 4);
// Test many jobs.
const count = 100;
let jobs;
jobs = new Array(count);
for (let i = 0; i < jobs.length; i++)
jobs[i] = offThreadCompileScript(`${i} * ${i}`);
for (let i = 0; i < jobs.length; i++)
assertEq(runOffThreadScript(jobs[i]), i * i);
jobs = new Array(count);
for (let i = 0; i < jobs.length; i++)
jobs[i] = offThreadCompileModule("");
for (let i = 0; i < jobs.length; i++)
assertEq(typeof finishOffThreadModule(jobs[i]), "object");
jobs = new Array(count);
for (let i = 0; i < jobs.length; i++)
jobs[i] = offThreadDecodeScript(encodeScript(`${i} * ${i}`));
for (let i = 0; i < jobs.length; i++)
assertEq(runOffThreadDecodedScript(jobs[i]), i * i);
```
vs
```js
function assertFails(f) {
let failed = false;
try {
f();
} catch (e) {
failed = true;
}
assertEq(failed, true);
}
function encodeScript(source) {
let entry = cacheEntry(source);
let global = newGlobal({
cloneSingletons: true,
});
evaluate(entry, {
global: global,
saveBytecode: true,
});
return entry;
}
let a, b, c;
assertFails(() => runOffThreadScript());
assertFails(() => finishOffThreadModule());
assertFails(() => runOffThreadDecodedScript());
a = offThreadCompileScript("");
b = offThreadCompileScript("");
assertFails(() => runOffThreadScript());
runOffThreadScript(a);
runOffThreadScript(b);
a = offThreadCompileModule("");
b = offThreadCompileModule("");
assertFails(() => finishOffThreadModule());
finishOffThreadModule(a);
finishOffThreadModule(b);
a = offThreadDecodeScript(encodeScript(""));
b = offThreadDecodeScript(encodeScript(""));
assertFails(() => runOffThreadScript());
runOffThreadDecodedScript(a);
runOffThreadDecodedScript(b);
offThreadCompileScript("42");
assertEq(runOffThreadScript(), 42);
offThreadCompileModule("");
assertEq(typeof finishOffThreadModule(), "object");
offThreadDecodeScript(encodeScript("23"));
assertEq(runOffThreadDecodedScript(), 23);
offThreadCompileScript("");
assertFails(() => runOffThreadScript("foo"));
assertFails(() => runOffThreadScript(42));
runOffThreadScript();
offThreadCompileModule("");
assertFails(() => finishOffThreadModule("foo"));
assertFails(() => finishOffThreadModule(42));
finishOffThreadModule();
offThreadDecodeScript(encodeScript(""));
assertFails(() => runOffThreadDecodedScript("foo"));
assertFails(() => runOffThreadDecodedScript(42));
runOffThreadDecodedScript();
a = offThreadCompileScript("");
runOffThreadScript(a);
assertFails(() => runOffThreadScript(a));
a = offThreadCompileModule("");
finishOffThreadModule(a);
assertFails(() => finishOffThreadModule(a));
a = offThreadDecodeScript(encodeScript(""));
runOffThreadDecodedScript(a);
assertFails(() => runOffThreadDecodedScript(a));
a = offThreadCompileScript("");
b = offThreadCompileModule("");
c = offThreadDecodeScript(encodeScript(""));
assertFails(() => runOffThreadScript(b));
assertFails(() => runOffThreadScript(c));
assertFails(() => finishOffThreadModule(a));
assertFails(() => finishOffThreadModule(c));
assertFails(() => runOffThreadDecodedScript(a));
assertFails(() => runOffThreadDecodedScript(b));
runOffThreadScript(a);
finishOffThreadModule(b);
runOffThreadDecodedScript(c);
a = offThreadCompileScript("1");
b = offThreadCompileScript("2");
assertEq(runOffThreadScript(a), 1);
assertEq(runOffThreadScript(b), 2);
a = offThreadCompileModule("");
b = offThreadCompileModule("");
assertEq(typeof finishOffThreadModule(a), "object");
assertEq(typeof finishOffThreadModule(b), "object");
a = offThreadDecodeScript(encodeScript("3"));
b = offThreadDecodeScript(encodeScript("4"));
assertEq(runOffThreadDecodedScript(a), 3);
assertEq(runOffThreadDecodedScript(b), 4);
const count = 100;
let jobs;
jobs = new Array(count);
for (let i = 0;i < jobs.length;i++) jobs[i] = offThreadCompileScript(`${i} * {i}`);
for (let i = 0;i < jobs.length;i++) assertEq(runOffThreadScript(jobs[i]), i * i);
jobs = new Array(count);
for (let i = 0;i < jobs.length;i++) jobs[i] = offThreadCompileModule("");
for (let i = 0;i < jobs.length;i++) assertEq(typeof finishOffThreadModule(jobs[i]), "object");
jobs = new Array(count);
for (let i = 0;i < jobs.length;i++) jobs[i] = offThreadDecodeScript(encodeScript(`${i} * {i}`));
for (let i = 0;i < jobs.length;i++) assertEq(runOffThreadDecodedScript(jobs[i]), i * i);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1431353.js)
<details>
```js
/* test Map.prototype.forEach */
load(libdir + 'asserts.js');
load(libdir + 'iteration.js');
// testing success conditions of Map.prototype.forEach
var testMap = new Map();
function callback(value, key, map) {
testMap.set(key, value);
assertEq(map.has(key), true);
assertEq(map.get(key), value);
}
var initialMap = new Map([['a', 1], ['b', 2.3], [false, undefined]]);
initialMap.forEach(callback);
// test that both the Maps are equal and are in same order
var iterator = initialMap[Symbol.iterator]();
var count = 0;
for (var [k, v] of testMap) {
assertEq(initialMap.has(k), true);
assertEq(initialMap.get(k), testMap.get(k));
assertIteratorNext(iterator, [k, testMap.get(k)]);
count++;
}
//check both the Maps we have are equal in size
assertEq(initialMap.size, testMap.size);
assertEq(initialMap.size, count);
var x = { abc: 'test'};
function callback2(value, key, map) {
assertEq(x, this);
}
initialMap = new Map([['a', 1]]);
initialMap.forEach(callback2, x);
// testing failure conditions of Map.prototype.forEach
var s = new Set([1, 2, 3]);
assertThrowsInstanceOf(function() {
Map.prototype.forEach.call(s, callback);
}, TypeError, "Map.prototype.forEach should raise TypeError if not used on a Map");
var fn = 2;
assertThrowsInstanceOf(function() {
initialMap.forEach(fn);
}, TypeError, "Map.prototype.forEach should raise TypeError if callback is not a function");
// testing that Map#forEach uses internal next() function.
var m = new Map([["one", 1]]);
Object.getPrototypeOf(m[Symbol.iterator]()).next = function () { throw "FAIL"; };
assertThrowsValue(function () {
m.forEach(function () { throw Math; });
}, Math, "Map.prototype.forEach should use intrinsic next method.");
```
vs
```js
load(libdir + 'asserts.js');
load(libdir + 'iteration.js');
var testMap = new Map();
function callback(value, key, map) {
testMap.set(key, value);
assertEq(map.has(key), true);
assertEq(map.get(key), value);
}
var initialMap = new Map([['a', 1,], ['b', 2.3,], [false, undefined,],]);
initialMap.forEach(callback);
var iterator = initialMap[Symbol.iterator]();
var count = 0;
for ([k,v,] of testMap) {
assertEq(initialMap.has(k), true);
assertEq(initialMap.get(k), testMap.get(k));
assertIteratorNext(iterator, [k, testMap.get(k),]);
count++;
}
assertEq(initialMap.size, testMap.size);
assertEq(initialMap.size, count);
var x = ({
abc: 'test',
});
function callback2(value, key, map) {
assertEq(x, this);
}
initialMap = new Map([['a', 1,],]);
initialMap.forEach(callback2, x);
var s = new Set([1, 2, 3,]);
assertThrowsInstanceOf((function() {
Map.prototype.forEach.call(s, callback);
}), TypeError, "Map.prototype.forEach should raise TypeError if not used on a Map");
var fn = 2;
assertThrowsInstanceOf((function() {
initialMap.forEach(fn);
}), TypeError, "Map.prototype.forEach should raise TypeError if callback is not a function");
var m = new Map([["one", 1,],]);
Object.getPrototypeOf(m[Symbol.iterator]()).next = (function() {
throw "FAIL";
});
assertThrowsValue((function() {
m.forEach(function() {
throw Math;
});
}), Math, "Map.prototype.forEach should use intrinsic next method.");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-forEach.js)
<details>
```js
// 'let' after "use strict" directive without semicolon is lexed as TOK_NAME
// before parsing the directive. 'let' with TOK_NAME should be handled
// correctly in strict mode.
"use strict"
let a = 1;
```
vs
```js
'use strict';
let a = 1;
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/let-after-directive.js)
<details>
```js
// Breakpoints work in non-compile-and-go code. Bug 738479.
var g = newGlobal();
g.s = '';
var dbg = new Debugger;
var gw = dbg.addDebuggee(g);
g.evaluate(
"function f() {\n" + // fscript.startLine
" s += 'a';\n" + // fscript.startLine + 1
" s += 'b';\n" + // fscript.startLine + 2
"}\n");
var fscript = gw.makeDebuggeeValue(g.f).script;
var handler = {hit: function (frame) { g.s += '1'; }};
for (var pc of fscript.getLineOffsets(fscript.startLine + 2))
fscript.setBreakpoint(pc, handler);
g.f();
assertEq(g.s, "a1b");
```
vs
```js
var g = newGlobal();
g.s = '';
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
g.evaluate("function f() {\n" + " s += 'a';\n" + " s += 'b';\n" + "}\n");
var fscript = gw.makeDebuggeeValue(g.f).script;
var handler = ({
hit: (function(frame) {
g.s += '1';
}),
});
for (pc of fscript.getLineOffsets(fscript.startLine + 2)) fscript.setBreakpoint(pc, handler);
g.f();
assertEq(g.s, "a1b");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/breakpoint-noncng.js)
<details>
```js
// Iterating over non-iterable values throws a TypeError.
load(libdir + "asserts.js");
var misc = [
{}, {x: 1}, Math, isNaN,
Object.create(null),
null, undefined,
true, 0, 3.1416,
new Boolean(true), new Number(0),
{iterator: function () { return undefined; }},
{iterator: function () { return null; }},
{iterator: function () { return true; }},
{iterator: function () { return 17; }},
];
for (var i = 0; i < misc.length; i++) {
let v = misc[i];
var testfn = function () {
for (var _ of v)
throw 'FAIL';
throw 'BAD';
};
assertThrowsInstanceOf(testfn, TypeError);
}
```
vs
```js
load(libdir + "asserts.js");
var misc = [({}), ({
x: 1,
}), Math, isNaN, Object.create(null), null, undefined, true, 0, 3.1416, new Boolean(true), new Number(0), ({
iterator: (function() {
return undefined;
}),
}), ({
iterator: (function() {
return null;
}),
}), ({
iterator: (function() {
return true;
}),
}), ({
iterator: (function() {
return 17;
}),
}),];
for (let i = 0;i < misc.length;i++) {
let v = misc[i];
var testfn = function() {
for (_ of v) throw 'FAIL';
throw 'BAD';
};
assertThrowsInstanceOf(testfn, TypeError);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/non-iterable.js)
<details>
```js
// The Map constructor can take an argument that is an array of pairs.
var arr = [["zero", 0], ["one", 1], ["two", 2]];
var m = new Map(arr);
for (var [k, v] of arr)
assertEq(m.get(k), v);
```
vs
```js
var arr = [["zero", 0,], ["one", 1,], ["two", 2,],];
var m = new Map(arr);
for ([k,v,] of arr) assertEq(m.get(k), v);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-constructor-2.js)
<details>
```js
// Tests that invocation functions work.
load(libdir + "asserts.js");
load(libdir + "debuggerNXHelper.js");
var g = newGlobal();
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
g.eval(`
function d() { debugger; }
function f() { return 42; }
var o = {
get p() { return 42; },
set p(x) { }
};
`);
var strs = ["f();", "o.p", "o.p = 42"];
var fw;
dbg.onDebuggerStatement = (frame) => {
fw = frame.arguments[0];
};
gw.executeInGlobal("d(f)");
dbg.onDebuggerStatement = undefined;
function testHook(hookName) {
var newestFrame = dbg.getNewestFrame();
for (var s of strs) {
if (newestFrame) {
assertEq(newestFrame.eval(s).return, 42);
}
assertEq(gw.executeInGlobal(s).return, 42);
assertEq(fw.apply(null).return, 42);
}
}
testDebuggerHooksNX(dbg, g, testHook);
```
vs
```js
load(libdir + "asserts.js");
load(libdir + "debuggerNXHelper.js");
var g = newGlobal();
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
g.eval(`
function d() { debugger; }
function f() { return 42; }
var o = {
get p() { return 42; },
set p(x) { }
};
`);
var strs = ["f();", "o.p", "o.p = 42",];
var fw;
dbg.onDebuggerStatement = frame => {
fw = frame.arguments[0];
};
gw.executeInGlobal("d(f)");
dbg.onDebuggerStatement = undefined;
function testHook(hookName) {
var newestFrame = dbg.getNewestFrame();
for (s of strs) {
if (newestFrame) {
assertEq(newestFrame.eval(s).return, 42);
}
assertEq(gw.executeInGlobal(s).return, 42);
assertEq(fw.apply(null).return, 42);
}
}
testDebuggerHooksNX(dbg, g, testHook);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/noExecute-02.js)
<details>
```js
// Test basic usage of drainAllocationsLog()
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root)
dbg.memory.trackingAllocationSites = true;
root.eval("(" + function immediate() {
this.tests = [
({}),
[],
/(two|2)\s*problems/,
new function Ctor(){},
new Object(),
new Array(),
new Date(),
];
} + "());");
const allocs = dbg.memory.drainAllocationsLog();
print(allocs.join("\n--------------------------------------------------------------------------\n"));
print("Total number of allocations logged: " + allocs.length);
let idx = -1;
for (let object of root.tests) {
let wrappedObject = wrappedRoot.makeDebuggeeValue(object);
let allocSite = wrappedObject.allocationSite;
let newIdx = allocs.map(x => x.frame).indexOf(allocSite);
assertEq(newIdx > idx, true);
idx = newIdx;
}
```
vs
```js
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root);
dbg.memory.trackingAllocationSites = true;
root.eval("(" + (function immediate() {
this.tests = [{ }, [], /(two|2)\s*problems/, new function Ctor() { }(), new Object(), new Array(), new Date(),];
}) + "());");
const allocs = dbg.memory.drainAllocationsLog();
print(allocs.join("\n--------------------------------------------------------------------------\n"));
print("Total number of allocations logged: " + allocs.length);
let idx = -1;
for (object of root.tests) {
let wrappedObject = wrappedRoot.makeDebuggeeValue(object);
let allocSite = wrappedObject.allocationSite;
let newIdx = allocs.map(x => x.frame).indexOf(allocSite);
assertEq(newIdx > idx, true);
idx = newIdx;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Memory-drainAllocationsLog-01.js)
<details>
```js
// Giving an Array an own .iterator property affects for-of.
load(libdir + "asserts.js");
load(libdir + "iteration.js");
var a = [];
a[Symbol.iterator] = function* () {
yield 'o';
yield 'k';
};
var s = '';
for (var v of a)
s += v;
assertEq(s, 'ok');
a[Symbol.iterator] = undefined;
assertThrowsInstanceOf(function () { for (var v of a) ; }, TypeError);
```
vs
```js
load(libdir + "asserts.js");
load(libdir + "iteration.js");
var a = [];
a[Symbol.iterator] = (function*() {
yield 'o';
yield 'k';
});
var s = '';
for (v of a) s += v;
assertEq(s, 'ok');
a[Symbol.iterator] = undefined;
assertThrowsInstanceOf((function() {
for (v of a) ;
}), TypeError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/semantics-04.js)
<details>
```js
// Clearing a Map after deleting some entries works.
var m = new Map([["a", 1], ["b", 2], ["c", 3], ["d", 4]]);
for (var [k, v] of m)
if (k !== "c")
m.delete(k);
m.clear();
assertEq(m.size, 0);
assertEq(m.has("c"), false);
assertEq(m.has("d"), false);
```
vs
```js
var m = new Map([["a", 1,], ["b", 2,], ["c", 3,], ["d", 4,],]);
for ([k,v,] of m) if (k !== "c") m.delete(k);
m.clear();
assertEq(m.size, 0);
assertEq(m.has("c"), false);
assertEq(m.has("d"), false);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-clear-4.js)
<details>
```js
load(libdir + 'asserts.js');
function test() {
let strcut = ctypes.StructType("a", [ { "x": ctypes.int32_t, } ])();
for (let arg of [1, undefined, null, false, {}, [], Symbol("foo")]) {
assertThrowsInstanceOf(() => { struct.addressOfField(arg); },
Error);
}
}
if (typeof ctypes === "object")
test();
```
vs
```js
load(libdir + 'asserts.js');
function test() {
let strcut = ctypes.StructType("a", [{
"x": ctypes.int32_t,
},])();
for (arg of [1, undefined, null, false, { }, [], Symbol("foo"),]) {
assertThrowsInstanceOf(() => {
struct.addressOfField(arg);
}, Error);
}
}
if (typeof ctypes === "object") test();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ctypes/AddressOfField.js)
<details>
```js
function IsASCIIAlphaString_CharCodeAt(s) {
for (var i = 0; i < s.length; i++) {
var c = s.charCodeAt(i);
if (!((0x41 <= c && c <= 0x5A) || (0x61 <= c && c <= 0x7A)))
return false;
}
return true;
}
function IsASCIIAlphaString_CharAt(s) {
for (var i = 0; i < s.length; i++) {
var c = s.charAt(i);
if (!(("A" <= c && c <= "Z") || ("a" <= c && c <= "z")))
return false;
}
return true;
}
function IsASCIIAlphaString_GetElem(s) {
for (var i = 0; i < s.length; i++) {
var c = s[i];
if (!(("A" <= c && c <= "Z") || ("a" <= c && c <= "z")))
return false;
}
return true;
}
function IsGreekOrCyrillicString_CharCodeAt(s) {
// U+0370 (GREEK CAPITAL LETTER HETA)
// U+03FF (GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL)
// U+0400 (CYRILLIC CAPITAL LETTER IE WITH GRAVE)
// U+052F (CYRILLIC SMALL LETTER EL WITH DESCENDER)
for (var i = 0; i < s.length; i++) {
var c = s.charCodeAt(i);
if (!((0x0370 <= c && c <= 0x03FF) || (0x400 <= c && c <= 0x052F)))
return false;
}
return true;
}
function IsGreekOrCyrillicString_CharAt(s) {
for (var i = 0; i < s.length; i++) {
var c = s.charAt(i);
if (!(("Ͱ" <= c && c <= "Ͽ") || ("Ѐ" <= c && c <= "ԯ")))
return false;
}
return true;
}
function IsGreekOrCyrillicString_GetElem(s) {
for (var i = 0; i < s.length; i++) {
var c = s[i];
if (!(("Ͱ" <= c && c <= "Ͽ") || ("Ѐ" <= c && c <= "ԯ")))
return false;
}
return true;
}
function main() {
function compareLatin1() {
var strings = ["ABCABCABC", "abcabcabc"];
var q = 0;
for (var i = 0; i < 200; ++i) {
var str = strings[i & 1];
for (var j = 0; j < str.length; ++j) {
if (str[j] === "a")
q++;
if ("A" == str[j])
q++;
if (str[j] != "b")
q++;
if ("D" !== str[j])
q++;
}
}
assertEq(q, 100*3 + 100*3 + 100*15 + 100*18);
}
function compareTwoByte() {
var strings = ["āĉœāĉœāĉœ", "abcabcabc"];
var q = 0;
for (var i = 0; i < 200; ++i) {
var str = strings[i & 1];
for (var j = 0; j < str.length; ++j) {
if ("œ" === str[j])
q++;
if (str[j] == "ĉ")
q++;
if ("ā" != str[j])
q++;
if (str[j] !== "Ɖ")
q++;
}
}
assertEq(q, 100*3 + 100*3 + 100*15 + 100*18);
}
function compareRangeLatin1() {
var strings = [
"ABCABCABC", // all upper
"abcabcabc", // all lower
"abcABCabc", // lower and upper
"abcabc123", // characters below limit
"abc[_]ABC", // characters between limit
"ABC{|}abc", // characters above limit
"!#$456_~ÿ", // no matches at all
"aBcZyyZUU", // -
];
for (var i = 0; i < 200; ++i) {
var str = strings[i & 7];
var resultCharCodeAt = IsASCIIAlphaString_CharCodeAt(str);
var resultCharAt = IsASCIIAlphaString_CharAt(str);
var resultGetElem = IsASCIIAlphaString_GetElem(str);
assertEq(resultCharAt, resultCharCodeAt);
assertEq(resultGetElem, resultCharCodeAt);
}
}
function compareRangeTwoByte() {
var strings = [
"αβγΑΒΓαβγ", // all Greek
"АБВабвАБВ", // all Cyrillic
"αβγабвАБΓ", // Greek and Cyrillic
"αβγāēōАБВ", // characters below limit
"αβγԱԲԳАБВ", // characters above limit
"abcāēōԱԲԳ", // no matches at all
"𝐀𝐁𝐂𝐀𝐁𝐂𝐀𝐁𝐂", // (non-BMP)
"abcabcabc", // -
];
for (var i = 0; i < 200; ++i) {
var str = strings[i & 7];
var resultCharCodeAt = IsGreekOrCyrillicString_CharCodeAt(str);
var resultCharAt = IsGreekOrCyrillicString_CharAt(str);
var resultGetElem = IsGreekOrCyrillicString_GetElem(str);
assertEq(resultCharAt, resultCharCodeAt);
assertEq(resultGetElem, resultCharCodeAt);
}
}
compareLatin1();
compareTwoByte();
compareRangeLatin1();
compareRangeTwoByte();
}
for (var i = 0; i < 15; ++i) {
main();
}
```
vs
```js
function IsASCIIAlphaString_CharCodeAt(s) {
for (let i = 0;i < s.length;i++) {
var c = s.charCodeAt(i);
if (!0x41 <= c && c <= 0x5A || 0x61 <= c && c <= 0x7A) return false;
}
return true;
}
function IsASCIIAlphaString_CharAt(s) {
for (let i = 0;i < s.length;i++) {
var c = s.charAt(i);
if (!"A" <= c && c <= "Z" || "a" <= c && c <= "z") return false;
}
return true;
}
function IsASCIIAlphaString_GetElem(s) {
for (let i = 0;i < s.length;i++) {
var c = s[i];
if (!"A" <= c && c <= "Z" || "a" <= c && c <= "z") return false;
}
return true;
}
function IsGreekOrCyrillicString_CharCodeAt(s) {
for (let i = 0;i < s.length;i++) {
var c = s.charCodeAt(i);
if (!0x0370 <= c && c <= 0x03FF || 0x400 <= c && c <= 0x052F) return false;
}
return true;
}
function IsGreekOrCyrillicString_CharAt(s) {
for (let i = 0;i < s.length;i++) {
var c = s.charAt(i);
if (!"Ͱ" <= c && c <= "Ͽ" || "Ѐ" <= c && c <= "ԯ") return false;
}
return true;
}
function IsGreekOrCyrillicString_GetElem(s) {
for (let i = 0;i < s.length;i++) {
var c = s[i];
if (!"Ͱ" <= c && c <= "Ͽ" || "Ѐ" <= c && c <= "ԯ") return false;
}
return true;
}
function main() {
function compareLatin1() {
var strings = ["ABCABCABC", "abcabcabc",];
var q = 0;
for (let i = 0;i < 200;++i) {
var str = strings[i & 1];
for (let j = 0;j < str.length;++j) {
if (str[j] === "a") q++;
if ("A" == str[j]) q++;
if (str[j] != "b") q++;
if ("D" !== str[j]) q++;
}
}
assertEq(q, 100 * 3 + 100 * 3 + 100 * 15 + 100 * 18);
}
function compareTwoByte() {
var strings = ["āĉœāĉœāĉœ", "abcabcabc",];
var q = 0;
for (let i = 0;i < 200;++i) {
var str = strings[i & 1];
for (let j = 0;j < str.length;++j) {
if ("œ" === str[j]) q++;
if (str[j] == "ĉ") q++;
if ("ā" != str[j]) q++;
if (str[j] !== "Ɖ") q++;
}
}
assertEq(q, 100 * 3 + 100 * 3 + 100 * 15 + 100 * 18);
}
function compareRangeLatin1() {
var strings = ["ABCABCABC", "abcabcabc", "abcABCabc", "abcabc123", "abc[_]ABC", "ABC{|}abc", "!#$456_~ÿ", "aBcZyyZUU",];
for (let i = 0;i < 200;++i) {
var str = strings[i & 7];
var resultCharCodeAt = IsASCIIAlphaString_CharCodeAt(str);
var resultCharAt = IsASCIIAlphaString_CharAt(str);
var resultGetElem = IsASCIIAlphaString_GetElem(str);
assertEq(resultCharAt, resultCharCodeAt);
assertEq(resultGetElem, resultCharCodeAt);
}
}
function compareRangeTwoByte() {
var strings = ["αβγΑΒΓαβγ", "АБВабвАБВ", "αβγабвАБΓ", "αβγāēōАБВ", "αβγԱԲԳАБВ", "abcāēōԱԲԳ", "𝐀𝐁𝐂𝐀𝐁𝐂𝐀𝐁𝐂", "abcabcabc",];
for (let i = 0;i < 200;++i) {
var str = strings[i & 7];
var resultCharCodeAt = IsGreekOrCyrillicString_CharCodeAt(str);
var resultCharAt = IsGreekOrCyrillicString_CharAt(str);
var resultGetElem = IsGreekOrCyrillicString_GetElem(str);
assertEq(resultCharAt, resultCharCodeAt);
assertEq(resultGetElem, resultCharCodeAt);
}
}
compareLatin1();
compareTwoByte();
compareRangeLatin1();
compareRangeTwoByte();
}
for (let i = 0;i < 15;++i) {
main();
}
```
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug647991-2.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/compare-char.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var map = new Map();
map.set("self", map);
var magic = deserialize(serialize(map));
assertEq(magic.get("self"), magic);
assertEq(magic.size, 1);
map = new Map();
map.set(map, "self");
magic = deserialize(serialize(map));
assertEq(magic.get(magic), "self");
assertEq(magic.size, 1);
var values = [
"a", "\uDEFF", undefined, null, -3.5, true, false, NaN, 155, -2
]
map = new Map();
for (var value of values) {
map.set(value, value);
}
magic = deserialize(serialize(map));
var i = 0;
for (value of magic) {
assertEq(value[0], value[1]);
assertEq(value[0], values[i++]);
}
assertEq([...map.keys()].toSource(), [...magic.keys()].toSource());
assertEq([...map.values()].toSource(), [...magic.values()].toSource());
var obj = {a: 1};
obj.map = new Map();
obj.map.set("obj", obj);
magic = deserialize(serialize(obj));
assertEq(magic.map.get("obj"), magic);
assertEq(magic.a, 1);
map = new Map();
map.set("a", new Number(1));
map.set("b", new String("aaaa"));
map.set("c", new Date(NaN));
magic = deserialize(serialize(map));
assertEq(magic.get("a").valueOf(), 1);
assertEq(magic.get("b").valueOf(), "aaaa");
assertEq(magic.get("c").valueOf(), NaN);
assertEq([...magic.keys()].toSource(), ["a", "b", "c"].toSource());
map = new Map();
map.set("x", new Map());
map.get("x").set("x", map);
map.get("x").set("b", null);
magic = deserialize(serialize(map));
assertEq(magic.get("x").get("x"), magic);
assertEq(magic.get("x").get("b"), null);
map = new Map()
map.set({a: 1}, "b");
magic = deserialize(serialize(map));
obj = [...magic.keys()][0];
assertEq(obj.a, 1);
assertEq(magic.get(obj), "b");
// Make sure expandos aren't cloned (Bug 1041172)
map = new Map();
map.a = "aaaaa";
magic = deserialize(serialize(map));
assertEq("a" in magic, false);
assertEq(Object.keys(magic).length, 0);
// Busted [[Prototype]] shouldn't matter
map = new Map();
Object.setPrototypeOf(map, null);
Map.prototype.set.call(map, "self", map);
magic = deserialize(serialize(map));
assertEq(magic.get("self"), magic);
assertEq(magic.size, 1);
// Can't fuzz around with Map after it is cloned
obj = {
a: new Map(),
get b() {
obj.a.delete("test");
return "invoked";
}
}
obj.a.set("test", "hello");
assertEq(obj.a.has("test"), true);
magic = deserialize(serialize(obj));
assertEq(obj.a.has("test"), false);
assertEq(magic.a.size, 1);
assertEq(magic.a.get("test"), "hello");
assertEq([...magic.a.keys()].toString(), "test");
assertEq(magic.b, "invoked");
```
vs
```js
var map = new Map();
map.set("self", map);
var magic = deserialize(serialize(map));
assertEq(magic.get("self"), magic);
assertEq(magic.size, 1);
map = new Map();
map.set(map, "self");
magic = deserialize(serialize(map));
assertEq(magic.get(magic), "self");
assertEq(magic.size, 1);
var values = ["a", "\uDEFF", undefined, null, -3.5, true, false, NaN, 155, -2,];
map = new Map();
for (value of values) {
map.set(value, value);
}
magic = deserialize(serialize(map));
var i = 0;
for (value of magic) {
assertEq(value[0], value[1]);
assertEq(value[0], values[i++]);
}
assertEq([...map.keys(),].toSource(), [...magic.keys(),].toSource());
assertEq([...map.values(),].toSource(), [...magic.values(),].toSource());
var obj = ({
a: 1,
});
obj.map = new Map();
obj.map.set("obj", obj);
magic = deserialize(serialize(obj));
assertEq(magic.map.get("obj"), magic);
assertEq(magic.a, 1);
map = new Map();
map.set("a", new Number(1));
map.set("b", new String("aaaa"));
map.set("c", new Date(NaN));
magic = deserialize(serialize(map));
assertEq(magic.get("a").valueOf(), 1);
assertEq(magic.get("b").valueOf(), "aaaa");
assertEq(magic.get("c").valueOf(), NaN);
assertEq([...magic.keys(),].toSource(), ["a", "b", "c",].toSource());
map = new Map();
map.set("x", new Map());
map.get("x").set("x", map);
map.get("x").set("b", null);
magic = deserialize(serialize(map));
assertEq(magic.get("x").get("x"), magic);
assertEq(magic.get("x").get("b"), null);
map = new Map();
map.set(({
a: 1,
}), "b");
magic = deserialize(serialize(map));
obj = [...magic.keys(),][0];
assertEq(obj.a, 1);
assertEq(magic.get(obj), "b");
map = new Map();
map.a = "aaaaa";
magic = deserialize(serialize(map));
assertEq("a" in magic, false);
assertEq(Object.keys(magic).length, 0);
map = new Map();
Object.setPrototypeOf(map, null);
Map.prototype.set.call(map, "self", map);
magic = deserialize(serialize(map));
assertEq(magic.get("self"), magic);
assertEq(magic.size, 1);
obj = ({
a: new Map(),
get b() {
obj.a.delete("test");
return "invoked";
},
});
obj.a.set("test", "hello");
assertEq(obj.a.has("test"), true);
magic = deserialize(serialize(obj));
assertEq(obj.a.has("test"), false);
assertEq(magic.a.size, 1);
assertEq(magic.a.get("test"), "hello");
assertEq([...magic.a.keys(),].toString(), "test");
assertEq(magic.b, "invoked");
```
<details>
```js
// |jit-test| error: uncaught exception
g = newGlobal();
g.parent = this;
g.eval(`
Debugger(parent).onExceptionUnwind = function(frame) { frame.older };
`);
var handler = {
has: function(tgt, key) { if (key == 'throw') { throw null; } }
};
var proxy = new Proxy({}, handler);
for (let k of ['foo', 'throw']) {
k in proxy;
}
```
vs
```js
g = newGlobal();
g.parent = this;
g.eval(`
Debugger(parent).onExceptionUnwind = function(frame) { frame.older };
`);
var handler = ({
has: (function(tgt, key) {
if (key == 'throw') {
throw null;
}
}),
});
var proxy = new Proxy(({}), handler);
for (k of ['foo', 'throw',]) {
k in proxy;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/bug1432764.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/structured-clone/Map.js)
<details>
```js
// Debugger.Frame.prototype.live is false for frames that have thrown or been thrown through
load(libdir + "asserts.js");
var g = newGlobal();
g.debuggeeGlobal = this;
g.eval("var finalCheck;");
g.eval("(" + function () {
var a = [];
var dbg = Debugger(debuggeeGlobal);
dbg.onDebuggerStatement = function (frame) {
a.push(frame);
for (var i = 0; i < a.length; i++)
assertEq(a[i].live, true);
};
finalCheck = function (n) {
assertEq(a.length, n);
for (var i = 0; i < n; i++)
assertEq(a[i].live, false);
};
} + ")()");
function f(n) {
debugger;
if (--n > 0)
f(n);
else
throw "fit";
}
assertThrowsValue(function () { f(10); }, "fit");
g.finalCheck(10);
```
vs
```js
load(libdir + "asserts.js");
var g = newGlobal();
g.debuggeeGlobal = this;
g.eval("var finalCheck;");
g.eval("(" + (function() {
var a = [];
var dbg = Debugger(debuggeeGlobal);
dbg.onDebuggerStatement = function(frame) {
a.push(frame);
for (let i = 0;i < a.length;i++) assertEq(a[i].live, true);
};
finalCheck = function(n) {
assertEq(a.length, n);
for (let i = 0;i < n;i++) assertEq(a[i].live, false);
};
}) + ")()");
function f(n) {
debugger;;
if (--n > 0) f(n);
else throw "fit";
}
assertThrowsValue((function() {
f(10);
}), "fit");
g.finalCheck(10);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Frame-live-02.js)
<details>
```js
// |jit-test| error: TypeError
new DoWhileObject;
function DoWhileObject(breakOut, breakIn, iterations, loops) {
loops.prototype = new DoWhile;
this.looping;
}
function DoWhile(object) {
do {} while (object);
}
```
vs
```js
new DoWhileObject();
function DoWhileObject(breakOut, breakIn, iterations, loops) {
loops.prototype = new DoWhile();
this.looping;
}
function DoWhile(object) {
do {
} while (object);
;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug657288.js)
<details>
```js
// only fix doubles for slots which the recompiled script thinks are doubles.
function foo(x) {
var y = x & 0xffff;
y = (y * (x * 1000));
assertEq(y, 140735340806145000);
}
foo(0x7fffffff);
```
vs
```js
function foo(x) {
var y = x & 0xffff;
y = y * x * 1000;
assertEq(y, 140735340806145000);
}
foo(0x7fffffff);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/patchdouble.js)
<details>
```js
function f(x) {
return (!(Math.round(Math.hypot(Number.MIN_VALUE, Math.fround(x))) | 0) | 0) !== (Math.atanh(x) ? false : Math.tan(0))
}
f(Number.MIN_VALUE)
assertEq(f(4294967295), true)
```
vs
```js
function f(x) {
return !Math.round(Math.hypot(Number.MIN_VALUE, Math.fround(x))) | 0 | 0 !== Math.atanh(x) ? false : Math.tan(0);
}
f(Number.MIN_VALUE);
assertEq(f(4294967295), true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/recover-bug1236114.js)
<details>
```js
// Deleting the .next method of an iterator in the middle of a for-of loop
// doesn't cause a TypeError at the next iteration.
load(libdir + "asserts.js");
load(libdir + "iteration.js");
var iterProto = Object.getPrototypeOf([][Symbol.iterator]());
var s = '';
for (var v of ['duck', 'duck', 'duck', 'goose', 'and now you\'re it']) {
s += v;
if (v === 'goose')
delete iterProto.next;
s += '.';
}
assertEq(s, 'duck.duck.duck.goose.and now you\'re it.');
```
vs
```js
load(libdir + "asserts.js");
load(libdir + "iteration.js");
var iterProto = Object.getPrototypeOf([][Symbol.iterator]());
var s = '';
for (v of ['duck', 'duck', 'duck', 'goose', 'and now you\'re it',]) {
s += v;
if (v === 'goose') delete iterProto.next;
s += '.';
}
assertEq(s, 'duck.duck.duck.goose.and now you\'re it.');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/semantics-07.js)
<details>
```js
function testHolePushing() {
var a = ["foobar", "baz"];
for (var i = 0; i < 5; i++)
a = [, "overwritten", "new"];
var s = "[";
for (i = 0; i < a.length; i++) {
s += (i in a) ? a[i] : "<hole>";
if (i != a.length - 1)
s += ",";
}
return s + "], " + (0 in a);
}
assertEq(testHolePushing(), "[<hole>,overwritten,new], false");
```
vs
```js
function testHolePushing() {
var a = ["foobar", "baz",];
for (let i = 0;i < 5;i++) a = [, "overwritten", "new",];
var s = "[";
for (i = 0;i < a.length;i++) {
s += i in a ? a[i] : "<hole>";
if (i != a.length - 1) s += ",";
}
return s + "], " + 0 in a;
}
assertEq(testHolePushing(), "[<hole>,overwritten,new], false");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/testHolePushing.js)
<details>
```js
// Tests that invocation functions work outside of Debugger code.
load(libdir + "asserts.js");
var g = newGlobal();
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
g.eval(`
function f() { debugger; return 42; }
function f2() { return 42; }
var o = {
get p() { return 42; },
set p(x) { }
};
`);
var strs = ["f(f2);", "o.p", "o.p = 42"];
var f2w;
dbg.onDebuggerStatement = (frame) => {
f2w = frame.arguments[0];
};
for (var s of strs) {
assertEq(gw.executeInGlobal(s).return, 42);
}
assertEq(f2w.apply(null).return, 42);
```
vs
```js
load(libdir + "asserts.js");
var g = newGlobal();
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
g.eval(`
function f() { debugger; return 42; }
function f2() { return 42; }
var o = {
get p() { return 42; },
set p(x) { }
};
`);
var strs = ["f(f2);", "o.p", "o.p = 42",];
var f2w;
dbg.onDebuggerStatement = frame => {
f2w = frame.arguments[0];
};
for (s of strs) {
assertEq(gw.executeInGlobal(s).return, 42);
}
assertEq(f2w.apply(null).return, 42);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/noExecute-03.js)
<details>
```js
// The Set constructor throws TypeError when passed a non-iterable argument.
load(libdir + "asserts.js");
var misc = [
{}, {x: 1}, Math, isNaN,
Object.create(null),
true, 0, 3.1416,
new Boolean(true), new Number(0),
{iterator: function () { return undefined; }},
{iterator: function () { return null; }},
{iterator: function () { return true; }},
{iterator: function () { return 17; }},
];
for (var v of misc) {
assertThrowsInstanceOf(function () { new Set(v); }, TypeError);
assertThrowsInstanceOf(function () { new Map(v); }, TypeError);
}
```
vs
```js
load(libdir + "asserts.js");
var misc = [({}), ({
x: 1,
}), Math, isNaN, Object.create(null), true, 0, 3.1416, new Boolean(true), new Number(0), ({
iterator: (function() {
return undefined;
}),
}), ({
iterator: (function() {
return null;
}),
}), ({
iterator: (function() {
return true;
}),
}), ({
iterator: (function() {
return 17;
}),
}),];
for (v of misc) {
assertThrowsInstanceOf(function() {
new Set(v);
}, TypeError);
assertThrowsInstanceOf(function() {
new Map(v);
}, TypeError);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/constructor-errors.js)
<details>
```js
// Removing and re-adding entries while an iterator is live causes the iterator to visit them again.
var map = new Map([['a', 1]]);
var n = 5;
for (let [k, v] of map) {
assertEq(k, 'a');
assertEq(v, 1);
if (n === 0)
break;
map.delete('a');
map.set('a', 1);
n--;
}
assertEq(n, 0);
```
vs
```js
var map = new Map([['a', 1,],]);
var n = 5;
for ([k,v,] of map) {
assertEq(k, 'a');
assertEq(v, 1);
if (n === 0) break;
map.delete('a');
map.set('a', 1);
n--;
}
assertEq(n, 0);
```
<details>
```js
// for-of consults Object.prototype when it encounters a hole.
Object.prototype[1] = 'peek';
var log = [];
for (var x of [0, , 2, 3])
log.push(x);
assertEq(log[1], 'peek');
assertEq(log.join(), "0,peek,2,3");
```
vs
```js
Object.prototype[1] = 'peek';
var log = [];
for (x of [0,, 2, 3,]) log.push(x);
assertEq(log[1], 'peek');
assertEq(log.join(), "0,peek,2,3");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-iterator-add-remove.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/array-holes-2.js)
<details>
```js
// Async stacks should not supplant LiveSavedFrameCache hits.
top();
// An ordinary function, to give the frame a convenient name.
function top() {
// Perform an async call. F will run in an activation that has an async stack
// supplied.
f().catch(catchError);
}
async function f() {
// Perform an ordinary call. Its parent frame will be a LiveSavedFrameCache
// hit.
g();
}
function g() {
// Populate the LiveSavedFrameCache.
saveStack();
// Capturing the stack again should find f (if not g) in the cache. The async
// stack supplied below the call to f should not supplant f's own frame.
let frame = saveStack();
assertEq(frame.functionDisplayName, 'g');
assertEq(parent(frame).functionDisplayName, 'f');
assertEq(parent(parent(frame)).functionDisplayName, 'top');
}
// Return the parent of |frame|, skipping self-hosted code and following async
// parent links.
function parent(frame) {
do {
frame = frame.parent || frame.asyncParent;
} while (frame.source.match(/self-hosted/));
return frame;
}
function catchError(e) {
print(`${e}\n${e.stack}`);
quit(1)
}
```
vs
```js
top();
function top() {
f().catch(catchError);
}
(async function f() {
g();
});
function g() {
saveStack();
let frame = saveStack();
assertEq(frame.functionDisplayName, 'g');
assertEq(parent(frame).functionDisplayName, 'f');
assertEq(parent(parent(frame)).functionDisplayName, 'top');
}
function parent(frame) {
do {
frame = frame.parent || frame.asyncParent;
} while (frame.source.match(/self-hosted/));
;
return frame;
}
function catchError(e) {
print(`${e}\n{e.stack}`);
quit(1);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/saved-stacks/async-livecache.js)
<details>
```js
// |jit-test| skip-if: getBuildConfiguration().debug === true
function f(){};
Object.defineProperty(f, "name", {value: "a".repeat((1<<30)-2)});
var ex = null;
try {
len = f.bind().name.length;
} catch (e) {
ex = e;
}
assertEq(ex === "out of memory" || (ex instanceof InternalError), true);
```
vs
```js
function f() { }
;
Object.defineProperty(f, "name", ({
value: "a".repeat(1 << 30 - 2),
}));
var ex = null;
try {
len = f.bind().name.length;
} catch (e) {
ex = e;
}
assertEq(ex === "out of memory" || ex instanceof InternalError, true);
```
<details>
```js
// Map can take an argument that is an array of singleton arrays.
var arr = [["a"], ["b"], ["c"]];
var m = new Map(arr);
assertEq(m.size, 3);
for (var [k, _] of arr) {
assertEq(m.has(k), true);
assertEq(m.get(k), undefined);
}
```
vs
```js
var arr = [["a",], ["b",], ["c",],];
var m = new Map(arr);
assertEq(m.size, 3);
for ([k,_,] of arr) {
assertEq(m.has(k), true);
assertEq(m.get(k), undefined);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/bug1355573.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-constructor-3.js)
<details>
```js
// Manually advancing the iterator.
load(libdir + 'iteration.js');
function* g(n) { for (var i=0; i<n; i++) yield i; }
var inner = g(20);
var n = 0;
for (var x of inner) {
assertEq(x, n * 2);
assertIteratorNext(inner, n * 2 + 1);
n++;
}
assertEq(n, 10);
```
vs
```js
load(libdir + 'iteration.js');
function *g(n) {
for (let i = 0;i < n;i++) yield i;
}
var inner = g(20);
var n = 0;
for (x of inner) {
assertEq(x, n * 2);
assertIteratorNext(inner, n * 2 + 1);
n++;
}
assertEq(n, 10);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/manual-advance.js)
<details>
```js
// GC-ing during a for-of loop doesn't crash.
var i = 0;
for (var x of new Set(Object.getOwnPropertyNames(this))) {
gc();
if (++i >= 20)
break;
}
```
vs
```js
var i = 0;
for (x of new Set(Object.getOwnPropertyNames(this))) {
gc();
if (++i >= 20) break;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-iterator-gc-2.js)
<details>
```js
// A map iterator can cope with removing the next entry.
load(libdir + "iteration.js");
var map = new Map([['a', 0], ['b', 1], ['c', 2], ['d', 3]]);
var iter = map[Symbol.iterator]();
var log = '';
for (let [k, v] of iter) {
log += k + v;
if (k === 'b')
map.delete('c');
}
assertEq(log, 'a0b1d3');
```
vs
```js
load(libdir + "iteration.js");
var map = new Map([['a', 0,], ['b', 1,], ['c', 2,], ['d', 3,],]);
var iter = map[Symbol.iterator]();
var log = '';
for ([k,v,] of iter) {
log += k + v;
if (k === 'b') map.delete('c');
}
assertEq(log, 'a0b1d3');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-iterator-remove-2.js)
<details>
```js
// for-of does not trigger the JS 1.7 for-in destructuring special case.
var data = [[1, 2, 3], [4, 5, 6, 7]];
function test(vars, expr, result) {
var s = '';
eval("for (" + vars + " of data) s += (" + expr + ") + ';';");
assertEq(s, result);
}
for (var prefix of ["var ", "let ", ""]) {
test(prefix + "[a, b, c]",
"a + ',' + b + ',' + c",
"1,2,3;4,5,6;");
}
test("var [a]", "a", "1;4;");
test("var {length: len}", "len", "3;4;");
test("var {length}", "length", "3;4;");
test("{}", "0", "0;0;");
```
vs
```js
var data = [[1, 2, 3,], [4, 5, 6, 7,],];
function test(vars, expr, result) {
var s = '';
eval("for (" + vars + " of data) s += (" + expr + ") + ';';");
assertEq(s, result);
}
for (prefix of ["var ", "let ", "",]) {
test(prefix + "[a, b, c]", "a + ',' + b + ',' + c", "1,2,3;4,5,6;");
}
test("var [a]", "a", "1;4;");
test("var {length: len}", "len", "3;4;");
test("var {length}", "length", "3;4;");
test("{}", "0", "0;0;");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/bug-728079-js17-1.js)
<details>
```js
// Bug 972961 - Test compiler with very long chains of property accesses
// Return true if we can compile a chain of n property accesses,
// false if we cannot. Throw if compilation fails in an unexpected way.
function test(n) {
print("testing " + n);
try {
eval('if (false) {' + Array(n).join(("a.")) + 'a}');
} catch (exc) {
// Expected outcome if the expression is too deeply nested is an InternalError.
if (!(exc instanceof InternalError))
throw exc;
print(exc.message);
return false;
}
print("no exception");
return true;
}
// Find out how long a chain is enough to break the compiler.
var n = 4, LIMIT = 0x000fffff;
var lo = 1, hi = 1;
while (n <= LIMIT && test(n)) {
lo = n;
n *= 4;
}
// Using binary search, find a pass/fail boundary (in order to
// test the edge case).
if (n <= LIMIT) {
hi = n;
while (lo !== hi) {
var mid = Math.floor((lo + hi) / 2);
if (test(mid))
lo = mid + 1;
else
hi = mid;
}
print((lo - 1) + " attributes should be enough for anyone");
}
```
vs
```js
function test(n) {
print("testing " + n);
try {
eval('if (false) {' + Array(n).join("a.") + 'a}');
} catch (exc) {
if (!exc instanceof InternalError) throw exc;
print(exc.message);
return false;
}
print("no exception");
return true;
}
var n = 4, LIMIT = 0x000fffff;
var lo = 1, hi = 1;
while (n <= LIMIT && test(n)) {
lo = n;
n *= 4;
}
if (n <= LIMIT) {
hi = n;
while (lo !== hi) {
var mid = Math.floor(lo + hi / 2);
if (test(mid)) lo = mid + 1;
else hi = mid;
}
print(lo - 1 + " attributes should be enough for anyone");
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/bug972961.js)
<details>
```js
// Constant folding doesn't affect strict delete either.
// In particular, it doesn't affect whether |delete x| is a strict error.
load(libdir + "asserts.js");
(function (x) {
"use strict";
// These senseless delete-expressions are legal even in strict mode.
// Per ES5.1 11.4.1 step 2, each one does nothing and returns true.
assertEq(delete (1 ? x : x), true);
assertEq(delete (0 || x), true);
assertEq(delete (1 && x), true);
// Plain `delete x` is a SyntaxError though.
assertThrowsInstanceOf(() => eval('delete x'), SyntaxError);
assertThrowsInstanceOf(() => Function('"use strict"; delete x'), SyntaxError);
}());
```
vs
```js
load(libdir + "asserts.js");
(function(x) {
'use strict';
assertEq(delete 1 ? x : x, true);
assertEq(delete 0 || x, true);
assertEq(delete 1 && x, true);
assertThrowsInstanceOf(() => eval('delete x'), SyntaxError);
assertThrowsInstanceOf(() => Function('"use strict"; delete x'), SyntaxError);
})();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-888002-3.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var set = new Set();
set.add(set);
var magic = deserialize(serialize(set));
assertEq(magic.size, 1);
assertEq(magic.values().next().value, magic);
var values = [
"a", "\uDEFF", undefined, null, -3.5, true, false, NaN, 155, -2
]
set = new Set();
for (var value of values) {
set.add(value)
}
magic = deserialize(serialize(set));
var i = 0;
for (value of magic) {
assertEq(value, values[i++]);
}
assertEq([...set.keys()].toSource(), [...magic.keys()].toSource());
assertEq([...set.values()].toSource(), [...magic.values()].toSource());
var obj = {a: 1};
obj.set = new Set();
obj.set.add(obj);
magic = deserialize(serialize(obj));
assertEq(magic.set.values().next().value, magic);
assertEq(magic.a, 1);
set = new Set();
set.add(new Number(1));
set.add(new String("aaaa"));
set.add(new Date(NaN));
magic = deserialize(serialize(set));
values = magic.values();
assertEq(values.next().value.valueOf(), 1);
assertEq(values.next().value.valueOf(), "aaaa");
assertEq(values.next().value.valueOf(), NaN);
assertEq(values.next().done, true);
// Make sure expandos aren't cloned (Bug 1041172)
set = new Set();
set.a = "aaaaa";
magic = deserialize(serialize(set));
assertEq("a" in magic, false);
assertEq(Object.keys(magic).length, 0);
// Busted [[Prototype]] shouldn't matter
set = new Set();
Object.setPrototypeOf(set, null);
Set.prototype.add.call(set, "aaa");
magic = deserialize(serialize(set));
assertEq(magic.has("aaa"), true);
assertEq(magic.size, 1);
// Can't fuzz around with Set after it is cloned
obj = {
a: new Set(),
get b() {
obj.a.delete("test");
return "invoked";
}
}
obj.a.add("test");
assertEq(obj.a.has("test"), true);
magic = deserialize(serialize(obj));
assertEq(obj.a.has("test"), false);
assertEq(magic.a.size, 1);
assertEq([...magic.a.keys()].toString(), "test");
assertEq(magic.b, "invoked");
```
vs
```js
var set = new Set();
set.add(set);
var magic = deserialize(serialize(set));
assertEq(magic.size, 1);
assertEq(magic.values().next().value, magic);
var values = ["a", "\uDEFF", undefined, null, -3.5, true, false, NaN, 155, -2,];
set = new Set();
for (value of values) {
set.add(value);
}
magic = deserialize(serialize(set));
var i = 0;
for (value of magic) {
assertEq(value, values[i++]);
}
assertEq([...set.keys(),].toSource(), [...magic.keys(),].toSource());
assertEq([...set.values(),].toSource(), [...magic.values(),].toSource());
var obj = ({
a: 1,
});
obj.set = new Set();
obj.set.add(obj);
magic = deserialize(serialize(obj));
assertEq(magic.set.values().next().value, magic);
assertEq(magic.a, 1);
set = new Set();
set.add(new Number(1));
set.add(new String("aaaa"));
set.add(new Date(NaN));
magic = deserialize(serialize(set));
values = magic.values();
assertEq(values.next().value.valueOf(), 1);
assertEq(values.next().value.valueOf(), "aaaa");
assertEq(values.next().value.valueOf(), NaN);
assertEq(values.next().done, true);
set = new Set();
set.a = "aaaaa";
magic = deserialize(serialize(set));
assertEq("a" in magic, false);
assertEq(Object.keys(magic).length, 0);
set = new Set();
Object.setPrototypeOf(set, null);
Set.prototype.add.call(set, "aaa");
magic = deserialize(serialize(set));
assertEq(magic.has("aaa"), true);
assertEq(magic.size, 1);
obj = ({
a: new Set(),
get b() {
obj.a.delete("test");
return "invoked";
},
});
obj.a.add("test");
assertEq(obj.a.has("test"), true);
magic = deserialize(serialize(obj));
assertEq(obj.a.has("test"), false);
assertEq(magic.a.size, 1);
assertEq([...magic.a.keys(),].toString(), "test");
assertEq(magic.b, "invoked");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/structured-clone/Set.js)
<details>
```js
// for-of can iterate strict arguments objects in non-strict code.
load(libdir + "iteration.js");
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var s;
function g(obj) {
for (var v of obj)
s += v;
}
function f() {
"use strict";
g(arguments);
}
s = '';
f(1, 2, 3);
assertEq(s, '123');
```
vs
```js
load(libdir + "iteration.js");
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var s;
function g(obj) {
for (v of obj) s += v;
}
function f() {
'use strict';
g(arguments);
}
s = '';
f(1, 2, 3);
assertEq(s, '123');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arguments-5.js)
<details>
```js
// A debugger can {throw:} from onEnterFrame at any resume point in a generator.
// It closes the generator.
load(libdir + "asserts.js");
let g = newGlobal();
g.eval(`
function* f() { yield 1; }
var exn = new TypeError("object too hairy");
`);
let dbg = new Debugger;
let gw = dbg.addDebuggee(g);
// Repeat the test for each onEnterFrame event.
// It fires up to three times:
// - when the generator g.f is called;
// - when we enter it to run to `yield 1`;
// - when we resume after the yield to run to the end.
for (let i = 0; i < 3; i++) {
let hits = 0;
dbg.onEnterFrame = frame => {
return hits++ < i ? undefined : {throw: gw.makeDebuggeeValue(g.exn)};
};
let genObj;
assertThrowsValue(
() => {
genObj = g.f();
for (let x of genObj) {}
},
g.exn
);
assertEq(hits, i + 1);
if (hits > 1)
assertEq(genObj.next().done, true);
}
```
vs
```js
load(libdir + "asserts.js");
let g = newGlobal();
g.eval(`
function* f() { yield 1; }
var exn = new TypeError("object too hairy");
`);
let dbg = new Debugger();
let gw = dbg.addDebuggee(g);
for (let i = 0;i < 3;i++) {
let hits = 0;
dbg.onEnterFrame = frame => {
return hits++ < i ? undefined : {
throw: gw.makeDebuggeeValue(g.exn),
};
};
let genObj;
assertThrowsValue(() => {
genObj = g.f();
for (x of genObj) {
}
}, g.exn);
assertEq(hits, i + 1);
if (hits > 1) assertEq(genObj.next().done, true);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/onEnterFrame-generator-resumption-01.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-45.js)
<details>
```js
// for-of works on cross-compartment wrappers of Arrays.
var g = newGlobal();
var s = '';
for (var x of g.Array(1, 1, 2, 3, 5))
s += x;
assertEq(s, '11235');
```
vs
```js
var g = newGlobal();
var s = '';
for (x of g.Array(1, 1, 2, 3, 5)) s += x;
assertEq(s, '11235');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/wrapper-1.js)
<details>
```js
// Test AutoSetAsyncStackForNewCalls's IMPLICIT kind.
// Given a SavedFrame stack, return a string listing the frame's function names
// and their async causes, if any.
function stackFunctions(stack) {
const frames = [];
for (; stack; stack = stack.parent || stack.asyncParent) {
if (!stack.functionDisplayName) {
frames.push('(top level)');
} else if (stack.asyncCause) {
frames.push(`${stack.asyncCause}*${stack.functionDisplayName}`);
} else {
frames.push(stack.functionDisplayName);
}
}
return frames.join(', ');
}
let fakeStack = (function fake1() {
function fake2() {
return saveStack();
}
return fake2();
})();
function bindAndExpect(options, expected) {
function bindee() {
assertEq(stackFunctions(saveStack()), expected);
}
return bindToAsyncStack(bindee, options);
}
function caller(f) {
return f();
}
// An explicit async stack always overrides the actual callers of the bindee.
// An implicit async stack never overrides callers; it is only attached when
// the stack is otherwise empty.
caller(bindAndExpect({ stack: fakeStack, cause: 'ano', explicit: false },
"bindee, caller, (top level)"));
caller(bindAndExpect({ stack: fakeStack, cause: 'hi', explicit: true },
"bindee, hi*fake2, fake1, (top level)"));
enqueueJob(bindAndExpect({ stack: fakeStack, cause: 'mita', explicit: false },
"bindee, mita*fake2, fake1, (top level)"));
enqueueJob(bindAndExpect({ stack: fakeStack, cause: 'hana', explicit: true },
"bindee, hana*fake2, fake1, (top level)"));
```
vs
```js
function stackFunctions(stack) {
const frames = [];
for (;stack;stack = stack.parent || stack.asyncParent) {
if (!stack.functionDisplayName) {
frames.push('(top level)');
} else if (stack.asyncCause) {
frames.push(`${stack.asyncCause}*{stack.functionDisplayName}`);
} else {
frames.push(stack.functionDisplayName);
}
}
return frames.join(', ');
}
let fakeStack = (function fake1() {
function fake2() {
return saveStack();
}
return fake2();
})();
function bindAndExpect(options, expected) {
function bindee() {
assertEq(stackFunctions(saveStack()), expected);
}
return bindToAsyncStack(bindee, options);
}
function caller(f) {
return f();
}
caller(bindAndExpect(({
stack: fakeStack,
cause: 'ano',
explicit: false,
}), "bindee, caller, (top level)"));
caller(bindAndExpect(({
stack: fakeStack,
cause: 'hi',
explicit: true,
}), "bindee, hi*fake2, fake1, (top level)"));
enqueueJob(bindAndExpect(({
stack: fakeStack,
cause: 'mita',
explicit: false,
}), "bindee, mita*fake2, fake1, (top level)"));
enqueueJob(bindAndExpect(({
stack: fakeStack,
cause: 'hana',
explicit: true,
}), "bindee, hana*fake2, fake1, (top level)"));
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/saved-stacks/async-implicit.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-32.js)
<details>
```js
var arr = [1, 2, 3];
var y = 0;
for (var i = 0; i < 10; i++)
for (var x of arr)
y += x;
assertEq(y, 60);
```
vs
```js
var arr = [1, 2, 3,];
var y = 0;
for (let i = 0;i < 10;i++) for (x of arr) y += x;
assertEq(y, 60);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/array-jit.js)
<details>
```js
// Constant folding doesn't affect non-strict delete.
(function (x) {
// These senseless delete-expressions are legal. Per ES5.1 11.4.1 step 2,
// each one does nothing and returns true.
assertEq(delete (1 ? x : x), true);
assertEq(delete (0 || x), true);
assertEq(delete (1 && x), true);
// This one is legal too, but returns false.
assertEq(delete x, false);
}());
```
vs
```js
(function(x) {
assertEq(delete 1 ? x : x, true);
assertEq(delete 0 || x, true);
assertEq(delete 1 && x, true);
assertEq(delete x, false);
})();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-888002-2.js)
<details>
```js
// for-of can iterate arguments objects.
load(libdir + "iteration.js");
// Arguments objects do not have a .@@iterator() method by default.
// Install one on Object.prototype.
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var s;
function test() {
for (var v of arguments)
s += v;
}
s = '';
test();
assertEq(s, '');
s = '';
test('x', 'y');
assertEq(s, 'xy');
```
vs
```js
load(libdir + "iteration.js");
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var s;
function test() {
for (v of arguments) s += v;
}
s = '';
test();
assertEq(s, '');
s = '';
test('x', 'y');
assertEq(s, 'xy');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arguments-1.js)
<details>
```js
// for-of throws if the target is a typed array prototype object.
load(libdir + "asserts.js");
assertThrowsInstanceOf(function () {
for (var v of Int8Array.prototype)
throw "FAIL";
}, TypeError);
```
vs
```js
load(libdir + "asserts.js");
assertThrowsInstanceOf((function() {
for (v of Int8Array.prototype) throw "FAIL";
}), TypeError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/typedarrays-4.js)
<details>
```js
// Nested for-of loops on the same slow array get distinct iterators.
var a = [1, 2, 3];
a.slow = true;
var s = '';
for (var x of a)
for (var y of a)
s += '' + x + y + ',';
assertEq(s, '11,12,13,21,22,23,31,32,33,');
```
vs
```js
var a = [1, 2, 3,];
a.slow = true;
var s = '';
for (x of a) for (y of a) s += '' + x + y + ',';
assertEq(s, '11,12,13,21,22,23,31,32,33,');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-slow-3.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
load(libdir + 'array-compare.js');
var obj = {};
function strictAssignArgumentsElement(a)
{
"use strict";
arguments[0] = 42;
return a;
}
for (var i = 0; i < 5; i++)
{
assertEq(strictAssignArgumentsElement(), undefined);
assertEq(strictAssignArgumentsElement(obj), obj);
assertEq(strictAssignArgumentsElement(17), 17);
}
```
vs
```js
load(libdir + 'array-compare.js');
var obj = ({});
function strictAssignArgumentsElement(a) {
'use strict';
arguments[0] = 42;
return a;
}
for (let i = 0;i < 5;i++) {
assertEq(strictAssignArgumentsElement(), undefined);
assertEq(strictAssignArgumentsElement(obj), obj);
assertEq(strictAssignArgumentsElement(17), 17);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/strict-assign-arguments-element.js)
<details>
```js
// Deleting String.prototype.iterator makes for-of stop working on strings.
load(libdir + "asserts.js");
load(libdir + "iteration.js");
delete String.prototype[Symbol.iterator];
assertThrowsInstanceOf(function () { for (var v of "abc") ; }, TypeError);
assertThrowsInstanceOf(function () { for (var v of new String("abc")) ; }, TypeError);
```
vs
```js
load(libdir + "asserts.js");
load(libdir + "iteration.js");
delete String.prototype[Symbol.iterator];
assertThrowsInstanceOf((function() {
for (v of "abc") ;
}), TypeError);
assertThrowsInstanceOf((function() {
for (v of new String("abc")) ;
}), TypeError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/semantics-05.js)
<details>
```js
// Iterating over a set of objects yields those exact objects.
var arr = [{}, {}, {}, [], /xyz/, new Date];
var set = new Set(arr);
assertEq(set.size, arr.length);
var i = 0;
for (var x of set)
assertEq(x, arr[i++]);
assertEq(i, arr.length);
```
vs
```js
var arr = [({}), ({}), ({}), [], /xyz/, new Date(),];
var set = new Set(arr);
assertEq(set.size, arr.length);
var i = 0;
for (x of set) assertEq(x, arr[i++]);
assertEq(i, arr.length);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-iterator-3.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-19.js)
<details>
```js
var m = new Map;
var s = new Set;
var A = [];
for (var i = 0; i < 1024; ++i) {
var key = {i:i};
m.set(key, i);
s.add(key);
A.push(key);
}
gc();
for (var i in A) {
var key = A[i];
assertEq(m.has(key), true);
assertEq(s.has(key), true);
}
```
vs
```js
var m = new Map();
var s = new Set();
var A = [];
for (let i = 0;i < 1024;++i) {
var key = {
i: i,
};
m.set(key, i);
s.add(key);
A.push(key);
}
gc();
for (i in A) {
var key = A[i];
assertEq(m.has(key), true);
assertEq(s.has(key), true);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-Set-moving-gc.js)
<details>
```js
// map.keys(), .values(), and .entries() on an empty map produce empty iterators.
var m = new Map();
var ki = m.keys(), vi = m.values(), ei = m.entries();
var p = Object.getPrototypeOf(ki)
assertEq(Object.getPrototypeOf(vi), p);
assertEq(Object.getPrototypeOf(ei), p);
for (let k of ki)
throw "FAIL";
for (let v of vi)
throw "FAIL";
for (let [k, v] of ei)
throw "FAIL";
```
vs
```js
var m = new Map();
var ki = m.keys(), vi = m.values(), ei = m.entries();
var p = Object.getPrototypeOf(ki);
assertEq(Object.getPrototypeOf(vi), p);
assertEq(Object.getPrototypeOf(ei), p);
for (k of ki) throw "FAIL";
for (v of vi) throw "FAIL";
for ([k,v,] of ei) throw "FAIL";
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-values-1.js)
<details>
```js
// for-of on a proxy causes a predictable sequence of trap calls.
load(libdir + "iteration.js");
var s = '';
var i = 0;
var next_fn = new Proxy(function() {}, {
apply() {
s += "n";
if (i == 3)
return { value: undefined, done: true };
return { value: i++, done: false };
}
});
var it = new Proxy({}, {
get(target, property, receiver) {
assertEq(property, "next");
s += "N";
return next_fn;
}
});
var iterator_fn = new Proxy(function() {}, {
apply() {
s += 'i';
return it;
}
});
var obj = new Proxy({}, {
get: function (receiver, name) {
assertEq(name, Symbol.iterator);
s += "I";
return iterator_fn;
}
});
for (var v of obj)
s += v;
assertEq(s, 'IiNn0n1n2n');
```
vs
```js
load(libdir + "iteration.js");
var s = '';
var i = 0;
var next_fn = new Proxy((function() { }), ({
apply: (function() {
s += "n";
if (i == 3) return {
value: undefined,
done: true,
};
return {
value: i++,
done: false,
};
}),
}));
var it = new Proxy(({}), ({
get: (function(target, property, receiver) {
assertEq(property, "next");
s += "N";
return next_fn;
}),
}));
var iterator_fn = new Proxy((function() { }), ({
apply: (function() {
s += 'i';
return it;
}),
}));
var obj = new Proxy(({}), ({
get: (function(receiver, name) {
assertEq(name, Symbol.iterator);
s += "I";
return iterator_fn;
}),
}));
for (v of obj) s += v;
assertEq(s, 'IiNn0n1n2n');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/semantics-11.js)
<details>
```js
// for-of consults Array.prototype when it encounters a hole.
Array.prototype[1] = 'peek';
var log = [];
for (var x of [0, , 2, 3])
log.push(x);
assertEq(log[1], 'peek');
assertEq(log.join(), "0,peek,2,3");
```
vs
```js
Array.prototype[1] = 'peek';
var log = [];
for (x of [0,, 2, 3,]) log.push(x);
assertEq(log[1], 'peek');
assertEq(log.join(), "0,peek,2,3");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/array-holes-3.js)
<details>
```js
// Don't assert with --ion-eager.
function RandBool() { var x = Math.random() >= 0.5; return x; }
var CHARS = "aaa";
function RandStr() {
var c = Math.floor(Math.random() * CHARS.length);
}
function RandVal() {
return RandBool() ? RandStr() : RandStr();
}
function GenerateSpecPermutes(matchVals, resultArray) {
var maxPermuteBody = (1 << matchVals.length) - 1;
for(var bod_pm = 0; bod_pm <= maxPermuteBody; bod_pm++)
for(var k = 0; k < matchVals.length; k++)
var body = ((bod_pm & (1 << k)) > 0) ? null : RandVal();
}
GenerateSpecPermutes(["foo", "bar", "zing"]);
```
vs
```js
function RandBool() {
var x = Math.random() >= 0.5;
return x;
}
var CHARS = "aaa";
function RandStr() {
var c = Math.floor(Math.random() * CHARS.length);
}
function RandVal() {
return RandBool() ? RandStr() : RandStr();
}
function GenerateSpecPermutes(matchVals, resultArray) {
var maxPermuteBody = 1 << matchVals.length - 1;
for (let bod_pm = 0;bod_pm <= maxPermuteBody;bod_pm++) for (let k = 0;k < matchVals.length;k++) var body = bod_pm & 1 << k > 0 ? null : RandVal();
}
GenerateSpecPermutes(["foo", "bar", "zing",]);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/bug798946.js)
<details>
```js
// tests calling script functions via Debugger.Object.prototype.getProperty
"use strict";
var global = newGlobal();
var dbg = new Debugger(global);
dbg.onDebuggerStatement = onDebuggerStatement;
global.eval(`
const normalObj = { };
const abruptObj = { };
const sym = Symbol("a symbol key");
const arr = [1, 2, 3];
const obj = {
get stringNormal(){
return "a value";
},
get stringAbrupt() {
throw "a value";
},
get objectNormal() {
return normalObj;
},
get objectAbrupt() {
throw abruptObj;
},
get context() {
return this;
},
1234: "number key",
[sym]: "symbol key",
stringProp: "a value",
objectProp: {},
method() {
return "a value";
},
undefined: "undefined value",
};
const propObj = obj.objectProp;
const methodObj = obj.method;
const objChild = Object.create(obj);
const proxyChild = new Proxy(obj, {});
debugger;
`);
function onDebuggerStatement(frame) {
const { environment } = frame;
const arr = environment.getVariable("arr");
const obj = environment.getVariable("obj");
const objChild = environment.getVariable("objChild");
const proxyChild = environment.getVariable("proxyChild");
const sym = environment.getVariable("sym");
const normalObj = environment.getVariable("normalObj");
const abruptObj = environment.getVariable("abruptObj");
const propObj = environment.getVariable("propObj");
const methodObj = environment.getVariable("methodObj");
assertEq(arr.getProperty(1).return, 2);
assertEq(arr.getProperty("1").return, 2);
assertEq(obj.getProperty().return, "undefined value");
assertEq(obj.getProperty("missing").return, undefined);
assertEq(obj.getProperty("stringNormal").return, "a value");
assertEq(obj.getProperty("stringAbrupt").throw, "a value");
assertEq(obj.getProperty("objectNormal").return, normalObj);
assertEq(obj.getProperty("objectAbrupt").throw, abruptObj);
assertEq(obj.getProperty("context").return, obj);
assertEq(obj.getProperty(1234).return, "number key");
assertEq(obj.getProperty(sym).return, "symbol key");
assertEq(obj.getProperty("stringProp").return, "a value");
assertEq(obj.getProperty("objectProp").return, propObj);
assertEq(obj.getProperty("method").return, methodObj);
assertEq(objChild.getProperty().return, "undefined value");
assertEq(objChild.getProperty("missing").return, undefined);
assertEq(objChild.getProperty("stringNormal").return, "a value");
assertEq(objChild.getProperty("stringAbrupt").throw, "a value");
assertEq(objChild.getProperty("objectNormal").return, normalObj);
assertEq(objChild.getProperty("objectAbrupt").throw, abruptObj);
assertEq(objChild.getProperty("context").return, objChild);
assertEq(objChild.getProperty(1234).return, "number key");
assertEq(objChild.getProperty(sym).return, "symbol key");
assertEq(objChild.getProperty("stringProp").return, "a value");
assertEq(objChild.getProperty("objectProp").return, propObj);
assertEq(objChild.getProperty("method").return, methodObj);
assertEq(proxyChild.getProperty().return, "undefined value");
assertEq(proxyChild.getProperty("missing").return, undefined);
assertEq(proxyChild.getProperty("stringNormal").return, "a value");
assertEq(proxyChild.getProperty("stringAbrupt").throw, "a value");
assertEq(proxyChild.getProperty("objectNormal").return, normalObj);
assertEq(proxyChild.getProperty("objectAbrupt").throw, abruptObj);
assertEq(proxyChild.getProperty("context").return, proxyChild);
assertEq(proxyChild.getProperty(1234).return, "number key");
assertEq(proxyChild.getProperty(sym).return, "symbol key");
assertEq(proxyChild.getProperty("stringProp").return, "a value");
assertEq(proxyChild.getProperty("objectProp").return, propObj);
assertEq(proxyChild.getProperty("method").return, methodObj);
};
```
vs
```js
'use strict';
var global = newGlobal();
var dbg = new Debugger(global);
dbg.onDebuggerStatement = onDebuggerStatement;
global.eval(`
const normalObj = { };
const abruptObj = { };
const sym = Symbol("a symbol key");
const arr = [1, 2, 3];
const obj = {
get stringNormal(){
return "a value";
},
get stringAbrupt() {
throw "a value";
},
get objectNormal() {
return normalObj;
},
get objectAbrupt() {
throw abruptObj;
},
get context() {
return this;
},
1234: "number key",
[sym]: "symbol key",
stringProp: "a value",
objectProp: {},
method() {
return "a value";
},
undefined: "undefined value",
};
const propObj = obj.objectProp;
const methodObj = obj.method;
const objChild = Object.create(obj);
const proxyChild = new Proxy(obj, {});
debugger;
`);
function onDebuggerStatement(frame) {
const {environment, } = frame;
const arr = environment.getVariable("arr");
const obj = environment.getVariable("obj");
const objChild = environment.getVariable("objChild");
const proxyChild = environment.getVariable("proxyChild");
const sym = environment.getVariable("sym");
const normalObj = environment.getVariable("normalObj");
const abruptObj = environment.getVariable("abruptObj");
const propObj = environment.getVariable("propObj");
const methodObj = environment.getVariable("methodObj");
assertEq(arr.getProperty(1).return, 2);
assertEq(arr.getProperty("1").return, 2);
assertEq(obj.getProperty().return, "undefined value");
assertEq(obj.getProperty("missing").return, undefined);
assertEq(obj.getProperty("stringNormal").return, "a value");
assertEq(obj.getProperty("stringAbrupt").throw, "a value");
assertEq(obj.getProperty("objectNormal").return, normalObj);
assertEq(obj.getProperty("objectAbrupt").throw, abruptObj);
assertEq(obj.getProperty("context").return, obj);
assertEq(obj.getProperty(1234).return, "number key");
assertEq(obj.getProperty(sym).return, "symbol key");
assertEq(obj.getProperty("stringProp").return, "a value");
assertEq(obj.getProperty("objectProp").return, propObj);
assertEq(obj.getProperty("method").return, methodObj);
assertEq(objChild.getProperty().return, "undefined value");
assertEq(objChild.getProperty("missing").return, undefined);
assertEq(objChild.getProperty("stringNormal").return, "a value");
assertEq(objChild.getProperty("stringAbrupt").throw, "a value");
assertEq(objChild.getProperty("objectNormal").return, normalObj);
assertEq(objChild.getProperty("objectAbrupt").throw, abruptObj);
assertEq(objChild.getProperty("context").return, objChild);
assertEq(objChild.getProperty(1234).return, "number key");
assertEq(objChild.getProperty(sym).return, "symbol key");
assertEq(objChild.getProperty("stringProp").return, "a value");
assertEq(objChild.getProperty("objectProp").return, propObj);
assertEq(objChild.getProperty("method").return, methodObj);
assertEq(proxyChild.getProperty().return, "undefined value");
assertEq(proxyChild.getProperty("missing").return, undefined);
assertEq(proxyChild.getProperty("stringNormal").return, "a value");
assertEq(proxyChild.getProperty("stringAbrupt").throw, "a value");
assertEq(proxyChild.getProperty("objectNormal").return, normalObj);
assertEq(proxyChild.getProperty("objectAbrupt").throw, abruptObj);
assertEq(proxyChild.getProperty("context").return, proxyChild);
assertEq(proxyChild.getProperty(1234).return, "number key");
assertEq(proxyChild.getProperty(sym).return, "symbol key");
assertEq(proxyChild.getProperty("stringProp").return, "a value");
assertEq(proxyChild.getProperty("objectProp").return, propObj);
assertEq(proxyChild.getProperty("method").return, methodObj);
}
;
```
<details>
```js
// Control can exit a for-of loop via return.
function f() {
for (var a of [1, 2, 3]) {
for (var b of [1, 2, 3]) {
for (var c of [1, 2, 3]) {
if (a !== b && b !== c && c !== a)
return "" + a + b + c;
}
}
}
}
assertEq(f(), "123");
```
vs
```js
function f() {
for (a of [1, 2, 3,]) {
for (b of [1, 2, 3,]) {
for (c of [1, 2, 3,]) {
if (a !== b && b !== c && c !== a) return "" + a + b + c;
}
}
}
}
assertEq(f(), "123");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Object-getProperty-01.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/return.js)
<details>
```js
// Constant folding does not affect strict delete.
function f(x) {
"use strict";
// This senseless delete-expression is legal even in strict mode. Per ES5.1
// 11.4.1 step 2, it does nothing and returns true.
return delete (1 ? x : x);
}
assertEq(f(), true);
```
vs
```js
function f(x) {
'use strict';
return delete 1 ? x : x;
}
assertEq(f(), true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-844805-2.js)
<details>
```js
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
function createVector(x,y,z) {
return new Array(x,y,z);
}
function sqrLengthVector(self) {
return self[0] * self[0] + self[1] * self[1] + self[2] * self[2];
}
function lengthVector(self) {
return Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
}
function addVector(self, v) {
self[0] += v[0];
self[1] += v[1];
self[2] += v[2];
return self;
}
function subVector(self, v) {
self[0] -= v[0];
self[1] -= v[1];
self[2] -= v[2];
return self;
}
function scaleVector(self, scale) {
self[0] *= scale;
self[1] *= scale;
self[2] *= scale;
return self;
}
function normaliseVector(self) {
var len = Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
self[0] /= len;
self[1] /= len;
self[2] /= len;
return self;
}
function add(v1, v2) {
return new Array(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]);
}
function sub(v1, v2) {
return new Array(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]);
}
function scalev(v1, v2) {
return new Array(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]);
}
function dot(v1, v2) {
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}
function scale(v, scale) {
return [v[0] * scale, v[1] * scale, v[2] * scale];
}
function cross(v1, v2) {
return [v1[1] * v2[2] - v1[2] * v2[1],
v1[2] * v2[0] - v1[0] * v2[2],
v1[0] * v2[1] - v1[1] * v2[0]];
}
function normalise(v) {
var len = lengthVector(v);
return [v[0] / len, v[1] / len, v[2] / len];
}
function transformMatrix(self, v) {
var vals = self;
var x = vals[0] * v[0] + vals[1] * v[1] + vals[2] * v[2] + vals[3];
var y = vals[4] * v[0] + vals[5] * v[1] + vals[6] * v[2] + vals[7];
var z = vals[8] * v[0] + vals[9] * v[1] + vals[10] * v[2] + vals[11];
return [x, y, z];
}
function invertMatrix(self) {
var temp = new Array(16);
var tx = -self[3];
var ty = -self[7];
var tz = -self[11];
for (h = 0; h < 3; h++)
for (v = 0; v < 3; v++)
temp[h + v * 4] = self[v + h * 4];
for (i = 0; i < 11; i++)
self[i] = temp[i];
self[3] = tx * self[0] + ty * self[1] + tz * self[2];
self[7] = tx * self[4] + ty * self[5] + tz * self[6];
self[11] = tx * self[8] + ty * self[9] + tz * self[10];
return self;
}
// Triangle intersection using barycentric coord method
function Triangle(p1, p2, p3) {
var edge1 = sub(p3, p1);
var edge2 = sub(p2, p1);
var normal = cross(edge1, edge2);
if (Math.abs(normal[0]) > Math.abs(normal[1]))
if (Math.abs(normal[0]) > Math.abs(normal[2]))
this.axis = 0;
else
this.axis = 2;
else
if (Math.abs(normal[1]) > Math.abs(normal[2]))
this.axis = 1;
else
this.axis = 2;
var u = (this.axis + 1) % 3;
var v = (this.axis + 2) % 3;
var u1 = edge1[u];
var v1 = edge1[v];
var u2 = edge2[u];
var v2 = edge2[v];
this.normal = normalise(normal);
this.nu = normal[u] / normal[this.axis];
this.nv = normal[v] / normal[this.axis];
this.nd = dot(normal, p1) / normal[this.axis];
var det = u1 * v2 - v1 * u2;
this.eu = p1[u];
this.ev = p1[v];
this.nu1 = u1 / det;
this.nv1 = -v1 / det;
this.nu2 = v2 / det;
this.nv2 = -u2 / det;
this.material = [0.7, 0.7, 0.7];
}
Triangle.prototype.intersect = function(orig, dir, near, far) {
var u = (this.axis + 1) % 3;
var v = (this.axis + 2) % 3;
var d = dir[this.axis] + this.nu * dir[u] + this.nv * dir[v];
var t = (this.nd - orig[this.axis] - this.nu * orig[u] - this.nv * orig[v]) / d;
if (t < near || t > far)
return null;
var Pu = orig[u] + t * dir[u] - this.eu;
var Pv = orig[v] + t * dir[v] - this.ev;
var a2 = Pv * this.nu1 + Pu * this.nv1;
if (a2 < 0)
return null;
var a3 = Pu * this.nu2 + Pv * this.nv2;
if (a3 < 0)
return null;
if ((a2 + a3) > 1)
return null;
return t;
}
function Scene(a_triangles) {
this.triangles = a_triangles;
this.lights = [];
this.ambient = [0,0,0];
this.background = [0.8,0.8,1];
}
var zero = new Array(0,0,0);
Scene.prototype.intersect = function(origin, dir, near, far) {
var closest = null;
for (i = 0; i < this.triangles.length; i++) {
var triangle = this.triangles[i];
var d = triangle.intersect(origin, dir, near, far);
if (d == null || d > far || d < near)
continue;
far = d;
closest = triangle;
}
if (!closest)
return [this.background[0],this.background[1],this.background[2]];
var normal = closest.normal;
var hit = add(origin, scale(dir, far));
if (dot(dir, normal) > 0)
normal = [-normal[0], -normal[1], -normal[2]];
var colour = null;
if (closest.shader) {
colour = closest.shader(closest, hit, dir);
} else {
colour = closest.material;
}
// do reflection
var reflected = null;
if (colour.reflection > 0.001) {
var reflection = addVector(scale(normal, -2*dot(dir, normal)), dir);
reflected = this.intersect(hit, reflection, 0.0001, 1000000);
if (colour.reflection >= 0.999999)
return reflected;
}
var l = [this.ambient[0], this.ambient[1], this.ambient[2]];
for (var i = 0; i < this.lights.length; i++) {
var light = this.lights[i];
var toLight = sub(light, hit);
var distance = lengthVector(toLight);
scaleVector(toLight, 1.0/distance);
distance -= 0.0001;
if (this.blocked(hit, toLight, distance))
continue;
var nl = dot(normal, toLight);
if (nl > 0)
addVector(l, scale(light.colour, nl));
}
l = scalev(l, colour);
if (reflected) {
l = addVector(scaleVector(l, 1 - colour.reflection), scaleVector(reflected, colour.reflection));
}
return l;
}
Scene.prototype.blocked = function(O, D, far) {
var near = 0.0001;
var closest = null;
for (i = 0; i < this.triangles.length; i++) {
var triangle = this.triangles[i];
var d = triangle.intersect(O, D, near, far);
if (d == null || d > far || d < near)
continue;
return true;
}
return false;
}
// this camera code is from notes i made ages ago, it is from *somewhere* -- i cannot remember where
// that somewhere is
function Camera(origin, lookat, up) {
var zaxis = normaliseVector(subVector(lookat, origin));
var xaxis = normaliseVector(cross(up, zaxis));
var yaxis = normaliseVector(cross(xaxis, subVector([0,0,0], zaxis)));
var m = new Array(16);
m[0] = xaxis[0]; m[1] = xaxis[1]; m[2] = xaxis[2];
m[4] = yaxis[0]; m[5] = yaxis[1]; m[6] = yaxis[2];
m[8] = zaxis[0]; m[9] = zaxis[1]; m[10] = zaxis[2];
invertMatrix(m);
m[3] = 0; m[7] = 0; m[11] = 0;
this.origin = origin;
this.directions = new Array(4);
this.directions[0] = normalise([-0.7, 0.7, 1]);
this.directions[1] = normalise([ 0.7, 0.7, 1]);
this.directions[2] = normalise([ 0.7, -0.7, 1]);
this.directions[3] = normalise([-0.7, -0.7, 1]);
this.directions[0] = transformMatrix(m, this.directions[0]);
this.directions[1] = transformMatrix(m, this.directions[1]);
this.directions[2] = transformMatrix(m, this.directions[2]);
this.directions[3] = transformMatrix(m, this.directions[3]);
}
Camera.prototype.generateRayPair = function(y) {
rays = new Array(new Object(), new Object());
rays[0].origin = this.origin;
rays[1].origin = this.origin;
rays[0].dir = addVector(scale(this.directions[0], y), scale(this.directions[3], 1 - y));
rays[1].dir = addVector(scale(this.directions[1], y), scale(this.directions[2], 1 - y));
return rays;
}
function renderRows(camera, scene, pixels, width, height, starty, stopy) {
for (var y = starty; y < stopy; y++) {
var rays = camera.generateRayPair(y / height);
for (var x = 0; x < width; x++) {
var xp = x / width;
var origin = addVector(scale(rays[0].origin, xp), scale(rays[1].origin, 1 - xp));
var dir = normaliseVector(addVector(scale(rays[0].dir, xp), scale(rays[1].dir, 1 - xp)));
var l = scene.intersect(origin, dir);
pixels[y][x] = l;
}
}
}
Camera.prototype.render = function(scene, pixels, width, height) {
var cam = this;
var row = 0;
renderRows(cam, scene, pixels, width, height, 0, height);
}
function raytraceScene()
{
var numTriangles = 2 * 6;
var triangles = new Array();//numTriangles);
var tfl = createVector(-10, 10, -10);
var tfr = createVector( 10, 10, -10);
var tbl = createVector(-10, 10, 10);
var tbr = createVector( 10, 10, 10);
var bfl = createVector(-10, -10, -10);
var bfr = createVector( 10, -10, -10);
var bbl = createVector(-10, -10, 10);
var bbr = createVector( 10, -10, 10);
// cube!!!
// front
var i = 0;
triangles[i++] = new Triangle(tfl, tfr, bfr);
triangles[i++] = new Triangle(tfl, bfr, bfl);
// back
triangles[i++] = new Triangle(tbl, tbr, bbr);
triangles[i++] = new Triangle(tbl, bbr, bbl);
// triangles[i-1].material = [0.7,0.2,0.2];
// triangles[i-1].material.reflection = 0.8;
// left
triangles[i++] = new Triangle(tbl, tfl, bbl);
// triangles[i-1].reflection = 0.6;
triangles[i++] = new Triangle(tfl, bfl, bbl);
// triangles[i-1].reflection = 0.6;
// right
triangles[i++] = new Triangle(tbr, tfr, bbr);
triangles[i++] = new Triangle(tfr, bfr, bbr);
// top
triangles[i++] = new Triangle(tbl, tbr, tfr);
triangles[i++] = new Triangle(tbl, tfr, tfl);
// bottom
triangles[i++] = new Triangle(bbl, bbr, bfr);
triangles[i++] = new Triangle(bbl, bfr, bfl);
//Floor!!!!
var green = createVector(0.0, 0.4, 0.0);
var grey = createVector(0.4, 0.4, 0.4);
grey.reflection = 1.0;
var floorShader = function(tri, pos, view) {
var x = ((pos[0]/32) % 2 + 2) % 2;
var z = ((pos[2]/32 + 0.3) % 2 + 2) % 2;
if (x < 1 != z < 1) {
//in the real world we use the fresnel term...
// var angle = 1-dot(view, tri.normal);
// angle *= angle;
// angle *= angle;
// angle *= angle;
//grey.reflection = angle;
return grey;
} else
return green;
}
var ffl = createVector(-1000, -30, -1000);
var ffr = createVector( 1000, -30, -1000);
var fbl = createVector(-1000, -30, 1000);
var fbr = createVector( 1000, -30, 1000);
triangles[i++] = new Triangle(fbl, fbr, ffr);
triangles[i-1].shader = floorShader;
triangles[i++] = new Triangle(fbl, ffr, ffl);
triangles[i-1].shader = floorShader;
var _scene = new Scene(triangles);
_scene.lights[0] = createVector(20, 38, -22);
_scene.lights[0].colour = createVector(0.7, 0.3, 0.3);
_scene.lights[1] = createVector(-23, 40, 17);
_scene.lights[1].colour = createVector(0.7, 0.3, 0.3);
_scene.lights[2] = createVector(23, 20, 17);
_scene.lights[2].colour = createVector(0.7, 0.7, 0.7);
_scene.ambient = createVector(0.1, 0.1, 0.1);
// _scene.background = createVector(0.7, 0.7, 1.0);
var size = 30;
var pixels = new Array();
for (var y = 0; y < size; y++) {
pixels[y] = new Array();
for (var x = 0; x < size; x++) {
pixels[y][x] = 0;
}
}
var _camera = new Camera(createVector(-40, 40, 40), createVector(0, 0, 0), createVector(0, 1, 0));
_camera.render(_scene, pixels, size, size);
return pixels;
}
function arrayToCanvasCommands(pixels)
{
var s = '<canvas id="renderCanvas" width="30px" height="30px"></canvas><scr' + 'ipt>\nvar pixels = [';
var size = 30;
for (var y = 0; y < size; y++) {
s += "[";
for (var x = 0; x < size; x++) {
s += "[" + pixels[y][x] + "],";
}
s+= "],";
}
s += '];\n var canvas = document.getElementById("renderCanvas").getContext("2d");\n\
\n\
\n\
var size = 30;\n\
canvas.fillStyle = "red";\n\
canvas.fillRect(0, 0, size, size);\n\
canvas.scale(1, -1);\n\
canvas.translate(0, -size);\n\
\n\
if (!canvas.setFillColor)\n\
canvas.setFillColor = function(r, g, b, a) {\n\
this.fillStyle = "rgb("+[Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]+")";\n\
}\n\
\n\
for (var y = 0; y < size; y++) {\n\
for (var x = 0; x < size; x++) {\n\
var l = pixels[y][x];\n\
canvas.setFillColor(l[0], l[1], l[2], 1);\n\
canvas.fillRect(x, y, 1, 1);\n\
}\n\
}</scr' + 'ipt>';
return s;
}
testOutput = arrayToCanvasCommands(raytraceScene());
expected = '<canvas id="renderCanvas" width="30px" height="30px"></canvas><script>\nvar pixels = [[[0,0.22646733835486615,0],[0,0.22917348499592718,0],[0,0.23178836719862694,0],[0,0.23429286876882874,0],[0,0.23666708243914814,0],[0,0.2388906159889881,0],[0,0.3260187640505792,0],[0,0.33121005205394954,0],[0,0.3363076586511704,0],[0,0.3412818000213254,0],[0,0.34610095331648705,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.369829536245317,0],[0,0.3725822614817006,0],[0,0.37489560357280544,0],[0,0.37673658797290227,0],[0,0.3780753374916205,0],[0,0.378886188721004,0],[0,0.3791488586269958,0],[0,0.3788495731470844,0],[0,0.3779820527845238,0],[0,0.37654824729910663,0],[0,0.4585834760044105,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0,0.22925665044954321,0],[0,0.2320573979410493,0],[0,0.23474822091583247,0],[0,0.2373069549209832,0],[0,0.2397107002896524,0],[0,0.15436982463108695,0],[0,0.15568628300351414,0],[0,0.33780762567168454,0],[0,0.3431766295062631,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.24744701364085558,0.14604872013179526,0.14604872013179526],[0,0.3743786742105677,0],[0,0.37742123153478285,0],[0,0.3799794006700716,0],[0,0.38201209682126785,0],[0,0.38348180518082586,0],[0,0.384356168843629,0],[0,0.3846096564538848,0],[0,0.3842251672467923,0],[0,0.3831954061706588,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0,0.23215413887706876,0],[0,0.2350440502458203,0],[0,0.23780113739316563,0],[0,0.24039973450409946,0],[0,0.24281359296637,0],[0,0.15528082901621987,0],[0,0.15653052853852803,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.24335890550700673,0.1442966737887172,0.1442966737887172],[0.21191595684264103,0.13082112436113186,0.13082112436113186],[0.27664813175852776,0.2248217713585563,0.2248217713585563],[0,0.3823836235518836,0],[0,0.3852234408034573,0],[0,0.38747642030616,0],[0,0.3890951276817348,0],[0,0.39003853152190077,0],[0,0.39027440447223904,0],[0,0.3897816153712006,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.23811367607569112,0],[0,0.240922314629212,0],[0,0.2435404294800615,0],[0,0.24593811382698388,0],[0,0.1559883317159253,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.233189785862315,0.13993847965527784,0.13993847965527784],[0.2095470195339134,0.1298058655145343,0.1298058655145343],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.2414541261336147,0.19927150247084813,0.19927150247084813],[0.30463716829842996,0.25698429422662805,0.25698429422662805],[0,0.39057010876231657,0],[0,0.39307456071571556,0],[0,0.394860705064173,0],[0,0.3958762994996104,0],[0,0.3960806578453934,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.24123643784061885,0],[0,0.24407545031211067,0],[0,0.24668523203085055,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.20428988349740462,0.1275528072131734,0.1275528072131734],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.2553534506258493,0.21540752629099336,0.21540752629099336],[0.8,0.8,1],[0,0.39871352471166227,0],[0,0.40068391900131317,0],[0,0.4017699848209471,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.24436322334505386,0],[0,0.24745253188899904,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0,0.40943101981787544,0],[0,0.41179341435345673,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.24398601063610253,0],[0,0.24734388131046534,0],[0,0.2504039497369661,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.8,0.8,1],[0,0.41015054936419404,0],[0,0.4139256751539831,0],[0,0.5176011801301246,0],[0,0.5175400296826781,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.23925831942915582,0],[0,0.2431514340750372,0],[0,0.24679679895694717,0],[0,0.25013656179204347,0],[0,0.25311244537612027,0],[0,0.2556680399787405,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.8,0.8,1],[0,0.4078259849771481,0],[0,0.4131357292874544,0],[0,0.5218814714518779,0],[0,0.5233124012306586,0],[0,0.522962771547786,0],[0,0.5207522057325761,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.47311372545546515,0],[0,0.4614041416827006,0],],[[0,0.21490764011046362,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.2331842261176049,0],[0,0.23755980367223836,0],[0,0.24175353358196602,0],[0,0.24570333061205787,0],[0,0.24934343472275186,0],[0,0.252606535195386,0],[0,0.25542647135913205,0],[0,0.25774138056580276,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.04000000000000001,0],[0,0.2913399551219817,0],[0,0.40821549181429595,0],[0,0.5226526471916983,0],[0,0.5257809891986108,0],[0,0.5270304637173788,0],[0,0.5262436797403963,0],[0,0.5233412343635394,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.48095949311801045,0],[0,0.46869626187306984,0],[0,0.4558873544509206,0],],[[0,0.21129537920439745,0],[0,0.2160838834157171,0],[0,0.22090682198375836,0],[0.8,0.8,1],[0,0.23049540839949767,0],[0,0.23516114626695328,0],[0,0.23966144813312718,0],[0,0.24392754707957162,0],[0,0.24788516106908107,0],[0,0.25145680804980497,0],[0,0.2545649373510444,0],[0,0.2571357591990073,0],[0,0.2591035093142245,0],[0,0.15255606913369724,0],[0,0.15301134862115395,0],[0.19736821241316202,0.12458637674849803,0.12458637674849803],[0,0.40504494009802183,0],[0,0.4123372862951718,0],[0,0.4183003766375901,0],[0,0.5268338036458257,0],[0,0.5277169309488912,0],[0,0.5263102439245335,0],[0,0.5225497158196737,0],[0,0.5164937589802646,0],[0.8,0.8,1],[0,0.49832248210805585,0],[0,0.4868414893043067,0],[0,0.47425805574715646,0],[0,0.46093994347307254,0],[0,0.4472184699099014,0],],[[0,0.20695133260602822,0],[0,0.21189973891969208,0],[0,0.21691233850171843,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.23191357418198488,0],[0,0.23671451069678634,0],[0,0.24129830018648707,0],[0,0.24558190818576656,0],[0,0.24947677854650704,0],[0,0.2528923625850763,0],[0,0.1528305739035691,0],[0,0.1542326299051252,0],[0.8,0.8,1],[0.19785925315493239,0.12479682278068532,0.12479682278068532],[0.2081375194488818,0.12920179404952076,0.12920179404952076],[0.2240887656214228,0.18514359742568504,0.18514359742568504],[0,0.4135020430625767,0],[0,0.4192949763868133,0],[0,0.42324582463394744,0],[0,0.524175088930771,0],[0,0.5219574826556216,0],[0,0.5172050501700545,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.4895533585416516,0],[0,0.4770140400123619,0],[0,0.4635030619052592,0],[0,0.44941365075166806,0],[0,0.43508467272477774,0],],[[0,0.20179362237895174,0],[0,0.20685458951965674,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.23760464753632676,0],[0,0.24220528986272394,0],[0,0.2464227921634767,0],[0,0.2501524694953926,0],[0,0.15461153696054686,0],[0.18550977568907606,0.11950418958103261,0.11950418958103261],[0.1973204644052136,0.12456591331652012,0.12456591331652012],[0.2088287796802108,0.12949804843437607,0.12949804843437607],[0.21976471724250635,0.134184878818217,0.134184878818217],[0.23568458491329167,0.19345433251780333,0.19345433251780333],[0.23236149715622312,0.19397984285078584,0.19397984285078584],[0.22707008733584053,0.19247800386744748,0.19247800386744748],[0,0.41921793505330557,0],[0,0.42018199893505187,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.4624620672233052,0],[0,0.4484080186022647,0],[0,0.43394937018864516,0],[0,0.4194117002954933,0],],[[0,0.195751560483372,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.4179362030887152,0],[0.8,0.8,1],[0.18284994643317204,0.11836426275707375,0.11836426275707375],[0.19559717882822145,0.12382736235495205,0.12382736235495205],[0.20829587479733996,0.1292696606274314,0.1292696606274314],[0.22064479825066774,0.13456205639314334,0.13456205639314334],[0.2323223325492669,0.13956671394968584,0.13956671394968584],[0.24724443467900797,0.20148878770701636,0.20148878770701636],[0.24548491352821342,0.20390487818440434,0.20390487818440434],[0.24239083545814452,0.20490715724849212,0.20490715724849212],[0.23580267356471662,0.2022853173521094,0.2022853173521094],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.42907468966717865,0],[0,0.4147140942539032,0],[0.8,0.8,1],],[[0.8,0.8,1],[0,0.19385093619429258,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.40369350610660937,0],[0,0.4158360873491173,0],[0.19261301561109398,0.12254843526189743,0.12254843526189743],[0.20636000368544563,0.1284400015794767,0.1284400015794767],[0.22006309132254379,0.13431275342394736,0.13431275342394736],[0.23336548922639505,0.14001378109702645,0.14001378109702645],[0.24588206119264946,0.1453780262254212,0.1453780262254212],[0.2585904923823373,0.20905557193769056,0.20905557193769056],[0.2583880059856603,0.21340384806404408,0.21340384806404408],[0.2579257731612357,0.21738553706566144,0.21738553706566144],[0.25469196497831764,0.21843261169087974,0.21843261169087974],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.4196956387047621,0],[0,0.40600233966188104,0],[0.8,0.8,1],[0.8,0.8,1],],[[0,0.18086678377768206,0],[0,0.29820732165845826,0],[0,0.3078671511008362,0],[0,0.31797632104786633,0],[0,0.3285185113204014,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.3740646417282967,0],[0,0.38583856211873363,0],[0,0.39747405235976174,0],[0.2029477686069114,0.12697761511724776,0.12697761511724776],[0.21781735307317274,0.1333502941742169,0.1333502941742169],[0.2326566051026994,0.13970997361544257,0.13970997361544257],[0.2470420370437997,0.145875158733057,0.145875158733057],[0.9125534455486627,0.5106731929990184,0.5106731929990184],[0.26957187383368114,0.21599310805975738,0.21599310805975738],[0.2707166126603939,0.2221190287629908,0.2221190287629908],[0.2730659500911373,0.22930539474084957,0.22930539474084957],[0.27432898752113144,0.23520013372187343,0.23520013372187343],[0,0.370913970040732,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.41728826192115065,0],[0,0.4053708259838642,0],[0,0.39282677897301016,0],[0,0.37998757881530154,0],[0,0.3671261088322657,0],[0.8,0.8,1],],[[0,0.2734507658091365,0],[0,0.28211354268150884,0],[0,0.29120495530846624,0],[0,0.3007197072254542,0],[0,0.31064069882287787,0],[0,0.32093517914620384,0],[0,0.3315502317284035,0],[0,0.34240777559380986,0],[0,0.35339949423457706,0],[0,0.3643824114196257,0],[0,0.3751761555363945,0],[0.21384735597314658,0.13164886684563426,0.13164886684563426],[0.2299739346154931,0.1385602576923542,0.1385602576923542],[0.24609657496992726,0.1454699607013974,0.1454699607013974],[0.9085781768104235,0.508698320758555,0.508698320758555],[0.9154549906081679,0.5170357163338555,0.5170357163338555],[0.9205088622142807,0.5252164494222175,0.5252164494222175],[0.28215745535360465,0.22973861951523428,0.22973861951523428],[0.2871003088909314,0.23996159648606105,0.23996159648606105],[0.29363706106359355,0.2515193872815144,0.2515193872815144],[0,0.41902122210815307,0],[0,0.41310298499553366,0],[0,0.40544274823125576,0],[0,0.396335311262737,0],[0,0.3861118369914827,0],[0,0.37510764377615097,0],[0,0.3636351145776063,0],[0,0.35196551120236436,0],[0,0.3403202703614798,0],[0,0.32887008288221503,0],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.28175542273932297,0],[0,0.29085225965171946,0],[0,0.3002718747152153,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.3493460616221397,0],[0.22528651843925174,0.1365513650453936,0.1365513650453936],[0.884020287542635,0.49068080880618953,0.49068080880618953],[0.8974534722142382,0.5016001274737849,0.5016001274737849],[0.9089511260291274,0.5124192313516149,0.5124192313516149],[0.918724776273931,0.5233733004162796,0.5233733004162796],[0.9271769325614658,0.5348099989058438,0.5348099989058438],[0.9348913571357613,0.5471866228466732,0.5471866228466732],[0.9425953513779031,0.5610467455399599,0.5610467455399599],[0.31111289810529186,0.2659003418574735,0.2659003418574735],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.36238100335464446,0],[0,0.353165370752559,0],[0,0.3433460721377995,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.269553510147819,0],[0,0.2779247384646558,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.862863795871991,0.4769708653359615,0.4769708653359615],[0.8809280461363547,0.48977541774660666,0.48977541774660666],[0.8970168973464191,0.5025218831442017,0.5025218831442017],[0.911183718592768,0.5154210174684783,0.5154210174684783],[0.923749369873305,0.5288572912288372,0.5288572912288372],[0.9353543113230034,0.5434323975814477,0.5434323975814477],[0.9469976115499875,0.5600089248350288,0.5600089248350288],[0.9600573266066551,0.5797476044207045,0.5797476044207045],[0.976264515309917,0.6041064704498702,0.6041064704498702],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.31964250752889856,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0,0.22050019052313752,0],[0,0.22681553981028935,0],[0,0.23339203717763343,0],[0,0.240214496679792,0],[0,0.24725746972595297,0],[0,0.25448250911433834,0],[0,0.26183515020613984,0],[0,0.26924183890499,0],[0,0.27660721846944913,0],[0,0.2838124066288337,0],[0,0.290715098224911,0],[0,0.2971524154784058,0],[0,0.3029472623689724,0],[0,0.3079184123129743,0],[0.9166547694971252,0.5166323224598249,0.5166323224598249],[0.9306991201883348,0.5311982918579957,0.5311982918579957],[0.942986803591991,0.5467760342781277,0.5467760342781277],[0,0.3165578521241011,0],[0,0.31548839579667104,0],[0,0.3131368632708015,0],[0.8,0.8,1],[0,0.30500137342777356,0],[0,0.29951030523776406,0],[0,0.29329773299429385,0],[0,0.28653936257609475,0],[0,0.27940222592749825,0],[0.8,0.8,1],[0,0.26457440761040923,0],[0,0.2571216942588568,0],[0,0.24976474642245705,0],],[[0.8,0.8,1],[0,0.20714814874471174,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.23670584867979186,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.2653456430194066,0],[0,0.2698801253354915,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.2797697633705014,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.2652596644585568,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.23044738434960232,0],[0.8,0.8,1],],[[0.8,0.8,1],[0,0.1874620478256095,0],[0,0.19215316230371715,0],[0,0.19696169224108015,0],[0,0.20186087426658073,0],[0,0.20681514030842463,0],[0,0.2117788084075138,0],[0,0.21669500719585458,0],[0,0.22149508562026893,0],[0,0.22609882383824634,0],[0,0.23041578943560334,0],[0,0.23434813805418903,0],[0,0.23779500435424242,0],[0,0.240658357082728,0],[0.8,0.8,1],[0,0.24429776275232565,0],[0,0.24495325891611666,0],[0,0.24479455500778916,0],[0,0.24382873003864916,0],[0.8,0.8,1],[0,0.23963973129383997,0],[0,0.23655408649128906,0],[0,0.23292473874860314,0],[0,0.2288489260033022,0],[0.8,0.8,1],[0,0.21974417921637143,0],[0,0.21489400490094954,0],[0,0.20994923454342304,0],[0,0.20497430079270745,0],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.1797204574749079,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.19516287408734248,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.2074862652007326,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.20573701126457444,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.19259287153244908,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.17697513874785395,0],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.1614935034375082,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.17936757268974335,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.17026872079690972,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0,0.12879641411423945,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.1358377385211167,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.1546643297719027,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.1559650385862031,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.14211514071040432,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.13513052327523242,0],],[[0,0.11212384156112787,0],[0.8,0.8,1],[0,0.11564325792725064,0],[0,0.1174011949544484,0],[0.8,0.8,1],[0,0.12084571295779206,0],[0,0.12249918688067803,0],[0,0.1240816293005488,0],[0,0.12557222890553357,0],[0.8,0.8,1],[0,0.12819024296879525,0],[0,0.12927368617900967,0],[0.8,0.8,1],[0,0.13088813449481448,0],[0,0.13138603838942955,0],[0.8,0.8,1],[0,0.13170953912018962,0],[0.8,0.8,1],[0,0.13112114069722186,0],[0,0.13049815823500216,0],[0.8,0.8,1],[0,0.12866048872503766,0],[0,0.1274822855623644,0],[0.8,0.8,1],[0,0.1247126669400825,0],[0,0.12316534788101306,0],[0,0.12153830315457151,0],[0,0.11985151859147432,0],[0.8,0.8,1],[0,0.11637011656642021,0],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.104782462250846,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.1094376687357348,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0,0.0830756783895465,0],[0.8,0.8,1],[0,0.08474229354589341,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.08702004690763979,0],[0.8,0.8,1],[0,0.08829471061229066,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.0896722795161435,0],[0.8,0.8,1],[0,0.0901512080809384,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.09012955842093213,0],[0.8,0.8,1],[0,0.08962319641070081,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.08821080590025861,0],[0.8,0.8,1],[0,0.08691857775431859,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.08462346811430875,0],[0.8,0.8,1],[0,0.08295071578903558,0],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.06935458357760912,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.07223735845162484,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.07191875490542338,0],[0,0.07163456254931609,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],];\n var canvas = document.getElementById("renderCanvas").getContext("2d");\n\n\n var size = 30;\n canvas.fillStyle = "red";\n canvas.fillRect(0, 0, size, size);\n canvas.scale(1, -1);\n canvas.translate(0, -size);\n\n if (!canvas.setFillColor)\n canvas.setFillColor = function(r, g, b, a) {\n this.fillStyle = "rgb("+[Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]+")";\n }\n\nfor (var y = 0; y < size; y++) {\n for (var x = 0; x < size; x++) {\n var l = pixels[y][x];\n canvas.setFillColor(l[0], l[1], l[2], 1);\n canvas.fillRect(x, y, 1, 1);\n }\n}</script>';
assertEq(testOutput, expected)
```
vs
```js
function createVector(x, y, z) {
return new Array(x, y, z);
}
function sqrLengthVector(self) {
return self[0] * self[0] + self[1] * self[1] + self[2] * self[2];
}
function lengthVector(self) {
return Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
}
function addVector(self, v) {
self[0] += v[0];
self[1] += v[1];
self[2] += v[2];
return self;
}
function subVector(self, v) {
self[0] -= v[0];
self[1] -= v[1];
self[2] -= v[2];
return self;
}
function scaleVector(self, scale) {
self[0] *= scale;
self[1] *= scale;
self[2] *= scale;
return self;
}
function normaliseVector(self) {
var len = Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
self[0] /= len;
self[1] /= len;
self[2] /= len;
return self;
}
function add(v1, v2) {
return new Array(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]);
}
function sub(v1, v2) {
return new Array(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]);
}
function scalev(v1, v2) {
return new Array(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]);
}
function dot(v1, v2) {
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}
function scale(v, scale) {
return [v[0] * scale, v[1] * scale, v[2] * scale,];
}
function cross(v1, v2) {
return [v1[1] * v2[2] - v1[2] * v2[1], v1[2] * v2[0] - v1[0] * v2[2], v1[0] * v2[1] - v1[1] * v2[0],];
}
function normalise(v) {
var len = lengthVector(v);
return [v[0] / len, v[1] / len, v[2] / len,];
}
function transformMatrix(self, v) {
var vals = self;
var x = vals[0] * v[0] + vals[1] * v[1] + vals[2] * v[2] + vals[3];
var y = vals[4] * v[0] + vals[5] * v[1] + vals[6] * v[2] + vals[7];
var z = vals[8] * v[0] + vals[9] * v[1] + vals[10] * v[2] + vals[11];
return [x, y, z,];
}
function invertMatrix(self) {
var temp = new Array(16);
var tx = -self[3];
var ty = -self[7];
var tz = -self[11];
for (h = 0;h < 3;h++) for (v = 0;v < 3;v++) temp[h + v * 4] = self[v + h * 4];
for (i = 0;i < 11;i++) self[i] = temp[i];
self[3] = tx * self[0] + ty * self[1] + tz * self[2];
self[7] = tx * self[4] + ty * self[5] + tz * self[6];
self[11] = tx * self[8] + ty * self[9] + tz * self[10];
return self;
}
function Triangle(p1, p2, p3) {
var edge1 = sub(p3, p1);
var edge2 = sub(p2, p1);
var normal = cross(edge1, edge2);
if (Math.abs(normal[0]) > Math.abs(normal[1])) if (Math.abs(normal[0]) > Math.abs(normal[2])) this.axis = 0;
else this.axis = 2;
else if (Math.abs(normal[1]) > Math.abs(normal[2])) this.axis = 1;
else this.axis = 2;
var u = this.axis + 1 % 3;
var v = this.axis + 2 % 3;
var u1 = edge1[u];
var v1 = edge1[v];
var u2 = edge2[u];
var v2 = edge2[v];
this.normal = normalise(normal);
this.nu = normal[u] / normal[this.axis];
this.nv = normal[v] / normal[this.axis];
this.nd = dot(normal, p1) / normal[this.axis];
var det = u1 * v2 - v1 * u2;
this.eu = p1[u];
this.ev = p1[v];
this.nu1 = u1 / det;
this.nv1 = -v1 / det;
this.nu2 = v2 / det;
this.nv2 = -u2 / det;
this.material = [0.7, 0.7, 0.7,];
}
Triangle.prototype.intersect = (function(orig, dir, near, far) {
var u = this.axis + 1 % 3;
var v = this.axis + 2 % 3;
var d = dir[this.axis] + this.nu * dir[u] + this.nv * dir[v];
var t = this.nd - orig[this.axis] - this.nu * orig[u] - this.nv * orig[v] / d;
if (t < near || t > far) return null;
var Pu = orig[u] + t * dir[u] - this.eu;
var Pv = orig[v] + t * dir[v] - this.ev;
var a2 = Pv * this.nu1 + Pu * this.nv1;
if (a2 < 0) return null;
var a3 = Pu * this.nu2 + Pv * this.nv2;
if (a3 < 0) return null;
if (a2 + a3 > 1) return null;
return t;
});
function Scene(a_triangles) {
this.triangles = a_triangles;
this.lights = [];
this.ambient = [0, 0, 0,];
this.background = [0.8, 0.8, 1,];
}
var zero = new Array(0, 0, 0);
Scene.prototype.intersect = (function(origin, dir, near, far) {
var closest = null;
for (i = 0;i < this.triangles.length;i++) {
var triangle = this.triangles[i];
var d = triangle.intersect(origin, dir, near, far);
if (d == null || d > far || d < near) continue;
far = d;
closest = triangle;
}
if (!closest) return [this.background[0], this.background[1], this.background[2],];
var normal = closest.normal;
var hit = add(origin, scale(dir, far));
if (dot(dir, normal) > 0) normal = [-normal[0], -normal[1], -normal[2],];
var colour = null;
if (closest.shader) {
colour = closest.shader(closest, hit, dir);
} else {
colour = closest.material;
}
var reflected = null;
if (colour.reflection > 0.001) {
var reflection = addVector(scale(normal, -2 * dot(dir, normal)), dir);
reflected = this.intersect(hit, reflection, 0.0001, 1000000);
if (colour.reflection >= 0.999999) return reflected;
}
var l = [this.ambient[0], this.ambient[1], this.ambient[2],];
for (let i = 0;i < this.lights.length;i++) {
var light = this.lights[i];
var toLight = sub(light, hit);
var distance = lengthVector(toLight);
scaleVector(toLight, 1.0 / distance);
distance -= 0.0001;
if (this.blocked(hit, toLight, distance)) continue;
var nl = dot(normal, toLight);
if (nl > 0) addVector(l, scale(light.colour, nl));
}
l = scalev(l, colour);
if (reflected) {
l = addVector(scaleVector(l, 1 - colour.reflection), scaleVector(reflected, colour.reflection));
}
return l;
});
Scene.prototype.blocked = (function(O, D, far) {
var near = 0.0001;
var closest = null;
for (i = 0;i < this.triangles.length;i++) {
var triangle = this.triangles[i];
var d = triangle.intersect(O, D, near, far);
if (d == null || d > far || d < near) continue;
return true;
}
return false;
});
function Camera(origin, lookat, up) {
var zaxis = normaliseVector(subVector(lookat, origin));
var xaxis = normaliseVector(cross(up, zaxis));
var yaxis = normaliseVector(cross(xaxis, subVector([0, 0, 0,], zaxis)));
var m = new Array(16);
m[0] = xaxis[0];
m[1] = xaxis[1];
m[2] = xaxis[2];
m[4] = yaxis[0];
m[5] = yaxis[1];
m[6] = yaxis[2];
m[8] = zaxis[0];
m[9] = zaxis[1];
m[10] = zaxis[2];
invertMatrix(m);
m[3] = 0;
m[7] = 0;
m[11] = 0;
this.origin = origin;
this.directions = new Array(4);
this.directions[0] = normalise([-0.7, 0.7, 1,]);
this.directions[1] = normalise([0.7, 0.7, 1,]);
this.directions[2] = normalise([0.7, -0.7, 1,]);
this.directions[3] = normalise([-0.7, -0.7, 1,]);
this.directions[0] = transformMatrix(m, this.directions[0]);
this.directions[1] = transformMatrix(m, this.directions[1]);
this.directions[2] = transformMatrix(m, this.directions[2]);
this.directions[3] = transformMatrix(m, this.directions[3]);
}
Camera.prototype.generateRayPair = (function(y) {
rays = new Array(new Object(), new Object());
rays[0].origin = this.origin;
rays[1].origin = this.origin;
rays[0].dir = addVector(scale(this.directions[0], y), scale(this.directions[3], 1 - y));
rays[1].dir = addVector(scale(this.directions[1], y), scale(this.directions[2], 1 - y));
return rays;
});
function renderRows(camera, scene, pixels, width, height, starty, stopy) {
for (let y = starty;y < stopy;y++) {
var rays = camera.generateRayPair(y / height);
for (let x = 0;x < width;x++) {
var xp = x / width;
var origin = addVector(scale(rays[0].origin, xp), scale(rays[1].origin, 1 - xp));
var dir = normaliseVector(addVector(scale(rays[0].dir, xp), scale(rays[1].dir, 1 - xp)));
var l = scene.intersect(origin, dir);
pixels[y][x] = l;
}
}
}
Camera.prototype.render = (function(scene, pixels, width, height) {
var cam = this;
var row = 0;
renderRows(cam, scene, pixels, width, height, 0, height);
});
function raytraceScene() {
var numTriangles = 2 * 6;
var triangles = new Array();
var tfl = createVector(-10, 10, -10);
var tfr = createVector(10, 10, -10);
var tbl = createVector(-10, 10, 10);
var tbr = createVector(10, 10, 10);
var bfl = createVector(-10, -10, -10);
var bfr = createVector(10, -10, -10);
var bbl = createVector(-10, -10, 10);
var bbr = createVector(10, -10, 10);
var i = 0;
triangles[i++] = new Triangle(tfl, tfr, bfr);
triangles[i++] = new Triangle(tfl, bfr, bfl);
triangles[i++] = new Triangle(tbl, tbr, bbr);
triangles[i++] = new Triangle(tbl, bbr, bbl);
triangles[i++] = new Triangle(tbl, tfl, bbl);
triangles[i++] = new Triangle(tfl, bfl, bbl);
triangles[i++] = new Triangle(tbr, tfr, bbr);
triangles[i++] = new Triangle(tfr, bfr, bbr);
triangles[i++] = new Triangle(tbl, tbr, tfr);
triangles[i++] = new Triangle(tbl, tfr, tfl);
triangles[i++] = new Triangle(bbl, bbr, bfr);
triangles[i++] = new Triangle(bbl, bfr, bfl);
var green = createVector(0.0, 0.4, 0.0);
var grey = createVector(0.4, 0.4, 0.4);
grey.reflection = 1.0;
var floorShader = function(tri, pos, view) {
var x = pos[0] / 32 % 2 + 2 % 2;
var z = pos[2] / 32 + 0.3 % 2 + 2 % 2;
if (x < 1 != z < 1) {
return grey;
} else return green;
};
var ffl = createVector(-1000, -30, -1000);
var ffr = createVector(1000, -30, -1000);
var fbl = createVector(-1000, -30, 1000);
var fbr = createVector(1000, -30, 1000);
triangles[i++] = new Triangle(fbl, fbr, ffr);
triangles[i - 1].shader = floorShader;
triangles[i++] = new Triangle(fbl, ffr, ffl);
triangles[i - 1].shader = floorShader;
var _scene = new Scene(triangles);
_scene.lights[0] = createVector(20, 38, -22);
_scene.lights[0].colour = createVector(0.7, 0.3, 0.3);
_scene.lights[1] = createVector(-23, 40, 17);
_scene.lights[1].colour = createVector(0.7, 0.3, 0.3);
_scene.lights[2] = createVector(23, 20, 17);
_scene.lights[2].colour = createVector(0.7, 0.7, 0.7);
_scene.ambient = createVector(0.1, 0.1, 0.1);
var size = 30;
var pixels = new Array();
for (let y = 0;y < size;y++) {
pixels[y] = new Array();
for (let x = 0;x < size;x++) {
pixels[y][x] = 0;
}
}
var _camera = new Camera(createVector(-40, 40, 40), createVector(0, 0, 0), createVector(0, 1, 0));
_camera.render(_scene, pixels, size, size);
return pixels;
}
function arrayToCanvasCommands(pixels) {
var s = '<canvas id="renderCanvas" width="30px" height="30px"></canvas><scr' + 'ipt>\nvar pixels = [';
var size = 30;
for (let y = 0;y < size;y++) {
s += "[";
for (let x = 0;x < size;x++) {
s += "[" + pixels[y][x] + "],";
}
s += "],";
}
s += '];\n var canvas = document.getElementById("renderCanvas").getContext("2d");\n\n\nvar size = 30;\ncanvas.fillStyle = "red";\ncanvas.fillRect(0, 0, size, size);\ncanvas.scale(1, -1);\ncanvas.translate(0, -size);\n\nif (!canvas.setFillColor)\ncanvas.setFillColor = function(r, g, b, a) {\nthis.fillStyle = "rgb("+[Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]+")";\n}\n\nfor (var y = 0; y < size; y++) {\nfor (var x = 0; x < size; x++) {\nvar l = pixels[y][x];\ncanvas.setFillColor(l[0], l[1], l[2], 1);\ncanvas.fillRect(x, y, 1, 1);\n}\n}</scr' + 'ipt>';
return s;
}
testOutput = arrayToCanvasCommands(raytraceScene());
expected = '<canvas id="renderCanvas" width="30px" height="30px"></canvas><script>\nvar pixels = [[[0,0.22646733835486615,0],[0,0.22917348499592718,0],[0,0.23178836719862694,0],[0,0.23429286876882874,0],[0,0.23666708243914814,0],[0,0.2388906159889881,0],[0,0.3260187640505792,0],[0,0.33121005205394954,0],[0,0.3363076586511704,0],[0,0.3412818000213254,0],[0,0.34610095331648705,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.369829536245317,0],[0,0.3725822614817006,0],[0,0.37489560357280544,0],[0,0.37673658797290227,0],[0,0.3780753374916205,0],[0,0.378886188721004,0],[0,0.3791488586269958,0],[0,0.3788495731470844,0],[0,0.3779820527845238,0],[0,0.37654824729910663,0],[0,0.4585834760044105,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0,0.22925665044954321,0],[0,0.2320573979410493,0],[0,0.23474822091583247,0],[0,0.2373069549209832,0],[0,0.2397107002896524,0],[0,0.15436982463108695,0],[0,0.15568628300351414,0],[0,0.33780762567168454,0],[0,0.3431766295062631,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.24744701364085558,0.14604872013179526,0.14604872013179526],[0,0.3743786742105677,0],[0,0.37742123153478285,0],[0,0.3799794006700716,0],[0,0.38201209682126785,0],[0,0.38348180518082586,0],[0,0.384356168843629,0],[0,0.3846096564538848,0],[0,0.3842251672467923,0],[0,0.3831954061706588,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0,0.23215413887706876,0],[0,0.2350440502458203,0],[0,0.23780113739316563,0],[0,0.24039973450409946,0],[0,0.24281359296637,0],[0,0.15528082901621987,0],[0,0.15653052853852803,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.24335890550700673,0.1442966737887172,0.1442966737887172],[0.21191595684264103,0.13082112436113186,0.13082112436113186],[0.27664813175852776,0.2248217713585563,0.2248217713585563],[0,0.3823836235518836,0],[0,0.3852234408034573,0],[0,0.38747642030616,0],[0,0.3890951276817348,0],[0,0.39003853152190077,0],[0,0.39027440447223904,0],[0,0.3897816153712006,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.23811367607569112,0],[0,0.240922314629212,0],[0,0.2435404294800615,0],[0,0.24593811382698388,0],[0,0.1559883317159253,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.233189785862315,0.13993847965527784,0.13993847965527784],[0.2095470195339134,0.1298058655145343,0.1298058655145343],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.2414541261336147,0.19927150247084813,0.19927150247084813],[0.30463716829842996,0.25698429422662805,0.25698429422662805],[0,0.39057010876231657,0],[0,0.39307456071571556,0],[0,0.394860705064173,0],[0,0.3958762994996104,0],[0,0.3960806578453934,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.24123643784061885,0],[0,0.24407545031211067,0],[0,0.24668523203085055,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.20428988349740462,0.1275528072131734,0.1275528072131734],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.2553534506258493,0.21540752629099336,0.21540752629099336],[0.8,0.8,1],[0,0.39871352471166227,0],[0,0.40068391900131317,0],[0,0.4017699848209471,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.24436322334505386,0],[0,0.24745253188899904,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0,0.40943101981787544,0],[0,0.41179341435345673,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.24398601063610253,0],[0,0.24734388131046534,0],[0,0.2504039497369661,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.8,0.8,1],[0,0.41015054936419404,0],[0,0.4139256751539831,0],[0,0.5176011801301246,0],[0,0.5175400296826781,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.23925831942915582,0],[0,0.2431514340750372,0],[0,0.24679679895694717,0],[0,0.25013656179204347,0],[0,0.25311244537612027,0],[0,0.2556680399787405,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.06999999999999999,0.06999999999999999,0.06999999999999999],[0.8,0.8,1],[0,0.4078259849771481,0],[0,0.4131357292874544,0],[0,0.5218814714518779,0],[0,0.5233124012306586,0],[0,0.522962771547786,0],[0,0.5207522057325761,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.47311372545546515,0],[0,0.4614041416827006,0],],[[0,0.21490764011046362,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.2331842261176049,0],[0,0.23755980367223836,0],[0,0.24175353358196602,0],[0,0.24570333061205787,0],[0,0.24934343472275186,0],[0,0.252606535195386,0],[0,0.25542647135913205,0],[0,0.25774138056580276,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.04000000000000001,0],[0,0.2913399551219817,0],[0,0.40821549181429595,0],[0,0.5226526471916983,0],[0,0.5257809891986108,0],[0,0.5270304637173788,0],[0,0.5262436797403963,0],[0,0.5233412343635394,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.48095949311801045,0],[0,0.46869626187306984,0],[0,0.4558873544509206,0],],[[0,0.21129537920439745,0],[0,0.2160838834157171,0],[0,0.22090682198375836,0],[0.8,0.8,1],[0,0.23049540839949767,0],[0,0.23516114626695328,0],[0,0.23966144813312718,0],[0,0.24392754707957162,0],[0,0.24788516106908107,0],[0,0.25145680804980497,0],[0,0.2545649373510444,0],[0,0.2571357591990073,0],[0,0.2591035093142245,0],[0,0.15255606913369724,0],[0,0.15301134862115395,0],[0.19736821241316202,0.12458637674849803,0.12458637674849803],[0,0.40504494009802183,0],[0,0.4123372862951718,0],[0,0.4183003766375901,0],[0,0.5268338036458257,0],[0,0.5277169309488912,0],[0,0.5263102439245335,0],[0,0.5225497158196737,0],[0,0.5164937589802646,0],[0.8,0.8,1],[0,0.49832248210805585,0],[0,0.4868414893043067,0],[0,0.47425805574715646,0],[0,0.46093994347307254,0],[0,0.4472184699099014,0],],[[0,0.20695133260602822,0],[0,0.21189973891969208,0],[0,0.21691233850171843,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.23191357418198488,0],[0,0.23671451069678634,0],[0,0.24129830018648707,0],[0,0.24558190818576656,0],[0,0.24947677854650704,0],[0,0.2528923625850763,0],[0,0.1528305739035691,0],[0,0.1542326299051252,0],[0.8,0.8,1],[0.19785925315493239,0.12479682278068532,0.12479682278068532],[0.2081375194488818,0.12920179404952076,0.12920179404952076],[0.2240887656214228,0.18514359742568504,0.18514359742568504],[0,0.4135020430625767,0],[0,0.4192949763868133,0],[0,0.42324582463394744,0],[0,0.524175088930771,0],[0,0.5219574826556216,0],[0,0.5172050501700545,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.4895533585416516,0],[0,0.4770140400123619,0],[0,0.4635030619052592,0],[0,0.44941365075166806,0],[0,0.43508467272477774,0],],[[0,0.20179362237895174,0],[0,0.20685458951965674,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.23760464753632676,0],[0,0.24220528986272394,0],[0,0.2464227921634767,0],[0,0.2501524694953926,0],[0,0.15461153696054686,0],[0.18550977568907606,0.11950418958103261,0.11950418958103261],[0.1973204644052136,0.12456591331652012,0.12456591331652012],[0.2088287796802108,0.12949804843437607,0.12949804843437607],[0.21976471724250635,0.134184878818217,0.134184878818217],[0.23568458491329167,0.19345433251780333,0.19345433251780333],[0.23236149715622312,0.19397984285078584,0.19397984285078584],[0.22707008733584053,0.19247800386744748,0.19247800386744748],[0,0.41921793505330557,0],[0,0.42018199893505187,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.4624620672233052,0],[0,0.4484080186022647,0],[0,0.43394937018864516,0],[0,0.4194117002954933,0],],[[0,0.195751560483372,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.4179362030887152,0],[0.8,0.8,1],[0.18284994643317204,0.11836426275707375,0.11836426275707375],[0.19559717882822145,0.12382736235495205,0.12382736235495205],[0.20829587479733996,0.1292696606274314,0.1292696606274314],[0.22064479825066774,0.13456205639314334,0.13456205639314334],[0.2323223325492669,0.13956671394968584,0.13956671394968584],[0.24724443467900797,0.20148878770701636,0.20148878770701636],[0.24548491352821342,0.20390487818440434,0.20390487818440434],[0.24239083545814452,0.20490715724849212,0.20490715724849212],[0.23580267356471662,0.2022853173521094,0.2022853173521094],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.42907468966717865,0],[0,0.4147140942539032,0],[0.8,0.8,1],],[[0.8,0.8,1],[0,0.19385093619429258,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.40369350610660937,0],[0,0.4158360873491173,0],[0.19261301561109398,0.12254843526189743,0.12254843526189743],[0.20636000368544563,0.1284400015794767,0.1284400015794767],[0.22006309132254379,0.13431275342394736,0.13431275342394736],[0.23336548922639505,0.14001378109702645,0.14001378109702645],[0.24588206119264946,0.1453780262254212,0.1453780262254212],[0.2585904923823373,0.20905557193769056,0.20905557193769056],[0.2583880059856603,0.21340384806404408,0.21340384806404408],[0.2579257731612357,0.21738553706566144,0.21738553706566144],[0.25469196497831764,0.21843261169087974,0.21843261169087974],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.4196956387047621,0],[0,0.40600233966188104,0],[0.8,0.8,1],[0.8,0.8,1],],[[0,0.18086678377768206,0],[0,0.29820732165845826,0],[0,0.3078671511008362,0],[0,0.31797632104786633,0],[0,0.3285185113204014,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.3740646417282967,0],[0,0.38583856211873363,0],[0,0.39747405235976174,0],[0.2029477686069114,0.12697761511724776,0.12697761511724776],[0.21781735307317274,0.1333502941742169,0.1333502941742169],[0.2326566051026994,0.13970997361544257,0.13970997361544257],[0.2470420370437997,0.145875158733057,0.145875158733057],[0.9125534455486627,0.5106731929990184,0.5106731929990184],[0.26957187383368114,0.21599310805975738,0.21599310805975738],[0.2707166126603939,0.2221190287629908,0.2221190287629908],[0.2730659500911373,0.22930539474084957,0.22930539474084957],[0.27432898752113144,0.23520013372187343,0.23520013372187343],[0,0.370913970040732,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.41728826192115065,0],[0,0.4053708259838642,0],[0,0.39282677897301016,0],[0,0.37998757881530154,0],[0,0.3671261088322657,0],[0.8,0.8,1],],[[0,0.2734507658091365,0],[0,0.28211354268150884,0],[0,0.29120495530846624,0],[0,0.3007197072254542,0],[0,0.31064069882287787,0],[0,0.32093517914620384,0],[0,0.3315502317284035,0],[0,0.34240777559380986,0],[0,0.35339949423457706,0],[0,0.3643824114196257,0],[0,0.3751761555363945,0],[0.21384735597314658,0.13164886684563426,0.13164886684563426],[0.2299739346154931,0.1385602576923542,0.1385602576923542],[0.24609657496992726,0.1454699607013974,0.1454699607013974],[0.9085781768104235,0.508698320758555,0.508698320758555],[0.9154549906081679,0.5170357163338555,0.5170357163338555],[0.9205088622142807,0.5252164494222175,0.5252164494222175],[0.28215745535360465,0.22973861951523428,0.22973861951523428],[0.2871003088909314,0.23996159648606105,0.23996159648606105],[0.29363706106359355,0.2515193872815144,0.2515193872815144],[0,0.41902122210815307,0],[0,0.41310298499553366,0],[0,0.40544274823125576,0],[0,0.396335311262737,0],[0,0.3861118369914827,0],[0,0.37510764377615097,0],[0,0.3636351145776063,0],[0,0.35196551120236436,0],[0,0.3403202703614798,0],[0,0.32887008288221503,0],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.28175542273932297,0],[0,0.29085225965171946,0],[0,0.3002718747152153,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.3493460616221397,0],[0.22528651843925174,0.1365513650453936,0.1365513650453936],[0.884020287542635,0.49068080880618953,0.49068080880618953],[0.8974534722142382,0.5016001274737849,0.5016001274737849],[0.9089511260291274,0.5124192313516149,0.5124192313516149],[0.918724776273931,0.5233733004162796,0.5233733004162796],[0.9271769325614658,0.5348099989058438,0.5348099989058438],[0.9348913571357613,0.5471866228466732,0.5471866228466732],[0.9425953513779031,0.5610467455399599,0.5610467455399599],[0.31111289810529186,0.2659003418574735,0.2659003418574735],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.36238100335464446,0],[0,0.353165370752559,0],[0,0.3433460721377995,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.269553510147819,0],[0,0.2779247384646558,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.862863795871991,0.4769708653359615,0.4769708653359615],[0.8809280461363547,0.48977541774660666,0.48977541774660666],[0.8970168973464191,0.5025218831442017,0.5025218831442017],[0.911183718592768,0.5154210174684783,0.5154210174684783],[0.923749369873305,0.5288572912288372,0.5288572912288372],[0.9353543113230034,0.5434323975814477,0.5434323975814477],[0.9469976115499875,0.5600089248350288,0.5600089248350288],[0.9600573266066551,0.5797476044207045,0.5797476044207045],[0.976264515309917,0.6041064704498702,0.6041064704498702],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.31964250752889856,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0,0.22050019052313752,0],[0,0.22681553981028935,0],[0,0.23339203717763343,0],[0,0.240214496679792,0],[0,0.24725746972595297,0],[0,0.25448250911433834,0],[0,0.26183515020613984,0],[0,0.26924183890499,0],[0,0.27660721846944913,0],[0,0.2838124066288337,0],[0,0.290715098224911,0],[0,0.2971524154784058,0],[0,0.3029472623689724,0],[0,0.3079184123129743,0],[0.9166547694971252,0.5166323224598249,0.5166323224598249],[0.9306991201883348,0.5311982918579957,0.5311982918579957],[0.942986803591991,0.5467760342781277,0.5467760342781277],[0,0.3165578521241011,0],[0,0.31548839579667104,0],[0,0.3131368632708015,0],[0.8,0.8,1],[0,0.30500137342777356,0],[0,0.29951030523776406,0],[0,0.29329773299429385,0],[0,0.28653936257609475,0],[0,0.27940222592749825,0],[0.8,0.8,1],[0,0.26457440761040923,0],[0,0.2571216942588568,0],[0,0.24976474642245705,0],],[[0.8,0.8,1],[0,0.20714814874471174,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.23670584867979186,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.2653456430194066,0],[0,0.2698801253354915,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.2797697633705014,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.2652596644585568,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.23044738434960232,0],[0.8,0.8,1],],[[0.8,0.8,1],[0,0.1874620478256095,0],[0,0.19215316230371715,0],[0,0.19696169224108015,0],[0,0.20186087426658073,0],[0,0.20681514030842463,0],[0,0.2117788084075138,0],[0,0.21669500719585458,0],[0,0.22149508562026893,0],[0,0.22609882383824634,0],[0,0.23041578943560334,0],[0,0.23434813805418903,0],[0,0.23779500435424242,0],[0,0.240658357082728,0],[0.8,0.8,1],[0,0.24429776275232565,0],[0,0.24495325891611666,0],[0,0.24479455500778916,0],[0,0.24382873003864916,0],[0.8,0.8,1],[0,0.23963973129383997,0],[0,0.23655408649128906,0],[0,0.23292473874860314,0],[0,0.2288489260033022,0],[0.8,0.8,1],[0,0.21974417921637143,0],[0,0.21489400490094954,0],[0,0.20994923454342304,0],[0,0.20497430079270745,0],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.1797204574749079,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.19516287408734248,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.2074862652007326,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.20573701126457444,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.19259287153244908,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.17697513874785395,0],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.1614935034375082,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.17936757268974335,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.17026872079690972,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0,0.12879641411423945,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.1358377385211167,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.1546643297719027,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.1559650385862031,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.14211514071040432,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.13513052327523242,0],],[[0,0.11212384156112787,0],[0.8,0.8,1],[0,0.11564325792725064,0],[0,0.1174011949544484,0],[0.8,0.8,1],[0,0.12084571295779206,0],[0,0.12249918688067803,0],[0,0.1240816293005488,0],[0,0.12557222890553357,0],[0.8,0.8,1],[0,0.12819024296879525,0],[0,0.12927368617900967,0],[0.8,0.8,1],[0,0.13088813449481448,0],[0,0.13138603838942955,0],[0.8,0.8,1],[0,0.13170953912018962,0],[0.8,0.8,1],[0,0.13112114069722186,0],[0,0.13049815823500216,0],[0.8,0.8,1],[0,0.12866048872503766,0],[0,0.1274822855623644,0],[0.8,0.8,1],[0,0.1247126669400825,0],[0,0.12316534788101306,0],[0,0.12153830315457151,0],[0,0.11985151859147432,0],[0.8,0.8,1],[0,0.11637011656642021,0],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.104782462250846,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.1094376687357348,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0,0.0830756783895465,0],[0.8,0.8,1],[0,0.08474229354589341,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.08702004690763979,0],[0.8,0.8,1],[0,0.08829471061229066,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.0896722795161435,0],[0.8,0.8,1],[0,0.0901512080809384,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.09012955842093213,0],[0.8,0.8,1],[0,0.08962319641070081,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.08821080590025861,0],[0.8,0.8,1],[0,0.08691857775431859,0],[0.8,0.8,1],[0.8,0.8,1],[0,0.08462346811430875,0],[0.8,0.8,1],[0,0.08295071578903558,0],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.06935458357760912,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.07223735845162484,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0,0.07191875490542338,0],[0,0.07163456254931609,0],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],[[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],[0.8,0.8,1],],];\n var canvas = document.getElementById("renderCanvas").getContext("2d");\n\n\n var size = 30;\n canvas.fillStyle = "red";\n canvas.fillRect(0, 0, size, size);\n canvas.scale(1, -1);\n canvas.translate(0, -size);\n\n if (!canvas.setFillColor)\n canvas.setFillColor = function(r, g, b, a) {\n this.fillStyle = "rgb("+[Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]+")";\n }\n\nfor (var y = 0; y < size; y++) {\n for (var x = 0; x < size; x++) {\n var l = pixels[y][x];\n canvas.setFillColor(l[0], l[1], l[2], 1);\n canvas.fillRect(x, y, 1, 1);\n }\n}</script>';
assertEq(testOutput, expected);
```
<details>
```js
// A for-of loop over an array does not take a snapshot of the array elements.
// Instead, each time the loop needs an element from the array, it gets its current value.
var a = [3, 5, 5, 4, 0, 5];
var s = '';
for (var i of a) {
s += i;
a[i] = 'X';
}
assertEq(s, '355X0X');
```
vs
```js
var a = [3, 5, 5, 4, 0, 5,];
var s = '';
for (i of a) {
s += i;
a[i] = 'X';
}
assertEq(s, '355X0X');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-2.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-3d-raytrace.js)
<details>
```js
var ws = new WeakSet;
// Delete on empty
assertEq(ws.delete({}), false);
// Delete existing
var value = {};
ws.add(value);
assertEq(ws.has(value), true);
assertEq(ws.delete(value), true);
assertEq(ws.has(value), false);
// Delete non-empty
for (var i = 0; i < 10; i++)
ws.add({});
assertEq(ws.add(value), ws);
assertEq(ws.has(value), true);
assertEq(ws.delete(value), true);
assertEq(ws.has(value), false);
assertEq(ws.delete(value), false);
assertEq(ws.has(value), false);
// Delete primitive
assertEq(ws.delete(15), false);
// Delete with cross-compartment WeakSet
ws = new (newGlobal().WeakSet);
WeakSet.prototype.add.call(ws, value);
assertEq(WeakSet.prototype.has.call(ws, value), true);
assertEq(WeakSet.prototype.delete.call(ws, value), true);
assertEq(WeakSet.prototype.has.call(ws, value), false);
assertEq(WeakSet.prototype.delete.call(ws, value), false);
```
vs
```js
var ws = new WeakSet();
assertEq(ws.delete(({})), false);
var value = ({});
ws.add(value);
assertEq(ws.has(value), true);
assertEq(ws.delete(value), true);
assertEq(ws.has(value), false);
for (let i = 0;i < 10;i++) ws.add({});
assertEq(ws.add(value), ws);
assertEq(ws.has(value), true);
assertEq(ws.delete(value), true);
assertEq(ws.has(value), false);
assertEq(ws.delete(value), false);
assertEq(ws.has(value), false);
assertEq(ws.delete(15), false);
ws = new newGlobal().WeakSet();
WeakSet.prototype.add.call(ws, value);
assertEq(WeakSet.prototype.has.call(ws, value), true);
assertEq(WeakSet.prototype.delete.call(ws, value), true);
assertEq(WeakSet.prototype.has.call(ws, value), false);
assertEq(WeakSet.prototype.delete.call(ws, value), false);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/WeakSet-delete.js)
<details>
```js
gczeal(1);
var o0 = Function.prototype;
o1 = {};
var o4 = Error.prototype;
o5 = new Int32Array(100);
o6 = new Proxy({}, {})
o8 = new Proxy(function() { return {}; }, {
get: function() { return 10; },
});
o9 = {};
var o10 = -500;
var o12 = new Int32Array(100);
function f0(o) {
}
function f1(o) {
}
function f3(o) {
with(o) {}
o[o5] = o5;
}
function f5(o) {
}for(var f2 in o9) {
for(var i1=0; i1<83; i1++) {
for(var i3=0; i3<98; i3++) {
for(var x in f1) { f1[x]; };
}
Object.defineProperty(o0, 'constructor', {enumerable: true,unused: 1 });
f1(f5);
f4(f3);
f3(o8);
f2(o5);
o9.toString(1, 2);
f4.caller = o3;
f2(o6);
f0(f2);
f1(f2);
f0(f1);
var key = Object.getOwnPropertyNames(o9)[2]; if(key) delete o9[key];
var props = Object.getOwnPropertyNames(o5);
if (props.length > 6) {
var prop = props[6];
o8[prop] = o5[prop];
}
f3(f1);
f1(f5);
}
for(var o3 in f1) {
f1(o3);
f4(o3);
o0 == f4;
f1(f3);
Object.freeze(o12);
f0(o9);
new f0(o1);
o4 = o5.call(o4, o4, o4, o4, o4, o4);
f2(o10);
var prop = Object.getOwnPropertyNames(o0)[15];
if (prop) { Object.defineProperty(o0, prop, {configurable: true,enumerable: true,get: function(){},set: function(){},unused: 1 }); }
f3(f1);
new f2(o0);
}
f5(o9);
gc();
f0(o2);
f3(f4);
new f4(o7);
f1 = new o10(f1, f1, f1, f1);
f5(o10);
f5(o7);
f0(o7);
f1(o10);
f3(o10);
delete f0.constructor;
f0(f3);
f1 = wrap(f3);
f4(f1);
delete o1.prototype;
f4(o5);
f2(f2);
o1 + '';
f2(f2);
f0(o12);
f0(o12);
f1(o3);
o5[3] = 8.3;
o10['__proto_' + '_'];
}
for(var o2 in f5) {
for(var o10 in f3) {
delete f2['__proto_' + '_'];
o8 = f1.toString;
f1(o1);
f0(o9);
f2(o12);
var key = Object.getOwnPropertyNames(o3)[19]; if(key) o9 = o3[key];
f1(o10);
f4(f1);
f1(o1);
f1(o7);
for(var x in o1) { o1[x]; };
f0(o8);
f4(o1);
f0(o1);
f0.p0 = o6;
f3(o9);
f5(o8);
f2 >>> o7;
if(o3 === o8) {}
f5(o3);
}
o5[0] = f4;
o0.caller = function() { };
Object.freeze(f0);
f4(o3);
o7.p0 = o3;
f1(f5);
f4(o10);
f2(o5);
f2(o5);
f0(o3);
o8[o8] = o8;
f0(o5);
f1(o6);
f2 = Object.create(o5);
var key = Object.getOwnPropertyNames(o11)[23]; if(key) f2 = o11[key];
f5(o9);
o12 = o6.bind(o12, o12, o12);
f5(f4);
f1(o1);
f0(o11);
f1(o11);
eval('f4');
f4(o1);
Object.isExtensible(o7);
}
(function() {
f1(o12);
f5 + '';
if(o8 != o3) {}
})();
f1(o10);
f3(f0);
o4.toSource = function() { };
var _o = o1;
var prop = Object.getOwnPropertyNames(_o)[5];
if (prop) { _o[prop](o2, o2); }
f3(o0);
f1(f3);
Object.isExtensible(f1);
```
vs
```js
gczeal(1);
var o0 = Function.prototype;
o1 = ({});
var o4 = Error.prototype;
o5 = new Int32Array(100);
o6 = new Proxy(({}), ({}));
o8 = new Proxy((function() {
return { };
}), ({
get: (function() {
return 10;
}),
}));
o9 = ({});
var o10 = -500;
var o12 = new Int32Array(100);
function f0(o) { }
function f1(o) { }
function f3(o) {
with (o) {
}
o[o5] = o5;
}
function f5(o) { }
for (f2 in o9) {
for (let i1 = 0;i1 < 83;i1++) {
for (let i3 = 0;i3 < 98;i3++) {
for (x in f1) {
f1[x];
}
;
}
Object.defineProperty(o0, 'constructor', {
enumerable: true,
unused: 1,
});
f1(f5);
f4(f3);
f3(o8);
f2(o5);
o9.toString(1, 2);
f4.caller = o3;
f2(o6);
f0(f2);
f1(f2);
f0(f1);
var key = Object.getOwnPropertyNames(o9)[2];
if (key) delete o9[key];
var props = Object.getOwnPropertyNames(o5);
if (props.length > 6) {
var prop = props[6];
o8[prop] = o5[prop];
}
f3(f1);
f1(f5);
}
for (o3 in f1) {
f1(o3);
f4(o3);
o0 == f4;
f1(f3);
Object.freeze(o12);
f0(o9);
new f0(o1);
o4 = o5.call(o4, o4, o4, o4, o4, o4);
f2(o10);
var prop = Object.getOwnPropertyNames(o0)[15];
if (prop) {
Object.defineProperty(o0, prop, {
configurable: true,
enumerable: true,
get: function() { },
set: function() { },
unused: 1,
});
}
f3(f1);
new f2(o0);
}
f5(o9);
gc();
f0(o2);
f3(f4);
new f4(o7);
f1 = new o10(f1, f1, f1, f1);
f5(o10);
f5(o7);
f0(o7);
f1(o10);
f3(o10);
delete f0.constructor;
f0(f3);
f1 = wrap(f3);
f4(f1);
delete o1.prototype;
f4(o5);
f2(f2);
o1 + '';
f2(f2);
f0(o12);
f0(o12);
f1(o3);
o5[3] = 8.3;
o10['__proto_' + '_'];
}
for (o2 in f5) {
for (o10 in f3) {
delete f2['__proto_' + '_'];
o8 = f1.toString;
f1(o1);
f0(o9);
f2(o12);
var key = Object.getOwnPropertyNames(o3)[19];
if (key) o9 = o3[key];
f1(o10);
f4(f1);
f1(o1);
f1(o7);
for (x in o1) {
o1[x];
}
;
f0(o8);
f4(o1);
f0(o1);
f0.p0 = o6;
f3(o9);
f5(o8);
f2 >>> o7;
if (o3 === o8) {
}
f5(o3);
}
o5[0] = f4;
o0.caller = function() { };
Object.freeze(f0);
f4(o3);
o7.p0 = o3;
f1(f5);
f4(o10);
f2(o5);
f2(o5);
f0(o3);
o8[o8] = o8;
f0(o5);
f1(o6);
f2 = Object.create(o5);
var key = Object.getOwnPropertyNames(o11)[23];
if (key) f2 = o11[key];
f5(o9);
o12 = o6.bind(o12, o12, o12);
f5(f4);
f1(o1);
f0(o11);
f1(o11);
eval('f4');
f4(o1);
Object.isExtensible(o7);
}
(function() {
f1(o12);
f5 + '';
if (o8 != o3) {
}
})();
f1(o10);
f3(f0);
o4.toSource = (function() { });
var _o = o1;
var prop = Object.getOwnPropertyNames(_o)[5];
if (prop) {
_o[prop](o2, o2);
}
f3(o0);
f1(f3);
Object.isExtensible(f1);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug641225.js)
<details>
```js
function test_syntax(postfixes, check_error, ignore_opts) {
function test_reflect(code, module) {
var options = undefined;
if (module) {
options = {target: "module"};
}
for (var postfix of postfixes) {
var cur_code = code + postfix;
var caught = false;
try {
Reflect.parse(cur_code, options);
} catch (e) {
caught = true;
check_error(e, cur_code, "reflect");
}
assertEq(caught, true);
}
}
function test_eval(code) {
for (var postfix of postfixes) {
var cur_code = code + postfix;
var caught = false;
try {
eval(cur_code);
} catch (e) {
caught = true;
check_error(e, cur_code, "eval");
}
assertEq(caught, true);
}
}
function test(code, opts={}) {
if (ignore_opts) {
opts = {};
}
let no_strict = "no_strict" in opts && opts.no_strict;
let no_fun = "no_fun" in opts && opts.no_fun;
let no_eval = "no_eval" in opts && opts.no_eval;
let module = "module" in opts && opts.module;
test_reflect(code, module);
if (!no_strict) {
test_reflect("'use strict'; " + code, module);
}
if (!no_fun) {
test_reflect("(function() { " + code, module);
if (!no_strict) {
test_reflect("(function() { 'use strict'; " + code, module);
}
}
if (!no_eval) {
test_eval(code);
if (!no_strict) {
test_eval("'use strict'; " + code);
}
if (!no_fun) {
test_eval("(function() { " + code);
if (!no_strict) {
test_eval("(function() { 'use strict'; " + code);
}
}
}
}
function test_fun_arg(arg) {
for (var postfix of postfixes) {
var cur_arg = arg + postfix;
var caught = false;
try {
new Function(cur_arg, "");
} catch (e) {
caught = true;
check_error(e, cur_arg, "fun_arg");
}
assertEq(caught, true);
}
}
// ==== Statements and declarations ====
// ---- Control flow ----
// Block
test("{ ");
test("{ } ");
test("{ 1 ");
test("{ 1; ");
test("{ 1; } ");
// break
test("a: for (;;) { break ");
test("a: for (;;) { break; ");
test("a: for (;;) { break a ");
test("a: for (;;) { break a; ");
test("a: for (;;) { break\n");
// continue
test("a: for (;;) { continue ");
test("a: for (;;) { continue; ");
test("a: for (;;) { continue a ");
test("a: for (;;) { continue a; ");
test("a: for (;;) { continue\n");
// Empty
test("");
test("; ");
// if...else
test("if ");
test("if (");
test("if (x ");
test("if (x) ");
test("if (x) { ");
test("if (x) {} ");
test("if (x) {} else ");
test("if (x) {} else { ");
test("if (x) {} else {} ");
test("if (x) x ");
test("if (x) x; ");
test("if (x) x; else ");
test("if (x) x; else y ");
test("if (x) x; else y; ");
// switch
test("switch ");
test("switch (");
test("switch (x ");
test("switch (x) ");
test("switch (x) { ");
test("switch (x) { case ");
test("switch (x) { case 1 ");
test("switch (x) { case 1: ");
test("switch (x) { case 1: case ");
test("switch (x) { case 1: case 2 ");
test("switch (x) { case 1: case 2: ");
test("switch (x) { case 1: case 2: x ");
test("switch (x) { case 1: case 2: x; ");
test("switch (x) { case 1: case 2: x; break ");
test("switch (x) { case 1: case 2: x; break; ");
test("switch (x) { case 1: case 2: x; break; case ");
test("switch (x) { case 1: case 2: x; break; case 3 ");
test("switch (x) { case 1: case 2: x; break; case 3: y ");
test("switch (x) { case 1: case 2: x; break; case 3: y; ");
test("switch (x) { case 1: case 2: x; break; case 3: y; default ");
test("switch (x) { case 1: case 2: x; break; case 3: y; default: ");
test("switch (x) { case 1: case 2: x; break; case 3: y; default: z ");
test("switch (x) { case 1: case 2: x; break; case 3: y; default: z; ");
test("switch (x) { case 1: case 2: x; break; case 3: y; default: z; } ");
// throw
test("throw ");
test("throw x ");
test("throw x; ");
// try...catch
test("try ");
test("try { ");
test("try {} ");
test("try {} catch ");
test("try {} catch ( ");
test("try {} catch (e ");
test("try {} catch (e) ");
test("try {} catch (e) { ");
test("try {} catch (e) {} ");
test("try {} catch (e) {} finally ");
test("try {} catch (e) {} finally { ");
test("try {} catch (e) {} finally {} ");
// ---- Declarations ----
// var
test("var ");
test("var x ");
test("var x = ");
test("var x = 1 ");
test("var x = 1 + ");
test("var x = 1 + 2 ");
test("var x = 1 + 2, ");
test("var x = 1 + 2, y ");
test("var x = 1 + 2, y, ");
test("var x = 1 + 2, y, z ");
test("var x = 1 + 2, y, z; ");
test("var [ ");
test("var [ x ");
test("var [ x, ");
test("var [ x, ... ");
test("var { ");
test("var { x ");
test("var { x: ");
test("var { x: y ");
test("var { x: y, ");
test("var { x: y } ");
test("var { x: y } = ");
// let
test("let ");
test("let x ");
test("let x = ");
test("let x = 1 ");
test("let x = 1 + ");
test("let x = 1 + 2 ");
test("let x = 1 + 2, ");
test("let x = 1 + 2, y ");
test("let x = 1 + 2, y, ");
test("let x = 1 + 2, y, z ");
test("let x = 1 + 2, y, z; ");
test("let [ ");
test("let [ x ");
test("let [ x, ");
test("let [ x, ... ");
test("let { ");
test("let { x ");
test("let { x: ");
test("let { x: y ");
test("let { x: y, ");
test("let { x: y } ");
test("let { x: y } = ");
// const
test("const ");
test("const x ");
test("const x = ");
test("const x = 1 ");
test("const x = 1 + ");
test("const x = 1 + 2 ");
test("const x = 1 + 2, ");
test("const x = 1 + 2, y = 0");
test("const x = 1 + 2, y = 0, ");
test("const x = 1 + 2, y = 0, z = 0 ");
test("const x = 1 + 2, y = 0, z = 0; ");
test("const [ ");
test("const [ x ");
test("const [ x, ");
test("const [ x, ... ");
test("const { ");
test("const { x ");
test("const { x: ");
test("const { x: y ");
test("const { x: y, ");
test("const { x: y } ");
test("const { x: y } = ");
// ---- Functions ----
// function
test("function ");
test("function f ");
test("function f( ");
test("function f(x ");
test("function f(x, ");
test("function f(x, [ ");
test("function f(x, [y ");
test("function f(x, [y, ");
test("function f(x, [y, { ");
test("function f(x, [y, {z ");
test("function f(x, [y, {z: ");
test("function f(x, [y, {z: zz ");
test("function f(x, [y, {z: zz, ");
test("function f(x, [y, {z: zz, w ");
test("function f(x, [y, {z: zz, w} ");
test("function f(x, [y, {z: zz, w}] ");
test("function f(x, [y, {z: zz, w}], ");
test("function f(x, [y, {z: zz, w}], v ");
test("function f(x, [y, {z: zz, w}], v= ");
test("function f(x, [y, {z: zz, w}], v=1 ");
test("function f(x, [y, {z: zz, w}], v=1, ");
test("function f(x, [y, {z: zz, w}], v=1, ... ");
test("function f(x, [y, {z: zz, w}], v=1, ...t ");
test("function f(x, [y, {z: zz, w}], v=1, ...t) ");
test("function f(x, [y, {z: zz, w}], v=1, ...t) {");
test("function f(x, [y, {z: zz, w}], v=1, ...t) { x ");
test("function f(x, [y, {z: zz, w}], v=1, ...t) { x; ");
test("function f(x, [y, {z: zz, w}], v=1, ...t) { x; } ");
// star function
test("function* ");
test("function* f ");
test("function* f( ");
test("function* f(x ");
test("function* f(x, ");
test("function* f(x, ... ");
test("function* f(x, ...t ");
test("function* f(x, ...t) ");
test("function* f(x, ...t) {");
test("function* f(x, ...t) { x ");
test("function* f(x, ...t) { x; ");
test("function* f(x, ...t) { x; } ");
// return
test("function f() { return ");
test("function f() { return 1 ");
test("function f() { return 1; ");
test("function f() { return 1; } ");
test("function f() { return; ");
test("function f() { return\n");
// yield
test("function* f() { yield ");
test("function* f() { yield 1 ");
test("function* f() { yield* ");
test("function* f() { yield* 1 ");
test("function* f() { yield\n");
test("function* f() { yield*\n");
// ---- Iterations ----
// do...while
test("do ");
test("do {");
test("do {} ");
test("do {} while ");
test("do {} while ( ");
test("do {} while (x ");
test("do {} while (x) ");
test("do {} while (x); ");
test("do x ");
test("do x; ");
test("do x; while ");
// for
test("for ");
test("for (");
test("for (x ");
test("for (x; ");
test("for (x; y ");
test("for (x; y; ");
test("for (x; y; z ");
test("for (x; y; z) ");
test("for (x; y; z) { ");
test("for (x; y; z) {} ");
test("for (x; y; z) x ");
test("for (x; y; z) x; ");
test("for (var ");
test("for (var x ");
test("for (var x = ");
test("for (var x = y ");
test("for (var x = y; ");
test("for (let ");
test("for (let x ");
test("for (let x = ");
test("for (let x = y ");
test("for (let x = y; ");
// for...in
test("for (x in ");
test("for (x in y ");
test("for (x in y) ");
test("for (var x in ");
test("for (var x in y ");
test("for (var x in y) ");
test("for (let x in ");
test("for (let x in y ");
test("for (let x in y) ");
// for...of
test("for (x of ");
test("for (x of y ");
test("for (x of y) ");
test("for (var x of ");
test("for (var x of y ");
test("for (var x of y) ");
test("for (let x of ");
test("for (let x of y ");
test("for (let x of y) ");
// while
test("while ");
test("while (");
test("while (x ");
test("while (x) ");
test("while (x) { ");
test("while (x) {} ");
test("while (x) x ");
test("while (x) x; ");
// ---- Others ----
// debugger
test("debugger ");
test("debugger; ");
// export
var opts = { no_fun: true, no_eval: true, module: true };
test("export ", opts);
test("export { ", opts);
test("export { x ", opts);
test("export { x, ", opts);
test("export { x, y ", opts);
test("export { x, y as ", opts);
test("export { x, y as z ", opts);
test("export { x, y as z } ", opts);
test("export { x, y as z } from ", opts);
test("export { x, y as z } from 'a' ", opts);
test("export { x, y as z } from 'a'; ", opts);
test("export * ", opts);
test("export * from ", opts);
test("export * from 'a' ", opts);
test("export * from 'a'; ", opts);
test("export function ", opts);
test("export function f ", opts);
test("export function f( ", opts);
test("export function f() ", opts);
test("export function f() { ", opts);
test("export function f() {} ", opts);
test("export function f() {}; ", opts);
test("export var ", opts);
test("export var a ", opts);
test("export var a = ", opts);
test("export var a = 1 ", opts);
test("export var a = 1, ", opts);
test("export var a = 1, b ", opts);
test("export var a = 1, b = ", opts);
test("export var a = 1, b = 2 ", opts);
test("export var a = 1, b = 2; ", opts);
test("export let ", opts);
test("export let a ", opts);
test("export let a = ", opts);
test("export let a = 1 ", opts);
test("export let a = 1, ", opts);
test("export let a = 1, b ", opts);
test("export let a = 1, b = ", opts);
test("export let a = 1, b = 2 ", opts);
test("export let a = 1, b = 2; ", opts);
test("export const ", opts);
test("export const a ", opts);
test("export const a = ", opts);
test("export const a = 1 ", opts);
test("export const a = 1, ", opts);
test("export const a = 1, b ", opts);
test("export const a = 1, b = ", opts);
test("export const a = 1, b = 2 ", opts);
test("export const a = 1, b = 2; ", opts);
test("export class ", opts);
test("export class Foo ", opts);
test("export class Foo { ", opts);
test("export class Foo { constructor ", opts);
test("export class Foo { constructor( ", opts);
test("export class Foo { constructor() ", opts);
test("export class Foo { constructor() { ", opts);
test("export class Foo { constructor() {} ", opts);
test("export class Foo { constructor() {} } ", opts);
test("export class Foo { constructor() {} }; ", opts);
test("export default ", opts);
test("export default 1 ", opts);
test("export default 1; ", opts);
test("export default function ", opts);
test("export default function() ", opts);
test("export default function() { ", opts);
test("export default function() {} ", opts);
test("export default function() {}; ", opts);
test("export default function foo ", opts);
test("export default function foo( ", opts);
test("export default function foo() ", opts);
test("export default function foo() { ", opts);
test("export default function foo() {} ", opts);
test("export default function foo() {}; ", opts);
test("export default class ", opts);
test("export default class { ", opts);
test("export default class { constructor ", opts);
test("export default class { constructor( ", opts);
test("export default class { constructor() ", opts);
test("export default class { constructor() { ", opts);
test("export default class { constructor() {} ", opts);
test("export default class { constructor() {} } ", opts);
test("export default class { constructor() {} }; ", opts);
test("export default class Foo ", opts);
test("export default class Foo { ", opts);
test("export default class Foo { constructor ", opts);
test("export default class Foo { constructor( ", opts);
test("export default class Foo { constructor() ", opts);
test("export default class Foo { constructor() { ", opts);
test("export default class Foo { constructor() {} ", opts);
test("export default class Foo { constructor() {} } ", opts);
test("export default class Foo { constructor() {} }; ", opts);
// import
test("import ", opts);
test("import x ", opts);
test("import x from ", opts);
test("import x from 'a' ", opts);
test("import x from 'a'; ", opts);
test("import { ", opts);
test("import { x ", opts);
test("import { x, ", opts);
test("import { x, y ", opts);
test("import { x, y } ", opts);
test("import { x, y } from ", opts);
test("import { x, y } from 'a' ", opts);
test("import { x, y } from 'a'; ", opts);
test("import { x as ", opts);
test("import { x as y ", opts);
test("import { x as y } ", opts);
test("import { x as y } from ", opts);
test("import { x as y } from 'a' ", opts);
test("import { x as y } from 'a'; ", opts);
test("import 'a' ", opts);
test("import 'a'; ", opts);
test("import * ", opts);
test("import * as ", opts);
test("import * as a ", opts);
test("import * as a from ", opts);
test("import * as a from 'a' ", opts);
test("import * as a from 'a'; ", opts);
test("import a ", opts);
test("import a, ", opts);
test("import a, * ", opts);
test("import a, * as ", opts);
test("import a, * as b ", opts);
test("import a, * as b from ", opts);
test("import a, * as b from 'c' ", opts);
test("import a, * as b from 'c'; ", opts);
test("import a, { ", opts);
test("import a, { b ", opts);
test("import a, { b } ", opts);
test("import a, { b } from ", opts);
test("import a, { b } from 'c' ", opts);
test("import a, { b } from 'c'; ", opts);
// label
test("a ");
test("a: ");
// with
opts = { no_strict: true };
test("with ", opts);
test("with (", opts);
test("with (x ", opts);
test("with (x) ", opts);
test("with (x) { ", opts);
test("with (x) {} ", opts);
test("with (x) x ", opts);
test("with (x) x; ", opts);
// ==== Expressions and operators ====
// ---- Primary expressions ----
// this
test("this ");
// function
test("(function ");
test("(function ( ");
test("(function (x ");
test("(function (x, ");
test("(function (x, ... ");
test("(function (x, ...t ");
test("(function (x, ...t) ");
test("(function (x, ...t) {");
test("(function (x, ...t) { x ");
test("(function (x, ...t) { x; ");
test("(function (x, ...t) { x; } ");
test("(function (x, ...t) { x; }) ");
// star function
test("(function* ");
test("(function* ( ");
test("(function* (x ");
test("(function* (x, ");
test("(function* (x, ... ");
test("(function* (x, ...t ");
test("(function* (x, ...t) ");
test("(function* (x, ...t) {");
test("(function* (x, ...t) { x ");
test("(function* (x, ...t) { x; ");
test("(function* (x, ...t) { x; } ");
test("(function* (x, ...t) { x; }) ");
// Array literal
test("[ ");
test("[] ");
test("[1 ");
test("[1, ");
test("[1, ... ");
test("[1, ...x ");
test("[1, ...x] ");
// object
test("({ ");
test("({ x ");
test("({ x: ");
test("({ x: 1 ");
test("({ x: 1, ");
test("({ x: 1, y ");
test("({ x: 1, y: ");
test("({ x: 1, y: 2 ");
test("({ x: 1, y: 2, ");
test("({ x: 1, y: 2, z ");
test("({ x: 1, y: 2, z, ");
test("({ x: 1, y: 2, z, w ");
test("({ x: 1, y: 2, z, w } ");
test("({ x: 1, y: 2, z, w }) ");
// object: computed property
test("({ [");
test("({ [k ");
test("({ [k] ");
test("({ [k]: ");
test("({ [k]: 1 ");
test("({ [k]: 1, ");
// object: getter
test("({ get ");
test("({ get p ");
test("({ get p( ");
test("({ get p() ");
test("({ get p() { ");
test("({ get p() {} ");
test("({ get p() {}, ");
test("({ get p() {}, } ");
test("({ get [ ");
test("({ get [p ");
test("({ get [p] ");
test("({ get [p]( ");
test("({ get [p]() ");
// object: setter
test("({ set ");
test("({ set p ");
test("({ set p( ");
test("({ set p(v ");
test("({ set p(v) ");
test("({ set p(v) { ");
test("({ set p(v) {} ");
test("({ set [ ");
test("({ set [p ");
test("({ set [p] ");
test("({ set [p]( ");
test("({ set [p](v ");
test("({ set [p](v) ");
// object: method
test("({ m ");
test("({ m( ");
test("({ m() ");
test("({ m() { ");
test("({ m() {} ");
test("({ m() {}, ");
test("({ [ ");
test("({ [m ");
test("({ [m] ");
test("({ [m]( ");
test("({ [m]() ");
test("({ [m]() { ");
test("({ [m]() {} ");
test("({ [m]() {}, ");
test("({ * ");
test("({ *m ");
test("({ *m( ");
test("({ *m() ");
test("({ *m() { ");
test("({ *m() {} ");
test("({ *m() {}, ");
test("({ *[ ");
test("({ *[m ");
test("({ *[m] ");
test("({ *[m]( ");
test("({ *[m]() ");
test("({ *[m]() { ");
test("({ *[m]() {} ");
test("({ *[m]() {}, ");
test("({ * get ");
test("({ * get ( ");
test("({ * get () ");
test("({ * get () { ");
test("({ * get () {} ");
test("({ * get () {}, ");
test("({ * set ");
test("({ * set ( ");
test("({ * set () ");
test("({ * set () { ");
test("({ * set () {} ");
test("({ * set () {}, ");
// Regular expression literal
test("/a/ ");
test("/a/g ");
// ---- Left-hand-side expressions ----
// property access
test("a[ ");
test("a[1 ");
test("a[1] ");
test("a. ");
test("a.b ");
test("a.b; ");
// new
test("new ");
test("new f ");
test("new f( ");
test("new f() ");
test("new f(); ");
// ---- Increment and decrement ----
test("a ++ ");
test("a ++; ");
test("-- ");
test("-- a ");
test("-- a; ");
// ---- Unary operators ----
// delete
test("delete ");
test("delete a ");
test("delete a[ ");
test("delete a[b ");
test("delete a[b] ");
test("delete a[b]; ");
test("delete ( ");
test("delete (a ");
test("delete (a[ ");
test("delete (a[b ");
test("delete (a[b] ");
test("delete (a[b]) ");
test("delete (a[b]); ");
// void
test("void ");
test("void a ");
test("void a; ");
test("void (");
test("void (a ");
test("void (a) ");
test("void (a); ");
// typeof
test("typeof ");
test("typeof a ");
test("typeof a; ");
test("typeof (");
test("typeof (a ");
test("typeof (a) ");
test("typeof (a); ");
// -
test("- ");
test("- 1 ");
test("- 1; ");
// +
test("+ ");
test("+ 1 ");
test("+ 1; ");
// ---- Arithmetic operators ----
// +
test("1 + ");
test("1 + 1 ");
test("1 + 1; ");
// ---- Relational operators ----
// in
test("a in ");
test("a in b ");
test("a in b; ");
// instanceof
test("a instanceof ");
test("a instanceof b ");
test("a instanceof b; ");
// ---- Equality operators ----
// ==
test("1 == ");
test("1 == 1 ");
test("1 == 1; ");
// ---- Bitwise shift operators ----
// <<
test("1 << ");
test("1 << 1 ");
test("1 << 1; ");
// ---- Binary bitwise operators ----
// &
test("1 & ");
test("1 & 1 ");
test("1 & 1; ");
// ---- Binary logical operators ----
// ||
test("1 || ");
test("1 || 1 ");
test("1 || 1; ");
// ---- Conditional (ternary) operator ----
test("1 ? ");
test("1 ? 2 ");
test("1 ? 2 : ");
test("1 ? 2 : 3 ");
test("1 ? 2 : 3; ");
// ---- Assignment operators ----
test("x = ");
test("x = 1 ");
test("x = 1 + ");
test("x = 1 + 2 ");
test("x = 1 + 2; ");
// ---- Comma operator ----
test("1, ");
test("1, 2 ");
test("1, 2; ");
// ---- Functions ----
// Arrow functions
test("a => ");
test("a => 1 ");
test("a => 1; ");
test("a => { ");
test("a => {} ");
test("a => {}; ");
test("( ");
test("() ");
test("() => ");
test("(...");
test("(...a ");
test("(...a) ");
test("(...a) => ");
test("([ ");
test("([a ");
test("([a] ");
test("([a]) ");
test("([a]) => ");
test("({ ");
test("({a ");
test("({a} ");
test("({a}) ");
test("({a}) => ");
test("({a: ");
test("({a: b ");
test("({a: b, ");
test("({a: b} ");
test("({a: b}) ");
test("({a: b}) => ");
// ---- Class declaration ----
test("class ");
test("class a ");
test("class a { ");
test("class a { constructor ");
test("class a { constructor( ");
test("class a { constructor() ");
test("class a { constructor() { ");
test("class a { constructor() { } ");
test("class a { constructor() { } } ");
test("class a { constructor() { } static ");
test("class a { constructor() { } static m ");
test("class a { constructor() { } static m( ");
test("class a { constructor() { } static m() ");
test("class a { constructor() { } static m() { ");
test("class a { constructor() { } static m() {} ");
test("class a { constructor() { } static m() {} } ");
test("class a { constructor() { } static ( ");
test("class a { constructor() { } static () ");
test("class a { constructor() { } static () { ");
test("class a { constructor() { } static () {} ");
test("class a { constructor() { } static () {} } ");
test("class a { constructor() { } static get ");
test("class a { constructor() { } static get p ");
test("class a { constructor() { } static get p( ");
test("class a { constructor() { } static get p() ");
test("class a { constructor() { } static get p() { ");
test("class a { constructor() { } static get p() {} ");
test("class a { constructor() { } static get p() {} } ");
test("class a { constructor() { } static set ");
test("class a { constructor() { } static set p ");
test("class a { constructor() { } static set p( ");
test("class a { constructor() { } static set p(v ");
test("class a { constructor() { } static set p(v) ");
test("class a { constructor() { } static set p(v) { ");
test("class a { constructor() { } static set p(v) {} ");
test("class a { constructor() { } static set p(v) {} } ");
test("class a { constructor() { } * ");
test("class a { constructor() { } *m ");
test("class a { constructor() { } *m( ");
test("class a { constructor() { } *m() ");
test("class a { constructor() { } *m() { ");
test("class a { constructor() { } *m() {} ");
test("class a { constructor() { } *m() {} } ");
test("class a { constructor() { } static * ");
test("class a { constructor() { } static *m ");
test("class a { constructor() { } static *m( ");
test("class a { constructor() { } static *m() ");
test("class a { constructor() { } static *m() { ");
test("class a { constructor() { } static *m() {} ");
test("class a { constructor() { } static *m() {} } ");
test("class a extends ");
test("class a extends b ");
test("class a extends b { ");
test("class a extends ( ");
test("class a extends ( b ");
test("class a extends ( b ) ");
test("class a extends ( b ) { ");
// ---- Class expression ----
test("( class ");
test("( class a ");
test("( class a { ");
test("( class a { constructor ");
test("( class a { constructor( ");
test("( class a { constructor() ");
test("( class a { constructor() { ");
test("( class a { constructor() { } ");
test("( class a { constructor() { } } ");
test("( class a { constructor() { } } ) ");
test("(class a extends ");
test("(class a extends b ");
test("(class a extends b { ");
test("(class a extends ( ");
test("(class a extends ( b ");
test("(class a extends ( b ) ");
test("(class a extends ( b ) { ");
test("( class { ");
test("( class { constructor ");
test("( class { constructor( ");
test("( class { constructor() ");
test("( class { constructor() { ");
test("( class { constructor() { } ");
test("( class { constructor() { } } ");
test("( class { constructor() { } } ) ");
test("(class extends ");
test("(class extends b ");
test("(class extends b { ");
test("(class extends ( ");
test("(class extends ( b ");
test("(class extends ( b ) ");
test("(class extends ( b ) { ");
// ---- Other ----
// Literals
test("a ");
test("1 ");
test("1. ");
test("1.2 ");
test("true ");
test("false ");
test("\"a\" ");
test("'a' ");
test("null ");
// Template strings
test("`${ ");
test("`${a ");
test("`${a}` ");
// Function calls
test("f( ");
test("f() ");
test("f(); ");
test("f(... ");
test("f(...x ");
test("f(...x) ");
// Function constructors
test_fun_arg("");
test_fun_arg("a ");
test_fun_arg("... ");
test_fun_arg("...a ");
// ==== Legacy ====
// ==== asm.js ====
test("(function() { 'use asm'; ");
test("(function() { 'use asm'; var ");
test("(function() { 'use asm'; var a ");
test("(function() { 'use asm'; var a = ");
test("(function() { 'use asm'; var a = 1 ");
test("(function() { 'use asm'; var a = 1; ");
test("(function() { 'use asm'; var a = 1; function ");
test("(function() { 'use asm'; var a = 1; function f ");
test("(function() { 'use asm'; var a = 1; function f( ");
test("(function() { 'use asm'; var a = 1; function f() ");
test("(function() { 'use asm'; var a = 1; function f() { ");
test("(function() { 'use asm'; var a = 1; function f() { } ");
test("(function() { 'use asm'; var a = 1; function f() { } var ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [ ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f] ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; return ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; return f ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; return f; ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; return f; } ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; return f; }) ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; return f; }); ");
// ==== async/await ====
// async/await function decralation
test("async ");
test("async function ");
test("async function A ");
test("async function A( ");
test("async function A() ");
test("async function A(a ");
test("async function A(a) ");
test("async function A(a) { ");
test("async function A(a) {} ");
test("async function A(a) { await ");
test("async function A(a) { await X ");
test("async function A(a) { await X; ");
test("async function A(a) { await X; } ");
test("async function A(a) { await await ");
test("async function A(a) { await await await ");
test("async function A(a) { await await await X ");
test("async function A(a) { await await await X; ");
test("async function A(a) { await await await X; } ");
opts = { no_fun: true, no_eval: true, module: true };
test("export default async ", opts);
test("export default async function ", opts);
test("export default async function ( ", opts);
test("export default async function () ", opts);
test("export default async function (a ", opts);
test("export default async function (a) ", opts);
test("export default async function (a) { ", opts);
test("export default async function (a) {} ", opts);
test("export default async function (a) { await ", opts);
test("export default async function (a) { await X ", opts);
test("export default async function (a) { await X; ", opts);
test("export default async function (a) { await X; } ", opts);
// async/await function expression
test("(async ");
test("(async function ");
test("(async function A ");
test("(async function A( ");
test("(async function A() ");
test("(async function A(a ");
test("(async function A(a) ");
test("(async function A(a) { ");
test("(async function A(a) {} ");
test("(async function A(a) { await ");
test("(async function A(a) { await X ");
test("(async function A(a) { await X; ");
test("(async function A(a) { await X; } ");
test("(async function A(a) { await X; }) ");
test("(async function ( ");
test("(async function () ");
test("(async function (a ");
test("(async function (a) ");
test("(async function (a) { ");
test("(async function (a) {} ");
test("(async function (a) { await ");
test("(async function (a) { await X ");
test("(async function (a) { await X; ");
test("(async function (a) { await X; } ");
test("(async function (a) { await X; }) ");
// async/await method
test("({ async ");
test("({ async m ");
test("({ async m( ");
test("({ async m() ");
test("({ async m() { ");
test("({ async m() {} ");
test("({ async m() {}, ");
test("class X { async ");
test("class X { async m ");
test("class X { async m( ");
test("class X { async m() ");
test("class X { async m() { ");
test("class X { async m() {} ");
test("class X { static async ");
test("class X { static async m ");
test("class X { static async m( ");
test("class X { static async m() ");
test("class X { static async m() { ");
test("class X { static async m() {} ");
// async/await arrow
test("(async a ");
test("(async a => ");
test("(async a => b ");
test("(async a => b) ");
test("(async a => { ");
test("(async a => { b ");
test("(async a => { b } ");
test("(async a => { b }) ");
test("(async ( ");
test("(async (a ");
test("(async (a) ");
test("(async (a) => ");
test("(async (a) => b ");
test("(async (a) => b) ");
test("(async (a, ");
test("(async (a, b ");
test("(async (a, b) ");
test("(async (a, b) => ");
test("(async (a, b) => b ");
test("(async (a, b) => b) ");
test("(async ([ ");
test("(async ([a ");
test("(async ([a] ");
test("(async ([a]) ");
test("(async ([a]) => ");
test("(async ([a]) => b ");
test("(async ([a]) => b) ");
test("(async ([a, ");
test("(async ([a, b ");
test("(async ([a, b] ");
test("(async ([a, b]) ");
test("(async ([a, b]) => ");
test("(async ([a, b]) => b ");
test("(async ([a, b]) => b) ");
test("(async ({ ");
test("(async ({a ");
test("(async ({a} ");
test("(async ({a}) ");
test("(async ({a}) => ");
test("(async ({a}) => b ");
test("(async ({a}) => b) ");
test("(async ({a, ");
test("(async ({a, b ");
test("(async ({a, b} ");
test("(async ({a, b}) ");
test("(async ({a, b}) => ");
test("(async ({a, b}) => b ");
test("(async ({a, b}) => b) ");
}
```
vs
```js
function test_syntax(postfixes, check_error, ignore_opts) {
function test_reflect(code, module) {
var options = undefined;
if (module) {
options = {
target: "module",
};
}
for (postfix of postfixes) {
var cur_code = code + postfix;
var caught = false;
try {
Reflect.parse(cur_code, options);
} catch (e) {
caught = true;
check_error(e, cur_code, "reflect");
}
assertEq(caught, true);
}
}
function test_eval(code) {
for (postfix of postfixes) {
var cur_code = code + postfix;
var caught = false;
try {
eval(cur_code);
} catch (e) {
caught = true;
check_error(e, cur_code, "eval");
}
assertEq(caught, true);
}
}
function test(code, opts = { }) {
if (ignore_opts) {
opts = { };
}
let no_strict = "no_strict" in opts && opts.no_strict;
let no_fun = "no_fun" in opts && opts.no_fun;
let no_eval = "no_eval" in opts && opts.no_eval;
let module = "module" in opts && opts.module;
test_reflect(code, module);
if (!no_strict) {
test_reflect("'use strict'; " + code, module);
}
if (!no_fun) {
test_reflect("(function() { " + code, module);
if (!no_strict) {
test_reflect("(function() { 'use strict'; " + code, module);
}
}
if (!no_eval) {
test_eval(code);
if (!no_strict) {
test_eval("'use strict'; " + code);
}
if (!no_fun) {
test_eval("(function() { " + code);
if (!no_strict) {
test_eval("(function() { 'use strict'; " + code);
}
}
}
}
function test_fun_arg(arg) {
for (postfix of postfixes) {
var cur_arg = arg + postfix;
var caught = false;
try {
new Function(cur_arg, "");
} catch (e) {
caught = true;
check_error(e, cur_arg, "fun_arg");
}
assertEq(caught, true);
}
}
test("{ ");
test("{ } ");
test("{ 1 ");
test("{ 1; ");
test("{ 1; } ");
test("a: for (;;) { break ");
test("a: for (;;) { break; ");
test("a: for (;;) { break a ");
test("a: for (;;) { break a; ");
test("a: for (;;) { break\n");
test("a: for (;;) { continue ");
test("a: for (;;) { continue; ");
test("a: for (;;) { continue a ");
test("a: for (;;) { continue a; ");
test("a: for (;;) { continue\n");
test("");
test("; ");
test("if ");
test("if (");
test("if (x ");
test("if (x) ");
test("if (x) { ");
test("if (x) {} ");
test("if (x) {} else ");
test("if (x) {} else { ");
test("if (x) {} else {} ");
test("if (x) x ");
test("if (x) x; ");
test("if (x) x; else ");
test("if (x) x; else y ");
test("if (x) x; else y; ");
test("switch ");
test("switch (");
test("switch (x ");
test("switch (x) ");
test("switch (x) { ");
test("switch (x) { case ");
test("switch (x) { case 1 ");
test("switch (x) { case 1: ");
test("switch (x) { case 1: case ");
test("switch (x) { case 1: case 2 ");
test("switch (x) { case 1: case 2: ");
test("switch (x) { case 1: case 2: x ");
test("switch (x) { case 1: case 2: x; ");
test("switch (x) { case 1: case 2: x; break ");
test("switch (x) { case 1: case 2: x; break; ");
test("switch (x) { case 1: case 2: x; break; case ");
test("switch (x) { case 1: case 2: x; break; case 3 ");
test("switch (x) { case 1: case 2: x; break; case 3: y ");
test("switch (x) { case 1: case 2: x; break; case 3: y; ");
test("switch (x) { case 1: case 2: x; break; case 3: y; default ");
test("switch (x) { case 1: case 2: x; break; case 3: y; default: ");
test("switch (x) { case 1: case 2: x; break; case 3: y; default: z ");
test("switch (x) { case 1: case 2: x; break; case 3: y; default: z; ");
test("switch (x) { case 1: case 2: x; break; case 3: y; default: z; } ");
test("throw ");
test("throw x ");
test("throw x; ");
test("try ");
test("try { ");
test("try {} ");
test("try {} catch ");
test("try {} catch ( ");
test("try {} catch (e ");
test("try {} catch (e) ");
test("try {} catch (e) { ");
test("try {} catch (e) {} ");
test("try {} catch (e) {} finally ");
test("try {} catch (e) {} finally { ");
test("try {} catch (e) {} finally {} ");
test("var ");
test("var x ");
test("var x = ");
test("var x = 1 ");
test("var x = 1 + ");
test("var x = 1 + 2 ");
test("var x = 1 + 2, ");
test("var x = 1 + 2, y ");
test("var x = 1 + 2, y, ");
test("var x = 1 + 2, y, z ");
test("var x = 1 + 2, y, z; ");
test("var [ ");
test("var [ x ");
test("var [ x, ");
test("var [ x, ... ");
test("var { ");
test("var { x ");
test("var { x: ");
test("var { x: y ");
test("var { x: y, ");
test("var { x: y } ");
test("var { x: y } = ");
test("let ");
test("let x ");
test("let x = ");
test("let x = 1 ");
test("let x = 1 + ");
test("let x = 1 + 2 ");
test("let x = 1 + 2, ");
test("let x = 1 + 2, y ");
test("let x = 1 + 2, y, ");
test("let x = 1 + 2, y, z ");
test("let x = 1 + 2, y, z; ");
test("let [ ");
test("let [ x ");
test("let [ x, ");
test("let [ x, ... ");
test("let { ");
test("let { x ");
test("let { x: ");
test("let { x: y ");
test("let { x: y, ");
test("let { x: y } ");
test("let { x: y } = ");
test("const ");
test("const x ");
test("const x = ");
test("const x = 1 ");
test("const x = 1 + ");
test("const x = 1 + 2 ");
test("const x = 1 + 2, ");
test("const x = 1 + 2, y = 0");
test("const x = 1 + 2, y = 0, ");
test("const x = 1 + 2, y = 0, z = 0 ");
test("const x = 1 + 2, y = 0, z = 0; ");
test("const [ ");
test("const [ x ");
test("const [ x, ");
test("const [ x, ... ");
test("const { ");
test("const { x ");
test("const { x: ");
test("const { x: y ");
test("const { x: y, ");
test("const { x: y } ");
test("const { x: y } = ");
test("function ");
test("function f ");
test("function f( ");
test("function f(x ");
test("function f(x, ");
test("function f(x, [ ");
test("function f(x, [y ");
test("function f(x, [y, ");
test("function f(x, [y, { ");
test("function f(x, [y, {z ");
test("function f(x, [y, {z: ");
test("function f(x, [y, {z: zz ");
test("function f(x, [y, {z: zz, ");
test("function f(x, [y, {z: zz, w ");
test("function f(x, [y, {z: zz, w} ");
test("function f(x, [y, {z: zz, w}] ");
test("function f(x, [y, {z: zz, w}], ");
test("function f(x, [y, {z: zz, w}], v ");
test("function f(x, [y, {z: zz, w}], v= ");
test("function f(x, [y, {z: zz, w}], v=1 ");
test("function f(x, [y, {z: zz, w}], v=1, ");
test("function f(x, [y, {z: zz, w}], v=1, ... ");
test("function f(x, [y, {z: zz, w}], v=1, ...t ");
test("function f(x, [y, {z: zz, w}], v=1, ...t) ");
test("function f(x, [y, {z: zz, w}], v=1, ...t) {");
test("function f(x, [y, {z: zz, w}], v=1, ...t) { x ");
test("function f(x, [y, {z: zz, w}], v=1, ...t) { x; ");
test("function f(x, [y, {z: zz, w}], v=1, ...t) { x; } ");
test("function* ");
test("function* f ");
test("function* f( ");
test("function* f(x ");
test("function* f(x, ");
test("function* f(x, ... ");
test("function* f(x, ...t ");
test("function* f(x, ...t) ");
test("function* f(x, ...t) {");
test("function* f(x, ...t) { x ");
test("function* f(x, ...t) { x; ");
test("function* f(x, ...t) { x; } ");
test("function f() { return ");
test("function f() { return 1 ");
test("function f() { return 1; ");
test("function f() { return 1; } ");
test("function f() { return; ");
test("function f() { return\n");
test("function* f() { yield ");
test("function* f() { yield 1 ");
test("function* f() { yield* ");
test("function* f() { yield* 1 ");
test("function* f() { yield\n");
test("function* f() { yield*\n");
test("do ");
test("do {");
test("do {} ");
test("do {} while ");
test("do {} while ( ");
test("do {} while (x ");
test("do {} while (x) ");
test("do {} while (x); ");
test("do x ");
test("do x; ");
test("do x; while ");
test("for ");
test("for (");
test("for (x ");
test("for (x; ");
test("for (x; y ");
test("for (x; y; ");
test("for (x; y; z ");
test("for (x; y; z) ");
test("for (x; y; z) { ");
test("for (x; y; z) {} ");
test("for (x; y; z) x ");
test("for (x; y; z) x; ");
test("for (var ");
test("for (var x ");
test("for (var x = ");
test("for (var x = y ");
test("for (var x = y; ");
test("for (let ");
test("for (let x ");
test("for (let x = ");
test("for (let x = y ");
test("for (let x = y; ");
test("for (x in ");
test("for (x in y ");
test("for (x in y) ");
test("for (var x in ");
test("for (var x in y ");
test("for (var x in y) ");
test("for (let x in ");
test("for (let x in y ");
test("for (let x in y) ");
test("for (x of ");
test("for (x of y ");
test("for (x of y) ");
test("for (var x of ");
test("for (var x of y ");
test("for (var x of y) ");
test("for (let x of ");
test("for (let x of y ");
test("for (let x of y) ");
test("while ");
test("while (");
test("while (x ");
test("while (x) ");
test("while (x) { ");
test("while (x) {} ");
test("while (x) x ");
test("while (x) x; ");
test("debugger ");
test("debugger; ");
var opts = {
no_fun: true,
no_eval: true,
module: true,
};
test("export ", opts);
test("export { ", opts);
test("export { x ", opts);
test("export { x, ", opts);
test("export { x, y ", opts);
test("export { x, y as ", opts);
test("export { x, y as z ", opts);
test("export { x, y as z } ", opts);
test("export { x, y as z } from ", opts);
test("export { x, y as z } from 'a' ", opts);
test("export { x, y as z } from 'a'; ", opts);
test("export * ", opts);
test("export * from ", opts);
test("export * from 'a' ", opts);
test("export * from 'a'; ", opts);
test("export function ", opts);
test("export function f ", opts);
test("export function f( ", opts);
test("export function f() ", opts);
test("export function f() { ", opts);
test("export function f() {} ", opts);
test("export function f() {}; ", opts);
test("export var ", opts);
test("export var a ", opts);
test("export var a = ", opts);
test("export var a = 1 ", opts);
test("export var a = 1, ", opts);
test("export var a = 1, b ", opts);
test("export var a = 1, b = ", opts);
test("export var a = 1, b = 2 ", opts);
test("export var a = 1, b = 2; ", opts);
test("export let ", opts);
test("export let a ", opts);
test("export let a = ", opts);
test("export let a = 1 ", opts);
test("export let a = 1, ", opts);
test("export let a = 1, b ", opts);
test("export let a = 1, b = ", opts);
test("export let a = 1, b = 2 ", opts);
test("export let a = 1, b = 2; ", opts);
test("export const ", opts);
test("export const a ", opts);
test("export const a = ", opts);
test("export const a = 1 ", opts);
test("export const a = 1, ", opts);
test("export const a = 1, b ", opts);
test("export const a = 1, b = ", opts);
test("export const a = 1, b = 2 ", opts);
test("export const a = 1, b = 2; ", opts);
test("export class ", opts);
test("export class Foo ", opts);
test("export class Foo { ", opts);
test("export class Foo { constructor ", opts);
test("export class Foo { constructor( ", opts);
test("export class Foo { constructor() ", opts);
test("export class Foo { constructor() { ", opts);
test("export class Foo { constructor() {} ", opts);
test("export class Foo { constructor() {} } ", opts);
test("export class Foo { constructor() {} }; ", opts);
test("export default ", opts);
test("export default 1 ", opts);
test("export default 1; ", opts);
test("export default function ", opts);
test("export default function() ", opts);
test("export default function() { ", opts);
test("export default function() {} ", opts);
test("export default function() {}; ", opts);
test("export default function foo ", opts);
test("export default function foo( ", opts);
test("export default function foo() ", opts);
test("export default function foo() { ", opts);
test("export default function foo() {} ", opts);
test("export default function foo() {}; ", opts);
test("export default class ", opts);
test("export default class { ", opts);
test("export default class { constructor ", opts);
test("export default class { constructor( ", opts);
test("export default class { constructor() ", opts);
test("export default class { constructor() { ", opts);
test("export default class { constructor() {} ", opts);
test("export default class { constructor() {} } ", opts);
test("export default class { constructor() {} }; ", opts);
test("export default class Foo ", opts);
test("export default class Foo { ", opts);
test("export default class Foo { constructor ", opts);
test("export default class Foo { constructor( ", opts);
test("export default class Foo { constructor() ", opts);
test("export default class Foo { constructor() { ", opts);
test("export default class Foo { constructor() {} ", opts);
test("export default class Foo { constructor() {} } ", opts);
test("export default class Foo { constructor() {} }; ", opts);
test("import ", opts);
test("import x ", opts);
test("import x from ", opts);
test("import x from 'a' ", opts);
test("import x from 'a'; ", opts);
test("import { ", opts);
test("import { x ", opts);
test("import { x, ", opts);
test("import { x, y ", opts);
test("import { x, y } ", opts);
test("import { x, y } from ", opts);
test("import { x, y } from 'a' ", opts);
test("import { x, y } from 'a'; ", opts);
test("import { x as ", opts);
test("import { x as y ", opts);
test("import { x as y } ", opts);
test("import { x as y } from ", opts);
test("import { x as y } from 'a' ", opts);
test("import { x as y } from 'a'; ", opts);
test("import 'a' ", opts);
test("import 'a'; ", opts);
test("import * ", opts);
test("import * as ", opts);
test("import * as a ", opts);
test("import * as a from ", opts);
test("import * as a from 'a' ", opts);
test("import * as a from 'a'; ", opts);
test("import a ", opts);
test("import a, ", opts);
test("import a, * ", opts);
test("import a, * as ", opts);
test("import a, * as b ", opts);
test("import a, * as b from ", opts);
test("import a, * as b from 'c' ", opts);
test("import a, * as b from 'c'; ", opts);
test("import a, { ", opts);
test("import a, { b ", opts);
test("import a, { b } ", opts);
test("import a, { b } from ", opts);
test("import a, { b } from 'c' ", opts);
test("import a, { b } from 'c'; ", opts);
test("a ");
test("a: ");
opts = {
no_strict: true,
};
test("with ", opts);
test("with (", opts);
test("with (x ", opts);
test("with (x) ", opts);
test("with (x) { ", opts);
test("with (x) {} ", opts);
test("with (x) x ", opts);
test("with (x) x; ", opts);
test("this ");
test("(function ");
test("(function ( ");
test("(function (x ");
test("(function (x, ");
test("(function (x, ... ");
test("(function (x, ...t ");
test("(function (x, ...t) ");
test("(function (x, ...t) {");
test("(function (x, ...t) { x ");
test("(function (x, ...t) { x; ");
test("(function (x, ...t) { x; } ");
test("(function (x, ...t) { x; }) ");
test("(function* ");
test("(function* ( ");
test("(function* (x ");
test("(function* (x, ");
test("(function* (x, ... ");
test("(function* (x, ...t ");
test("(function* (x, ...t) ");
test("(function* (x, ...t) {");
test("(function* (x, ...t) { x ");
test("(function* (x, ...t) { x; ");
test("(function* (x, ...t) { x; } ");
test("(function* (x, ...t) { x; }) ");
test("[ ");
test("[] ");
test("[1 ");
test("[1, ");
test("[1, ... ");
test("[1, ...x ");
test("[1, ...x] ");
test("({ ");
test("({ x ");
test("({ x: ");
test("({ x: 1 ");
test("({ x: 1, ");
test("({ x: 1, y ");
test("({ x: 1, y: ");
test("({ x: 1, y: 2 ");
test("({ x: 1, y: 2, ");
test("({ x: 1, y: 2, z ");
test("({ x: 1, y: 2, z, ");
test("({ x: 1, y: 2, z, w ");
test("({ x: 1, y: 2, z, w } ");
test("({ x: 1, y: 2, z, w }) ");
test("({ [");
test("({ [k ");
test("({ [k] ");
test("({ [k]: ");
test("({ [k]: 1 ");
test("({ [k]: 1, ");
test("({ get ");
test("({ get p ");
test("({ get p( ");
test("({ get p() ");
test("({ get p() { ");
test("({ get p() {} ");
test("({ get p() {}, ");
test("({ get p() {}, } ");
test("({ get [ ");
test("({ get [p ");
test("({ get [p] ");
test("({ get [p]( ");
test("({ get [p]() ");
test("({ set ");
test("({ set p ");
test("({ set p( ");
test("({ set p(v ");
test("({ set p(v) ");
test("({ set p(v) { ");
test("({ set p(v) {} ");
test("({ set [ ");
test("({ set [p ");
test("({ set [p] ");
test("({ set [p]( ");
test("({ set [p](v ");
test("({ set [p](v) ");
test("({ m ");
test("({ m( ");
test("({ m() ");
test("({ m() { ");
test("({ m() {} ");
test("({ m() {}, ");
test("({ [ ");
test("({ [m ");
test("({ [m] ");
test("({ [m]( ");
test("({ [m]() ");
test("({ [m]() { ");
test("({ [m]() {} ");
test("({ [m]() {}, ");
test("({ * ");
test("({ *m ");
test("({ *m( ");
test("({ *m() ");
test("({ *m() { ");
test("({ *m() {} ");
test("({ *m() {}, ");
test("({ *[ ");
test("({ *[m ");
test("({ *[m] ");
test("({ *[m]( ");
test("({ *[m]() ");
test("({ *[m]() { ");
test("({ *[m]() {} ");
test("({ *[m]() {}, ");
test("({ * get ");
test("({ * get ( ");
test("({ * get () ");
test("({ * get () { ");
test("({ * get () {} ");
test("({ * get () {}, ");
test("({ * set ");
test("({ * set ( ");
test("({ * set () ");
test("({ * set () { ");
test("({ * set () {} ");
test("({ * set () {}, ");
test("/a/ ");
test("/a/g ");
test("a[ ");
test("a[1 ");
test("a[1] ");
test("a. ");
test("a.b ");
test("a.b; ");
test("new ");
test("new f ");
test("new f( ");
test("new f() ");
test("new f(); ");
test("a ++ ");
test("a ++; ");
test("-- ");
test("-- a ");
test("-- a; ");
test("delete ");
test("delete a ");
test("delete a[ ");
test("delete a[b ");
test("delete a[b] ");
test("delete a[b]; ");
test("delete ( ");
test("delete (a ");
test("delete (a[ ");
test("delete (a[b ");
test("delete (a[b] ");
test("delete (a[b]) ");
test("delete (a[b]); ");
test("void ");
test("void a ");
test("void a; ");
test("void (");
test("void (a ");
test("void (a) ");
test("void (a); ");
test("typeof ");
test("typeof a ");
test("typeof a; ");
test("typeof (");
test("typeof (a ");
test("typeof (a) ");
test("typeof (a); ");
test("- ");
test("- 1 ");
test("- 1; ");
test("+ ");
test("+ 1 ");
test("+ 1; ");
test("1 + ");
test("1 + 1 ");
test("1 + 1; ");
test("a in ");
test("a in b ");
test("a in b; ");
test("a instanceof ");
test("a instanceof b ");
test("a instanceof b; ");
test("1 == ");
test("1 == 1 ");
test("1 == 1; ");
test("1 << ");
test("1 << 1 ");
test("1 << 1; ");
test("1 & ");
test("1 & 1 ");
test("1 & 1; ");
test("1 || ");
test("1 || 1 ");
test("1 || 1; ");
test("1 ? ");
test("1 ? 2 ");
test("1 ? 2 : ");
test("1 ? 2 : 3 ");
test("1 ? 2 : 3; ");
test("x = ");
test("x = 1 ");
test("x = 1 + ");
test("x = 1 + 2 ");
test("x = 1 + 2; ");
test("1, ");
test("1, 2 ");
test("1, 2; ");
test("a => ");
test("a => 1 ");
test("a => 1; ");
test("a => { ");
test("a => {} ");
test("a => {}; ");
test("( ");
test("() ");
test("() => ");
test("(...");
test("(...a ");
test("(...a) ");
test("(...a) => ");
test("([ ");
test("([a ");
test("([a] ");
test("([a]) ");
test("([a]) => ");
test("({ ");
test("({a ");
test("({a} ");
test("({a}) ");
test("({a}) => ");
test("({a: ");
test("({a: b ");
test("({a: b, ");
test("({a: b} ");
test("({a: b}) ");
test("({a: b}) => ");
test("class ");
test("class a ");
test("class a { ");
test("class a { constructor ");
test("class a { constructor( ");
test("class a { constructor() ");
test("class a { constructor() { ");
test("class a { constructor() { } ");
test("class a { constructor() { } } ");
test("class a { constructor() { } static ");
test("class a { constructor() { } static m ");
test("class a { constructor() { } static m( ");
test("class a { constructor() { } static m() ");
test("class a { constructor() { } static m() { ");
test("class a { constructor() { } static m() {} ");
test("class a { constructor() { } static m() {} } ");
test("class a { constructor() { } static ( ");
test("class a { constructor() { } static () ");
test("class a { constructor() { } static () { ");
test("class a { constructor() { } static () {} ");
test("class a { constructor() { } static () {} } ");
test("class a { constructor() { } static get ");
test("class a { constructor() { } static get p ");
test("class a { constructor() { } static get p( ");
test("class a { constructor() { } static get p() ");
test("class a { constructor() { } static get p() { ");
test("class a { constructor() { } static get p() {} ");
test("class a { constructor() { } static get p() {} } ");
test("class a { constructor() { } static set ");
test("class a { constructor() { } static set p ");
test("class a { constructor() { } static set p( ");
test("class a { constructor() { } static set p(v ");
test("class a { constructor() { } static set p(v) ");
test("class a { constructor() { } static set p(v) { ");
test("class a { constructor() { } static set p(v) {} ");
test("class a { constructor() { } static set p(v) {} } ");
test("class a { constructor() { } * ");
test("class a { constructor() { } *m ");
test("class a { constructor() { } *m( ");
test("class a { constructor() { } *m() ");
test("class a { constructor() { } *m() { ");
test("class a { constructor() { } *m() {} ");
test("class a { constructor() { } *m() {} } ");
test("class a { constructor() { } static * ");
test("class a { constructor() { } static *m ");
test("class a { constructor() { } static *m( ");
test("class a { constructor() { } static *m() ");
test("class a { constructor() { } static *m() { ");
test("class a { constructor() { } static *m() {} ");
test("class a { constructor() { } static *m() {} } ");
test("class a extends ");
test("class a extends b ");
test("class a extends b { ");
test("class a extends ( ");
test("class a extends ( b ");
test("class a extends ( b ) ");
test("class a extends ( b ) { ");
test("( class ");
test("( class a ");
test("( class a { ");
test("( class a { constructor ");
test("( class a { constructor( ");
test("( class a { constructor() ");
test("( class a { constructor() { ");
test("( class a { constructor() { } ");
test("( class a { constructor() { } } ");
test("( class a { constructor() { } } ) ");
test("(class a extends ");
test("(class a extends b ");
test("(class a extends b { ");
test("(class a extends ( ");
test("(class a extends ( b ");
test("(class a extends ( b ) ");
test("(class a extends ( b ) { ");
test("( class { ");
test("( class { constructor ");
test("( class { constructor( ");
test("( class { constructor() ");
test("( class { constructor() { ");
test("( class { constructor() { } ");
test("( class { constructor() { } } ");
test("( class { constructor() { } } ) ");
test("(class extends ");
test("(class extends b ");
test("(class extends b { ");
test("(class extends ( ");
test("(class extends ( b ");
test("(class extends ( b ) ");
test("(class extends ( b ) { ");
test("a ");
test("1 ");
test("1. ");
test("1.2 ");
test("true ");
test("false ");
test("\"a\" ");
test("'a' ");
test("null ");
test("`${ ");
test("`${a ");
test("`${a}` ");
test("f( ");
test("f() ");
test("f(); ");
test("f(... ");
test("f(...x ");
test("f(...x) ");
test_fun_arg("");
test_fun_arg("a ");
test_fun_arg("... ");
test_fun_arg("...a ");
test("(function() { 'use asm'; ");
test("(function() { 'use asm'; var ");
test("(function() { 'use asm'; var a ");
test("(function() { 'use asm'; var a = ");
test("(function() { 'use asm'; var a = 1 ");
test("(function() { 'use asm'; var a = 1; ");
test("(function() { 'use asm'; var a = 1; function ");
test("(function() { 'use asm'; var a = 1; function f ");
test("(function() { 'use asm'; var a = 1; function f( ");
test("(function() { 'use asm'; var a = 1; function f() ");
test("(function() { 'use asm'; var a = 1; function f() { ");
test("(function() { 'use asm'; var a = 1; function f() { } ");
test("(function() { 'use asm'; var a = 1; function f() { } var ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [ ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f] ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; return ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; return f ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; return f; ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; return f; } ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; return f; }) ");
test("(function() { 'use asm'; var a = 1; function f() { } var tbl = [f]; return f; }); ");
test("async ");
test("async function ");
test("async function A ");
test("async function A( ");
test("async function A() ");
test("async function A(a ");
test("async function A(a) ");
test("async function A(a) { ");
test("async function A(a) {} ");
test("async function A(a) { await ");
test("async function A(a) { await X ");
test("async function A(a) { await X; ");
test("async function A(a) { await X; } ");
test("async function A(a) { await await ");
test("async function A(a) { await await await ");
test("async function A(a) { await await await X ");
test("async function A(a) { await await await X; ");
test("async function A(a) { await await await X; } ");
opts = {
no_fun: true,
no_eval: true,
module: true,
};
test("export default async ", opts);
test("export default async function ", opts);
test("export default async function ( ", opts);
test("export default async function () ", opts);
test("export default async function (a ", opts);
test("export default async function (a) ", opts);
test("export default async function (a) { ", opts);
test("export default async function (a) {} ", opts);
test("export default async function (a) { await ", opts);
test("export default async function (a) { await X ", opts);
test("export default async function (a) { await X; ", opts);
test("export default async function (a) { await X; } ", opts);
test("(async ");
test("(async function ");
test("(async function A ");
test("(async function A( ");
test("(async function A() ");
test("(async function A(a ");
test("(async function A(a) ");
test("(async function A(a) { ");
test("(async function A(a) {} ");
test("(async function A(a) { await ");
test("(async function A(a) { await X ");
test("(async function A(a) { await X; ");
test("(async function A(a) { await X; } ");
test("(async function A(a) { await X; }) ");
test("(async function ( ");
test("(async function () ");
test("(async function (a ");
test("(async function (a) ");
test("(async function (a) { ");
test("(async function (a) {} ");
test("(async function (a) { await ");
test("(async function (a) { await X ");
test("(async function (a) { await X; ");
test("(async function (a) { await X; } ");
test("(async function (a) { await X; }) ");
test("({ async ");
test("({ async m ");
test("({ async m( ");
test("({ async m() ");
test("({ async m() { ");
test("({ async m() {} ");
test("({ async m() {}, ");
test("class X { async ");
test("class X { async m ");
test("class X { async m( ");
test("class X { async m() ");
test("class X { async m() { ");
test("class X { async m() {} ");
test("class X { static async ");
test("class X { static async m ");
test("class X { static async m( ");
test("class X { static async m() ");
test("class X { static async m() { ");
test("class X { static async m() {} ");
test("(async a ");
test("(async a => ");
test("(async a => b ");
test("(async a => b) ");
test("(async a => { ");
test("(async a => { b ");
test("(async a => { b } ");
test("(async a => { b }) ");
test("(async ( ");
test("(async (a ");
test("(async (a) ");
test("(async (a) => ");
test("(async (a) => b ");
test("(async (a) => b) ");
test("(async (a, ");
test("(async (a, b ");
test("(async (a, b) ");
test("(async (a, b) => ");
test("(async (a, b) => b ");
test("(async (a, b) => b) ");
test("(async ([ ");
test("(async ([a ");
test("(async ([a] ");
test("(async ([a]) ");
test("(async ([a]) => ");
test("(async ([a]) => b ");
test("(async ([a]) => b) ");
test("(async ([a, ");
test("(async ([a, b ");
test("(async ([a, b] ");
test("(async ([a, b]) ");
test("(async ([a, b]) => ");
test("(async ([a, b]) => b ");
test("(async ([a, b]) => b) ");
test("(async ({ ");
test("(async ({a ");
test("(async ({a} ");
test("(async ({a}) ");
test("(async ({a}) => ");
test("(async ({a}) => b ");
test("(async ({a}) => b) ");
test("(async ({a, ");
test("(async ({a, b ");
test("(async ({a, b} ");
test("(async ({a, b}) ");
test("(async ({a, b}) => ");
test("(async ({a, b}) => b ");
test("(async ({a, b}) => b) ");
}
```
<details>
```js
// Map iterators produces entries in the order they were inserted.
load(libdir + "eqArrayHelper.js");
var map = new Map();
for (var i = 7; i !== 1; i = i * 7 % 1117)
map.set("" + i, i);
assertEq(map.size, 557);
i = 7;
for (var pair of map) {
assertEqArray(pair, ["" + i, i]);
i = i * 7 % 1117;
}
assertEq(i, 1);
```
vs
```js
load(libdir + "eqArrayHelper.js");
var map = new Map();
for (let i = 7;i !== 1;i = i * 7 % 1117) map.set("" + i, i);
assertEq(map.size, 557);
i = 7;
for (pair of map) {
assertEqArray(pair, ["" + i, i,]);
i = i * 7 % 1117;
}
assertEq(i, 1);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-iterator-order.js)
<details>
```js
// Array.prototype.iterator applied to undefined or null throws directly.
load(libdir + "asserts.js");
load(libdir + "iteration.js");
for (var v of [undefined, null]) {
// ES6 draft 2013-09-05 section 22.1.5.1.
assertThrowsInstanceOf(function () { Array.prototype[Symbol.iterator].call(v); }, TypeError);
assertThrowsInstanceOf(function () { Array.prototype.keys.call(v); }, TypeError);
assertThrowsInstanceOf(function () { Array.prototype.entries.call(v); }, TypeError);
}
```
vs
```js
load(libdir + "asserts.js");
load(libdir + "iteration.js");
for (v of [undefined, null,]) {
assertThrowsInstanceOf(function() {
Array.prototype[Symbol.iterator].call(v);
}, TypeError);
assertThrowsInstanceOf(function() {
Array.prototype.keys.call(v);
}, TypeError);
assertThrowsInstanceOf(function() {
Array.prototype.entries.call(v);
}, TypeError);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/array-iterator-null.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/lib/syntax.js)
<details>
```js
load(libdir + 'asserts.js');
function test() {
let a = ctypes.int32_t.array(10)();
assertTypeErrorMessage(() => { let x = a[-1]; },
"the string \"-1\" is not a valid array index");
assertTypeErrorMessage(() => { a[-1] = 1; },
"the string \"-1\" is not a valid array index");
assertTypeErrorMessage(() => { a.addressOfElement(-1); },
"the number -1 is not a valid array index");
assertRangeErrorMessage(() => { let x = a[10]; },
"array index 10 is out of bounds for array of length 10");
assertRangeErrorMessage(() => { a[10] = 1; },
"array index 10 is out of bounds for array of length 10");
assertRangeErrorMessage(() => { a.addressOfElement(10); },
"array index 10 is out of bounds for array of length 10");
let obj = {
toSource() {
throw 1;
}
};
assertTypeErrorMessage(() => { a.addressOfElement(obj); },
"<<error converting value to string>> is not a valid array index");
}
if (typeof ctypes === "object")
test();
```
vs
```js
load(libdir + 'asserts.js');
function test() {
let a = ctypes.int32_t.array(10)();
assertTypeErrorMessage(() => {
let x = a[-1];
}, "the string \"-1\" is not a valid array index");
assertTypeErrorMessage(() => {
a[-1] = 1;
}, "the string \"-1\" is not a valid array index");
assertTypeErrorMessage(() => {
a.addressOfElement(-1);
}, "the number -1 is not a valid array index");
assertRangeErrorMessage(() => {
let x = a[10];
}, "array index 10 is out of bounds for array of length 10");
assertRangeErrorMessage(() => {
a[10] = 1;
}, "array index 10 is out of bounds for array of length 10");
assertRangeErrorMessage(() => {
a.addressOfElement(10);
}, "array index 10 is out of bounds for array of length 10");
let obj = {
toSource: function() {
throw 1;
},
};
assertTypeErrorMessage(() => {
a.addressOfElement(obj);
}, "<<error converting value to string>> is not a valid array index");
}
if (typeof ctypes === "object") test();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ctypes/array-index.js)
<details>
```js
// Clearing a Set removes its elements; the Set remains usable afterwards.
var s = new Set(["x", "y", "z", "z", "y"]);
assertEq(s.size, 3);
s.clear();
assertEq(s.size, 0);
assertEq(s.has("x"), false);
assertEq(s.delete("x"), false);
assertEq(s.has("z"), false);
for (var v of s)
throw "FAIL"; // shouldn't be any elements
s.add("y");
assertEq(s.size, 1);
assertEq(s.has("x"), false);
assertEq(s.has("z"), false);
```
vs
```js
var s = new Set(["x", "y", "z", "z", "y",]);
assertEq(s.size, 3);
s.clear();
assertEq(s.size, 0);
assertEq(s.has("x"), false);
assertEq(s.delete("x"), false);
assertEq(s.has("z"), false);
for (v of s) throw "FAIL";
s.add("y");
assertEq(s.size, 1);
assertEq(s.has("x"), false);
assertEq(s.has("z"), false);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-clear-2.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
setJitCompilerOption("ion.warmup.trigger", 30);
var PointType = TypedObject.uint32.array(3);
var VecPointType = PointType.array(3);
function foo() {
for (var i = 0; i < 5000; i += 10) {
var vec = new VecPointType();
var i0 = i % 3;
var i1 = (i+1) % 3;
var i2 = (i+2) % 3;
vec[i0][i0] = i;
vec[i0][i1] = i+1;
vec[i0][i2] = i+2;
vec[i1][i0] = i+3;
vec[i1][i1] = i+4;
vec[i1][i2] = i+5;
vec[i2][i0] = i+6;
vec[i2][i1] = i+7;
vec[i2][i2] = i+8;
var sum = vec[i0][i0] + vec[i0][i1] + vec[i0][i2];
assertEq(sum, 3*i + 3);
sum = vec[i1][i0] + vec[i1][i1] + vec[i1][i2];
assertEq(sum, 3*i + 12);
sum = vec[i2][i0] + vec[i2][i1] + vec[i2][i2];
assertEq(sum, 3*i + 21);
}
}
foo();
```
vs
```js
setJitCompilerOption("ion.warmup.trigger", 30);
var PointType = TypedObject.uint32.array(3);
var VecPointType = PointType.array(3);
function foo() {
for (let i = 0;i < 5000;i += 10) {
var vec = new VecPointType();
var i0 = i % 3;
var i1 = i + 1 % 3;
var i2 = i + 2 % 3;
vec[i0][i0] = i;
vec[i0][i1] = i + 1;
vec[i0][i2] = i + 2;
vec[i1][i0] = i + 3;
vec[i1][i1] = i + 4;
vec[i1][i2] = i + 5;
vec[i2][i0] = i + 6;
vec[i2][i1] = i + 7;
vec[i2][i2] = i + 8;
var sum = vec[i0][i0] + vec[i0][i1] + vec[i0][i2];
assertEq(sum, 3 * i + 3);
sum = vec[i1][i0] + vec[i1][i1] + vec[i1][i2];
assertEq(sum, 3 * i + 12);
sum = vec[i2][i0] + vec[i2][i1] + vec[i2][i2];
assertEq(sum, 3 * i + 21);
}
}
foo();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/TypedObject/jit-write-u32-into-mdim-array.js)
<details>
```js
// An unmapped arguments object is created for strict functions or functions
// with default/rest/destructuring args.
load(libdir + "asserts.js");
function testDefaults(a, b=3) {
a = 3;
b = 4;
assertEq(arguments.length, 1);
assertEq(arguments[0], 1);
assertEq(arguments[1], undefined);
arguments[0] = 5;
assertEq(a, 3);
assertThrowsInstanceOf(() => arguments.callee, TypeError);
}
testDefaults(1);
function testRest(a, ...rest) {
a = 3;
assertEq(arguments.length, 3);
assertEq(arguments[0], 1);
assertEq(arguments[1], 2);
arguments[0] = 5;
assertEq(a, 3);
arguments[1] = 6;
assertEq(arguments[1], 6);
assertEq(rest.toString(), "2,3");
assertThrowsInstanceOf(() => arguments.callee, TypeError);
}
testRest(1, 2, 3);
function testDestructuring(a, {foo, bar}, b) {
a = 3;
bar = 4;
b = 1;
assertEq(arguments.length, 3);
assertEq(arguments[0], 1);
assertEq(arguments[1].bar, 2);
assertEq(arguments[2], 9);
assertThrowsInstanceOf(() => arguments.callee, TypeError);
}
testDestructuring(1, {foo: 1, bar: 2}, 9);
function testStrict(a) {
"use strict";
a = 3;
assertEq(arguments[0], 1);
arguments[0] = 8;
assertEq(a, 3);
assertThrowsInstanceOf(() => arguments.callee, TypeError);
}
testStrict(1, 2);
function testMapped(a) {
a = 3;
assertEq(arguments[0], 3);
arguments[0] = 5;
assertEq(a, 5);
assertEq(arguments.callee, testMapped);
}
testMapped(1);
```
vs
```js
load(libdir + "asserts.js");
function testDefaults(a, b = 3) {
a = 3;
b = 4;
assertEq(arguments.length, 1);
assertEq(arguments[0], 1);
assertEq(arguments[1], undefined);
arguments[0] = 5;
assertEq(a, 3);
assertThrowsInstanceOf(() => arguments.callee, TypeError);
}
testDefaults(1);
function testRest(a, rest) {
a = 3;
assertEq(arguments.length, 3);
assertEq(arguments[0], 1);
assertEq(arguments[1], 2);
arguments[0] = 5;
assertEq(a, 3);
arguments[1] = 6;
assertEq(arguments[1], 6);
assertEq(rest.toString(), "2,3");
assertThrowsInstanceOf(() => arguments.callee, TypeError);
}
testRest(1, 2, 3);
function testDestructuring(a, {foo, bar,}, b) {
a = 3;
bar = 4;
b = 1;
assertEq(arguments.length, 3);
assertEq(arguments[0], 1);
assertEq(arguments[1].bar, 2);
assertEq(arguments[2], 9);
assertThrowsInstanceOf(() => arguments.callee, TypeError);
}
testDestructuring(1, ({
foo: 1,
bar: 2,
}), 9);
function testStrict(a) {
'use strict';
a = 3;
assertEq(arguments[0], 1);
arguments[0] = 8;
assertEq(a, 3);
assertThrowsInstanceOf(() => arguments.callee, TypeError);
}
testStrict(1, 2);
function testMapped(a) {
a = 3;
assertEq(arguments[0], 3);
arguments[0] = 5;
assertEq(a, 5);
assertEq(arguments.callee, testMapped);
}
testMapped(1);
```
<details>
```js
var SECTION = "";
var VERSION = "";
function test() {}
function writeTestCaseResult( expect, actual, string ) {
if (typeof document != "object" ||
!document.location.href.match(/jsreftest.html/)) {
}
}
TIME_0000 = now = new Date;
TIME_NOW = now.valueOf();
function DaysInYear( y ) {
function MakeDate( day, time ) {
}
}
function TimeClip( t ) {
if ( isNaN ) { Number.NaN; }
}
function runDSTOffsetCachingTestsFraction(part, parts) { print; };
test_times=( TIME_NOW, TIME_0000, ( SECTION, VERSION+".getUTCMinutes()",
TIME_NOW.test_times,VERSION.SECTION ) , TIME_0000, TIME_0000,
0, 0 );
try { j = 0( SECTION, TimeClip(1.1), 0 ); } catch (e) {}
```
vs
```js
var SECTION = "";
var VERSION = "";
function test() { }
function writeTestCaseResult(expect, actual, string) {
if (typeof document != "object" || !document.location.href.match(/jsreftest.html/)) {
}
}
TIME_0000 = now = new Date();
TIME_NOW = now.valueOf();
function DaysInYear(y) {
function MakeDate(day, time) { }
}
function TimeClip(t) {
if (isNaN) {
Number.NaN;
}
}
function runDSTOffsetCachingTestsFraction(part, parts) {
print;
}
;
test_times = TIME_NOW, TIME_0000, SECTION, VERSION + ".getUTCMinutes()", TIME_NOW.test_times, VERSION.SECTION, TIME_0000, TIME_0000, 0, 0;
try {
j = 0(SECTION, TimeClip(1.1), 0);
} catch (e) {
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/mapped-unmapped-args.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug647183.js)
<details>
```js
// The Great Computer Language Shootout
// http://shootout.alioth.debian.org/
//
// contributed by Ian Osgood
function A(i,j) {
return 1/((i+j)*(i+j+1)/2+i+1);
}
function Au(u,v) {
for (var i=0; i<u.length; ++i) {
var t = 0;
for (var j=0; j<u.length; ++j)
t += A(i,j) * u[j];
v[i] = t;
}
}
function Atu(u,v) {
for (var i=0; i<u.length; ++i) {
var t = 0;
for (var j=0; j<u.length; ++j)
t += A(j,i) * u[j];
v[i] = t;
}
}
function AtAu(u,v,w) {
Au(u,w);
Atu(w,v);
}
function spectralnorm(n) {
var i, u=[], v=[], w=[], vv=0, vBv=0;
for (i=0; i<n; ++i) {
u[i] = 1; v[i] = w[i] = 0;
}
for (i=0; i<10; ++i) {
AtAu(u,v,w);
AtAu(v,u,w);
}
for (i=0; i<n; ++i) {
vBv += u[i]*v[i];
vv += v[i]*v[i];
}
return Math.sqrt(vBv/vv);
}
var actual = '';
for (var i = 6; i <= 48; i *= 2) {
actual += spectralnorm(i) + ',';
}
assertEq(actual, "1.2657786149754053,1.2727355112619148,1.273989979775574,1.274190125290389,");
```
vs
```js
function A(i, j) {
return 1 / i + j * i + j + 1 / 2 + i + 1;
}
function Au(u, v) {
for (let i = 0;i < u.length;++i) {
var t = 0;
for (let j = 0;j < u.length;++j) t += A(i, j) * u[j];
v[i] = t;
}
}
function Atu(u, v) {
for (let i = 0;i < u.length;++i) {
var t = 0;
for (let j = 0;j < u.length;++j) t += A(j, i) * u[j];
v[i] = t;
}
}
function AtAu(u, v, w) {
Au(u, w);
Atu(w, v);
}
function spectralnorm(n) {
var i, u = [], v = [], w = [], vv = 0, vBv = 0;
for (i = 0;i < n;++i) {
u[i] = 1;
v[i] = w[i] = 0;
}
for (i = 0;i < 10;++i) {
AtAu(u, v, w);
AtAu(v, u, w);
}
for (i = 0;i < n;++i) {
vBv += u[i] * v[i];
vv += v[i] * v[i];
}
return Math.sqrt(vBv / vv);
}
var actual = '';
for (let i = 6;i <= 48;i *= 2) {
actual += spectralnorm(i) + ',';
}
assertEq(actual, "1.2657786149754053,1.2727355112619148,1.273989979775574,1.274190125290389,");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-math-spectral-norm.js)
<details>
```js
function f(x, y) {
-(undefined ? 0 : 0);
assertEq(y === y, true);
return 0;
}
f(1, 2);
{
f(3, 3.14);
f(true, f(4, 5));
function g() {}
}
```
vs
```js
function f(x, y) {
-undefined ? 0 : 0;
assertEq(y === y, true);
return 0;
}
f(1, 2);
{
f(3, 3.14);
f(true, f(4, 5));
function g() { }
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug648502.js)
<details>
```js
// Test that we can track allocation sites by setting
// Debugger.Memory.prototype.trackingAllocationSites to true and then get the
// allocation site via Debugger.Object.prototype.allocationSite.
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root);
assertEq(dbg.memory.trackingAllocationSites, false);
dbg.memory.trackingAllocationSites = true;
assertEq(dbg.memory.trackingAllocationSites, true);
root.eval("(" + function immediate() {
this.tests = [
{ name: "object literal", object: ({}), line: Error().lineNumber },
{ name: "array literal", object: [], line: Error().lineNumber },
{ name: "regexp literal", object: /(two|2)\s*problems/, line: Error().lineNumber },
{ name: "new constructor", object: new function Ctor(){}, line: Error().lineNumber },
{ name: "new Object", object: new Object(), line: Error().lineNumber },
{ name: "new Array", object: new Array(), line: Error().lineNumber },
{ name: "new Date", object: new Date(), line: Error().lineNumber }
];
} + "());");
dbg.memory.trackingAllocationSites = false;
assertEq(dbg.memory.trackingAllocationSites, false);
for (let { name, object, line } of root.tests) {
print("Entering test: " + name);
let wrappedObject = wrappedRoot.makeDebuggeeValue(object);
let allocationSite = wrappedObject.allocationSite;
print("Allocation site: " + allocationSite);
assertEq(allocationSite.line, line);
}
```
vs
```js
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root);
assertEq(dbg.memory.trackingAllocationSites, false);
dbg.memory.trackingAllocationSites = true;
assertEq(dbg.memory.trackingAllocationSites, true);
root.eval("(" + (function immediate() {
this.tests = [{
name: "object literal",
object: { },
line: Error().lineNumber,
}, {
name: "array literal",
object: [],
line: Error().lineNumber,
}, {
name: "regexp literal",
object: /(two|2)\s*problems/,
line: Error().lineNumber,
}, {
name: "new constructor",
object: new function Ctor() { }(),
line: Error().lineNumber,
}, {
name: "new Object",
object: new Object(),
line: Error().lineNumber,
}, {
name: "new Array",
object: new Array(),
line: Error().lineNumber,
}, {
name: "new Date",
object: new Date(),
line: Error().lineNumber,
},];
}) + "());");
dbg.memory.trackingAllocationSites = false;
assertEq(dbg.memory.trackingAllocationSites, false);
for ({name, object, line,} of root.tests) {
print("Entering test: " + name);
let wrappedObject = wrappedRoot.makeDebuggeeValue(object);
let allocationSite = wrappedObject.allocationSite;
print("Allocation site: " + allocationSite);
assertEq(allocationSite.line, line);
}
```
<details>
```js
// TDZ checks work in destructuring default expressions,
// even after the variables are initialized the first time.
load(libdir + "asserts.js");
assertThrowsInstanceOf(() => {
// should throw the second time through: b is uninitialized
for (const {a=b, b} of [{a:1, b:2}, {b:3}]) {}
}, ReferenceError);
```
vs
```js
load(libdir + "asserts.js");
assertThrowsInstanceOf(() => {
for ({a, b, } of [{
a: 1,
b: 2,
}, {
b: 3,
},]) {
}
}, ReferenceError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Memory-trackingAllocationSites-01.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-51.js)
<details>
```js
// for-of can iterate strict arguments objects.
load(libdir + "iteration.js");
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var s;
function test() {
"use strict";
for (var v of arguments)
s += v;
}
s = '';
test();
assertEq(s, '');
s = '';
test('a', 'b');
assertEq(s, 'ab');
```
vs
```js
load(libdir + "iteration.js");
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var s;
function test() {
'use strict';
for (v of arguments) s += v;
}
s = '';
test();
assertEq(s, '');
s = '';
test('a', 'b');
assertEq(s, 'ab');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arguments-3.js)
<details>
```js
// Removing a Set entry already visited by an iterator does not cause any
// entries to be skipped.
var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var set = new Set(str);
var log = '';
var i = 0;
for (var x of set) {
log += x;
if (i++ % 5 === 0) {
// Delete all entries preceding this one.
for (let y of set) {
if (y === x)
break;
set.delete(y);
}
}
}
assertEq(log, str);
assertEq(set.size, 1); // Elements 0 to 24 are removed, leaving only 25 (Z).
assertEq(set.has('Z'), true);
```
vs
```js
var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var set = new Set(str);
var log = '';
var i = 0;
for (x of set) {
log += x;
if (i++ % 5 === 0) {
for (y of set) {
if (y === x) break;
set.delete(y);
}
}
}
assertEq(log, str);
assertEq(set.size, 1);
assertEq(set.has('Z'), true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-iterator-remove-5.js)
<details>
```js
// |jit-test| error: ReferenceError
// jsfunfuzz-generated
gczeal(9);
for (var i in function(){});
s = newGlobal();
aa = f();
function f(x) {
evalcx(x, s)
}
function h(x) {
f(x)
}
// Adapted from randomly chosen test: js/src/jit-test/tests/debug/resumption-05.js
h("\
var g = newGlobal();\
g.debuggeeGlobal = this;\
g.eval(\"(\" + function() {\
var dbg = Debugger(debuggeeGlobal);\
dbg.onDebuggerStatement = function(frame) {\
frame.eval(\"f\")\
}\
} + \")()\");\
debugger;\
");
z;
```
vs
```js
gczeal(9);
for (i in function() { }) ;
s = newGlobal();
aa = f();
function f(x) {
evalcx(x, s);
}
function h(x) {
f(x);
}
h("var g = newGlobal();g.debuggeeGlobal = this;g.eval(\"(\" + function() {var dbg = Debugger(debuggeeGlobal);dbg.onDebuggerStatement = function(frame) {frame.eval(\"f\")}} + \")()\");debugger;");
z;
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-13.js)
<details>
```js
// for-of does not skip Array holes. The value at a hole is undefined.
var a = [0, , 2, 3];
var log = [];
for (var x of a) {
assertEq(x, a[log.length]);
log.push(x);
}
assertEq(log[1], undefined);
assertEq(log.join(), "0,,2,3");
```
vs
```js
var a = [0,, 2, 3,];
var log = [];
for (x of a) {
assertEq(x, a[log.length]);
log.push(x);
}
assertEq(log[1], undefined);
assertEq(log.join(), "0,,2,3");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/array-holes-1.js)
<details>
```js
// Removing a Map entry already visited by an iterator does not cause any
// entries to be skipped.
var map = new Map();
for (var i = 0; i < 20; i++)
map.set(String.fromCharCode('A'.charCodeAt(0) + i), i);
var log = '';
for (var [k, v] of map) {
log += k;
if (v % 5 === 4) {
// Delete all entries preceding this one.
for (let [k1, v1] of map) {
if (k1 === k)
break;
map.delete(k1);
}
}
}
assertEq(log, 'ABCDEFGHIJKLMNOPQRST');
assertEq(map.size, 1); // Only the last entry remains.
assertEq(map.get('T'), 19);
```
vs
```js
var map = new Map();
for (let i = 0;i < 20;i++) map.set(String.fromCharCode('A'.charCodeAt(0) + i), i);
var log = '';
for ([k,v,] of map) {
log += k;
if (v % 5 === 4) {
for ([k1,v1,] of map) {
if (k1 === k) break;
map.delete(k1);
}
}
}
assertEq(log, 'ABCDEFGHIJKLMNOPQRST');
assertEq(map.size, 1);
assertEq(map.get('T'), 19);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-iterator-remove-5.js)
<details>
```js
function getval(o) {
return obj.val
}
function f(x, o) {
var lhs = -(~x >>> 0)
var rhs = getval(o)
return (lhs - rhs >> 0)
}
function getObj(v) {
return {
val: v
}
}
var obj = getObj(1)
assertEq(f(0, obj), 0)
assertEq(f(0, obj), 0)
obj = getObj('can has bug?')
obj = getObj(.5)
assertEq(f(0, obj), 1)
```
vs
```js
function getval(o) {
return obj.val;
}
function f(x, o) {
var lhs = -~x >>> 0;
var rhs = getval(o);
return lhs - rhs >> 0;
}
function getObj(v) {
return {
val: v,
};
}
var obj = getObj(1);
assertEq(f(0, obj), 0);
assertEq(f(0, obj), 0);
obj = getObj('can has bug?');
obj = getObj(.5);
assertEq(f(0, obj), 1);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/bug1007213.js)
<details>
```js
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var loops = 15
var nx = 120
var nz = 120
function morph(a, f) {
var PI2nx = Math.PI * 8/nx
var sin = Math.sin
var f30 = -(50 * sin(f*Math.PI*2))
for (var i = 0; i < nz; ++i) {
for (var j = 0; j < nx; ++j) {
a[3*(i*nx+j)+1] = sin((j-1) * PI2nx ) * -f30
}
}
}
var a = Array()
for (var i=0; i < nx*nz*3; ++i)
a[i] = 0
for (var i = 0; i < loops; ++i) {
morph(a, i/loops)
}
testOutput = 0;
for (var i = 0; i < nx; i++)
testOutput += a[3*(i*nx+i)+1];
a = null;
/* not based on any mathematical error calculation.*/
acceptableDelta = 4e-15
assertEq((testOutput - 6.394884621840902e-14) < acceptableDelta, true);
```
vs
```js
var loops = 15;
var nx = 120;
var nz = 120;
function morph(a, f) {
var PI2nx = Math.PI * 8 / nx;
var sin = Math.sin;
var f30 = -50 * sin(f * Math.PI * 2);
for (let i = 0;i < nz;++i) {
for (let j = 0;j < nx;++j) {
a[3 * i * nx + j + 1] = sin(j - 1 * PI2nx) * -f30;
}
}
}
var a = Array();
for (let i = 0;i < nx * nz * 3;++i) a[i] = 0;
for (let i = 0;i < loops;++i) {
morph(a, i / loops);
}
testOutput = 0;
for (let i = 0;i < nx;i++) testOutput += a[3 * i * nx + i + 1];
a = null;
acceptableDelta = 4e-15;
assertEq(testOutput - 6.394884621840902e-14 < acceptableDelta, true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-3d-morph.js)
<details>
```js
// Nested for-of loops can use the same generator-iterator.
function* range(n) {
for (var i = 0; i < n; i++)
yield i;
}
var r = range(10);
for (var a of r)
for (var b of r)
for (var c of r)
for (var d of r)
;
assertEq(a, 0);
assertEq(b, 1);
assertEq(c, 2);
assertEq(d, 9);
```
vs
```js
function *range(n) {
for (let i = 0;i < n;i++) yield i;
}
var r = range(10);
for (a of r) for (b of r) for (c of r) for (d of r) ;
assertEq(a, 0);
assertEq(b, 1);
assertEq(c, 2);
assertEq(d, 9);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/generators-3.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
load(libdir + 'array-compare.js');
var obj = {};
function strictNestedAssignShadowCatchCall(p)
{
"use strict";
function inner()
{
try
{
}
catch (p)
{
var f = function innermost() { p = 1776; return 12; };
f();
}
}
inner();
return arguments;
}
var a1, a2, a3, a4;
for (var i = 0; i < 5; i++)
{
a1 = strictNestedAssignShadowCatchCall();
a2 = strictNestedAssignShadowCatchCall(99);
a3 = strictNestedAssignShadowCatchCall("");
a4 = strictNestedAssignShadowCatchCall(obj);
}
assertEq(arraysEqual(a1, []), true);
assertEq(arraysEqual(a2, [99]), true);
assertEq(arraysEqual(a3, [""]), true);
assertEq(arraysEqual(a4, [obj]), true);
```
vs
```js
load(libdir + 'array-compare.js');
var obj = ({});
function strictNestedAssignShadowCatchCall(p) {
'use strict';
function inner() {
try {
} catch (p) {
var f = function innermost() {
p = 1776;
return 12;
};
f();
}
}
inner();
return arguments;
}
var a1, a2, a3, a4;
for (let i = 0;i < 5;i++) {
a1 = strictNestedAssignShadowCatchCall();
a2 = strictNestedAssignShadowCatchCall(99);
a3 = strictNestedAssignShadowCatchCall("");
a4 = strictNestedAssignShadowCatchCall(obj);
}
assertEq(arraysEqual(a1, []), true);
assertEq(arraysEqual(a2, [99,]), true);
assertEq(arraysEqual(a3, ["",]), true);
assertEq(arraysEqual(a4, [obj,]), true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch-call.js)
<details>
```js
// for-of works on slow arrays.
var a = ['a', 'b', 'c'];
a.slow = true;
var log = '';
for (var x of a)
log += x;
assertEq(log, 'abc');
```
vs
```js
var a = ['a', 'b', 'c',];
a.slow = true;
var log = '';
for (x of a) log += x;
assertEq(log, 'abc');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-slow-1.js)
<details>
```js
gczeal(4);
var symbols = [Symbol(), Symbol("comet"), Symbol.for("moon"), Symbol.iterator, 0];
for (var a of symbols) {}
```
vs
```js
gczeal(4);
var symbols = [Symbol(), Symbol("comet"), Symbol.for("moon"), Symbol.iterator, 0,];
for (a of symbols) {
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/gc/bug-1032206.js)
<details>
```js
// Superficial tests of the Array.prototype[@@iterator] builtin function and its workalikes.
load(libdir + "iteration.js");
var constructors = [Array, String, Uint8Array, Uint8ClampedArray];
for (var c of constructors) {
assertEq(c.prototype[Symbol.iterator].length, 0);
var loc = (c === Array || c === String)
? c.prototype
: Object.getPrototypeOf(c.prototype);
var desc = Object.getOwnPropertyDescriptor(loc, Symbol.iterator);
assertEq(desc.configurable, true);
assertEq(desc.enumerable, false);
assertEq(desc.writable, true);
}
```
vs
```js
load(libdir + "iteration.js");
var constructors = [Array, String, Uint8Array, Uint8ClampedArray,];
for (c of constructors) {
assertEq(c.prototype[Symbol.iterator].length, 0);
var loc = c === Array || c === String ? c.prototype : Object.getPrototypeOf(c.prototype);
var desc = Object.getOwnPropertyDescriptor(loc, Symbol.iterator);
assertEq(desc.configurable, true);
assertEq(desc.enumerable, false);
assertEq(desc.writable, true);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/array-iterator-surfaces-1.js)
<details>
```js
// A Set iterator does not visit entries removed by clear().
load(libdir + "iteration.js");
var s = new Set();
var it = s[Symbol.iterator]();
s.clear();
assertIteratorDone(it, undefined);
s = new Set(["a", "b", "c", "d"]);
it = s[Symbol.iterator]();
assertIteratorNext(it, "a");
s.clear();
assertIteratorDone(it, undefined);
var log = "";
s = new Set(["a", "b", "c", "d"]);
for (var v of s) {
log += v;
if (v == "b")
s.clear();
}
assertEq(log, "ab");
```
vs
```js
load(libdir + "iteration.js");
var s = new Set();
var it = s[Symbol.iterator]();
s.clear();
assertIteratorDone(it, undefined);
s = new Set(["a", "b", "c", "d",]);
it = s[Symbol.iterator]();
assertIteratorNext(it, "a");
s.clear();
assertIteratorDone(it, undefined);
var log = "";
s = new Set(["a", "b", "c", "d",]);
for (v of s) {
log += v;
if (v == "b") s.clear();
}
assertEq(log, "ab");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-clear-iterators-1.js)
<details>
```js
// Tests that we can reflect optimized out values.
//
// Unfortunately these tests are brittle. They depend on opaque JIT heuristics
// kicking in.
// Use gczeal 0 to keep CGC from invalidating Ion code and causing test failures.
gczeal(0);
load(libdir + "jitopts.js");
if (!jitTogglesMatch(Opts_Ion2NoOffthreadCompilation))
quit(0);
withJitOptions(Opts_Ion2NoOffthreadCompilation, function () {
var g = newGlobal();
var dbg = new Debugger;
// Note that this *depends* on CCW scripted functions being opaque to Ion
// optimization and not deoptimizing the frames below the call to toggle.
g.toggle = function toggle(d) {
if (d) {
dbg.addDebuggee(g);
var frame = dbg.getNewestFrame();
assertEq(frame.implementation, "ion");
// x is unused and should be elided.
assertEq(frame.environment.getVariable("x").optimizedOut, true);
assertEq(frame.arguments[1].optimizedOut, true);
}
};
g.eval("" + function f(d, x) {
"use strict";
eval("g(d, x)"); // `eval` to avoid inlining g.
});
g.eval("" + function g(d, x) {
"use strict";
for (var i = 0; i < 200; i++);
toggle(d);
});
g.eval("(" + function test() {
for (i = 0; i < 5; i++)
f(false, 42);
f(true, 42);
} + ")();");
});
```
vs
```js
gczeal(0);
load(libdir + "jitopts.js");
if (!jitTogglesMatch(Opts_Ion2NoOffthreadCompilation)) quit(0);
withJitOptions(Opts_Ion2NoOffthreadCompilation, (function() {
var g = newGlobal();
var dbg = new Debugger();
g.toggle = function toggle(d) {
if (d) {
dbg.addDebuggee(g);
var frame = dbg.getNewestFrame();
assertEq(frame.implementation, "ion");
assertEq(frame.environment.getVariable("x").optimizedOut, true);
assertEq(frame.arguments[1].optimizedOut, true);
}
};
g.eval("" + function f(d, x) {
'use strict';
eval("g(d, x)");
});
g.eval("" + function g(d, x) {
'use strict';
for (let i = 0;i < 200;i++) ;
toggle(d);
});
g.eval("(" + function test() {
for (i = 0;i < 5;i++) f(false, 42);
f(true, 42);
} + ")();");
}));
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/optimized-out-01.js)
<details>
```js
// Test the behavior of property sets on typed objects when they are a
// prototype or their prototype has a setter.
var TO = TypedObject;
function assertThrows(fun, errorType) {
try {
fun();
assertEq(true, false, "Expected error, but none was thrown");
} catch (e) {
assertEq(e instanceof errorType, true, "Wrong error type thrown");
}
}
var PointType = new TO.StructType({x: TO.int32, y: TO.int32 });
function testPoint() {
var p = new PointType();
var sub = Object.create(p);
var found;
Object.defineProperty(PointType.prototype, "z", {set: function(a) { this.d = a; }});
Object.defineProperty(PointType.prototype, "innocuous", {set: function(a) { found = a; }});
sub.x = 5;
assertEq(sub.x, 5);
assertEq(p.x, 0);
sub.z = 5;
assertEq(sub.d, 5);
assertEq(sub.z, undefined);
sub[3] = 5;
assertEq(sub[3], 5);
p.innocuous = 10;
assertEq(found, 10);
assertThrows(function() {
p.z = 10;
assertEq(true, false);
}, TypeError);
}
testPoint();
var IntArrayType = new TO.ArrayType(TO.int32, 3);
function testArray() {
var arr = new IntArrayType();
var found;
Object.defineProperty(IntArrayType.prototype, 5, {set: function(a) { found = a; }});
assertThrows(function() {
arr[5] = 5;
}, RangeError);
assertThrows(function() {
arr[4] = 5;
}, RangeError);
var p = Object.create(arr);
p.length = 100;
assertEq(p.length, 3);
assertThrows(function() {
"use strict";
p.length = 100;
}, TypeError);
}
testArray();
```
vs
```js
var TO = TypedObject;
function assertThrows(fun, errorType) {
try {
fun();
assertEq(true, false, "Expected error, but none was thrown");
} catch (e) {
assertEq(e instanceof errorType, true, "Wrong error type thrown");
}
}
var PointType = new TO.StructType(({
x: TO.int32,
y: TO.int32,
}));
function testPoint() {
var p = new PointType();
var sub = Object.create(p);
var found;
Object.defineProperty(PointType.prototype, "z", {
set: function(a) {
this.d = a;
},
});
Object.defineProperty(PointType.prototype, "innocuous", {
set: function(a) {
found = a;
},
});
sub.x = 5;
assertEq(sub.x, 5);
assertEq(p.x, 0);
sub.z = 5;
assertEq(sub.d, 5);
assertEq(sub.z, undefined);
sub[3] = 5;
assertEq(sub[3], 5);
p.innocuous = 10;
assertEq(found, 10);
assertThrows(function() {
p.z = 10;
assertEq(true, false);
}, TypeError);
}
testPoint();
var IntArrayType = new TO.ArrayType(TO.int32, 3);
function testArray() {
var arr = new IntArrayType();
var found;
Object.defineProperty(IntArrayType.prototype, 5, {
set: function(a) {
found = a;
},
});
assertThrows(function() {
arr[5] = 5;
}, RangeError);
assertThrows(function() {
arr[4] = 5;
}, RangeError);
var p = Object.create(arr);
p.length = 100;
assertEq(p.length, 3);
assertThrows(function() {
'use strict';
p.length = 100;
}, TypeError);
}
testArray();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/TypedObject/set-property-with-prototype.js)
<details>
```js
// The Great Computer Language Shootout
// http://shootout.alioth.debian.org
//
// Contributed by Ian Osgood
var last = 42, A = 3877, C = 29573, M = 139968;
function rand(max) {
last = (last * A + C) % M;
return max * last / M;
}
var ALU =
"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
var IUB = {
a:0.27, c:0.12, g:0.12, t:0.27,
B:0.02, D:0.02, H:0.02, K:0.02,
M:0.02, N:0.02, R:0.02, S:0.02,
V:0.02, W:0.02, Y:0.02
}
var HomoSap = {
a: 0.3029549426680,
c: 0.1979883004921,
g: 0.1975473066391,
t: 0.3015094502008
}
function makeCumulative(table) {
var last = null;
for (var c in table) {
if (last) table[c] += table[last];
last = c;
}
}
function fastaRepeat(n, seq) {
var seqi = 0, lenOut = 60;
while (n>0) {
if (n<lenOut) lenOut = n;
if (seqi + lenOut < seq.length) {
ret = seq.substring(seqi, seqi+lenOut);
seqi += lenOut;
} else {
var s = seq.substring(seqi);
seqi = lenOut - s.length;
ret = s + seq.substring(0, seqi);
}
n -= lenOut;
}
return ret;
}
function fastaRandom(n, table) {
var line = new Array(60);
makeCumulative(table);
while (n>0) {
if (n<line.length) line = new Array(n);
for (var i=0; i<line.length; i++) {
var r = rand(1);
for (var c in table) {
if (r < table[c]) {
line[i] = c;
break;
}
}
}
ret = line.join('');
n -= line.length;
}
return ret;
}
var ret;
var count = 7;
var actual1 = fastaRepeat(2*count*100000, ALU);
var actual2 = fastaRandom(3*count*1000, IUB);
var actual3 = fastaRandom(5*count*1000, HomoSap);
assertEq(actual1, "CAAAAAGGCCGGGCGCGGTG");
assertEq(actual2, "VtttaDtKgcaaWaaaaatSccMcVatgtKgtaKgcgatatgtagtSaaaDttatacaaa");
assertEq(actual3, "ttggctatatttatgttgga");
```
vs
```js
var last = 42, A = 3877, C = 29573, M = 139968;
function rand(max) {
last = last * A + C % M;
return max * last / M;
}
var ALU = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" + "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" + "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" + "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" + "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" + "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" + "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
var IUB = ({
a: 0.27,
c: 0.12,
g: 0.12,
t: 0.27,
B: 0.02,
D: 0.02,
H: 0.02,
K: 0.02,
M: 0.02,
N: 0.02,
R: 0.02,
S: 0.02,
V: 0.02,
W: 0.02,
Y: 0.02,
});
var HomoSap = ({
a: 0.3029549426680,
c: 0.1979883004921,
g: 0.1975473066391,
t: 0.3015094502008,
});
function makeCumulative(table) {
var last = null;
for (c in table) {
if (last) table[c] += table[last];
last = c;
}
}
function fastaRepeat(n, seq) {
var seqi = 0, lenOut = 60;
while (n > 0) {
if (n < lenOut) lenOut = n;
if (seqi + lenOut < seq.length) {
ret = seq.substring(seqi, seqi + lenOut);
seqi += lenOut;
} else {
var s = seq.substring(seqi);
seqi = lenOut - s.length;
ret = s + seq.substring(0, seqi);
}
n -= lenOut;
}
return ret;
}
function fastaRandom(n, table) {
var line = new Array(60);
makeCumulative(table);
while (n > 0) {
if (n < line.length) line = new Array(n);
for (let i = 0;i < line.length;i++) {
var r = rand(1);
for (c in table) {
if (r < table[c]) {
line[i] = c;
break;
}
}
}
ret = line.join('');
n -= line.length;
}
return ret;
}
var ret;
var count = 7;
var actual1 = fastaRepeat(2 * count * 100000, ALU);
var actual2 = fastaRandom(3 * count * 1000, IUB);
var actual3 = fastaRandom(5 * count * 1000, HomoSap);
assertEq(actual1, "CAAAAAGGCCGGGCGCGGTG");
assertEq(actual2, "VtttaDtKgcaaWaaaaatSccMcVatgtKgtaKgcgatatgtagtSaaaDttatacaaa");
assertEq(actual3, "ttggctatatttatgttgga");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-string-fasta.js)
<details>
```js
// For-of passes one arg to "next".
load(libdir + 'iteration.js')
var log = '';
function Iter() {
function next() {
log += 'n';
assertEq(arguments.length, 0)
assertEq(arguments[0], undefined)
return { get value() { throw 42; }, done: true }
}
this[Symbol.iterator] = function () { return this; }
this.next = next;
}
for (var x of new Iter())
throw 'not reached';
assertEq(log, 'n');
```
vs
```js
load(libdir + 'iteration.js');
var log = '';
function Iter() {
function next() {
log += 'n';
assertEq(arguments.length, 0);
assertEq(arguments[0], undefined);
return {
get value() {
throw 42;
},
done: true,
};
}
this[Symbol.iterator] = function() {
return this;
};
this.next = next;
}
for (x of new Iter()) throw 'not reached';
assertEq(log, 'n');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/next-arity.js)
<details>
```js
// Test if isInCatchScope properly detects catch blocks.
let g = newGlobal();
let dbg = new Debugger(g);
function test(string, mustBeCaught) {
let index = 0;
dbg.onExceptionUnwind = function (frame) {
let willBeCaught = false;
do {
if (frame.script.isInCatchScope(frame.offset)) {
willBeCaught = true;
break;
}
frame = frame.older;
} while (frame != null);
assertEq(willBeCaught, mustBeCaught[index++]);
};
try {
g.eval(string);
} catch (ex) {}
assertEq(index, mustBeCaught.length);
}
// Should correctly detect catch blocks
test("throw new Error();", [false]);
test("try { throw new Error(); } catch (e) {}", [true]);
test("try { throw new Error(); } finally {}", [false, false]);
test("try { throw new Error(); } catch (e) {} finally {}", [true]);
// Source of the exception shouldn't matter
test("(null)();", [false]);
test("try { (null)(); } catch (e) {}", [true]);
test("try { (null)(); } finally {}", [false, false]);
test("try { (null)(); } catch (e) {} finally {}", [true]);
// Should correctly detect catch blocks in functions
test("function f() { throw new Error(); } f();", [false, false]);
test("function f() { try { throw new Error(); } catch (e) {} } f();", [true]);
test("function f() { try { throw new Error(); } finally {} } f();", [false, false, false]);
test("function f() { try { throw new Error(); } catch (e) {} finally {} } f();", [true]);
// Should correctly detect catch blocks in evals
test("eval('throw new Error();')", [false, false]);
test("eval('try { throw new Error(); } catch (e) {}');", [true]);
test("eval('try { throw new Error(); } finally {}');", [false, false, false]);
test("eval('try { throw new Error(); } catch (e) {} finally {}');", [true]);
// Should correctly detect rethrows
test("try { throw new Error(); } catch (e) { throw e; }", [true, false]);
test("try { try { throw new Error(); } catch (e) { throw e; } } catch (e) {}", [true, true]);
test("try { try { throw new Error(); } finally {} } catch (e) {}", [true, true]);
test("function f() { try { throw new Error(); } catch (e) { throw e; } } f();", [true, false, false]);
test("function f() { try { try { throw new Error(); } catch (e) { throw e; } } catch (e) {} } f();", [true, true]);
test("function f() { try { try { throw new Error(); } finally {} } catch (e) {} } f();", [true, true]);
test("eval('try { throw new Error(); } catch (e) { throw e; }')", [true, false, false]);
test("eval('try { try { throw new Error(); } catch (e) { throw e; } } catch (e) {}')", [true, true]);
// Should correctly detect catch blocks across frame boundaries
test("function f() { throw new Error(); } try { f(); } catch (e) {}", [true, true]);
test("function f() { throw new Error(); } try { f(); } catch (e) { throw e; }", [true, true, false]);
test("try { eval('throw new Error()'); } catch (e) {}", [true, true]);
test("try { eval('throw new Error()'); } catch (e) { throw e; }", [true, true, false]);
// Should correctly detect catch blocks just before and just after throws
test("throw new Error; try {} catch (e) {}", [false]);
test("try {} catch (e) {} throw new Error();", [false]);
```
vs
```js
let g = newGlobal();
let dbg = new Debugger(g);
function test(string, mustBeCaught) {
let index = 0;
dbg.onExceptionUnwind = function(frame) {
let willBeCaught = false;
do {
if (frame.script.isInCatchScope(frame.offset)) {
willBeCaught = true;
break;
}
frame = frame.older;
} while (frame != null);
;
assertEq(willBeCaught, mustBeCaught[index++]);
};
try {
g.eval(string);
} catch (ex) {
}
assertEq(index, mustBeCaught.length);
}
test("throw new Error();", [false,]);
test("try { throw new Error(); } catch (e) {}", [true,]);
test("try { throw new Error(); } finally {}", [false, false,]);
test("try { throw new Error(); } catch (e) {} finally {}", [true,]);
test("(null)();", [false,]);
test("try { (null)(); } catch (e) {}", [true,]);
test("try { (null)(); } finally {}", [false, false,]);
test("try { (null)(); } catch (e) {} finally {}", [true,]);
test("function f() { throw new Error(); } f();", [false, false,]);
test("function f() { try { throw new Error(); } catch (e) {} } f();", [true,]);
test("function f() { try { throw new Error(); } finally {} } f();", [false, false, false,]);
test("function f() { try { throw new Error(); } catch (e) {} finally {} } f();", [true,]);
test("eval('throw new Error();')", [false, false,]);
test("eval('try { throw new Error(); } catch (e) {}');", [true,]);
test("eval('try { throw new Error(); } finally {}');", [false, false, false,]);
test("eval('try { throw new Error(); } catch (e) {} finally {}');", [true,]);
test("try { throw new Error(); } catch (e) { throw e; }", [true, false,]);
test("try { try { throw new Error(); } catch (e) { throw e; } } catch (e) {}", [true, true,]);
test("try { try { throw new Error(); } finally {} } catch (e) {}", [true, true,]);
test("function f() { try { throw new Error(); } catch (e) { throw e; } } f();", [true, false, false,]);
test("function f() { try { try { throw new Error(); } catch (e) { throw e; } } catch (e) {} } f();", [true, true,]);
test("function f() { try { try { throw new Error(); } finally {} } catch (e) {} } f();", [true, true,]);
test("eval('try { throw new Error(); } catch (e) { throw e; }')", [true, false, false,]);
test("eval('try { try { throw new Error(); } catch (e) { throw e; } } catch (e) {}')", [true, true,]);
test("function f() { throw new Error(); } try { f(); } catch (e) {}", [true, true,]);
test("function f() { throw new Error(); } try { f(); } catch (e) { throw e; }", [true, true, false,]);
test("try { eval('throw new Error()'); } catch (e) {}", [true, true,]);
test("try { eval('throw new Error()'); } catch (e) { throw e; }", [true, true, false,]);
test("throw new Error; try {} catch (e) {}", [false,]);
test("try {} catch (e) {} throw new Error();", [false,]);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Script-isInCatchScope.js)
<details>
```js
var array = new (TypedObject.uint8.array(5));
for (var i = 0; i < array.length; i++)
assertEq(i in array, true);
for (var v of [20, 300, -1, 5, -10, Math.pow(2, 32) - 1, -Math.pow(2, 32)])
assertEq(v in array, false);
// Don't inherit elements
array.__proto__[50] = "hello";
assertEq(array.__proto__[50], "hello");
assertEq(50 in array, false);
// Do inherit normal properties
array.__proto__.a = "world";
assertEq(array.__proto__.a, "world");
assertEq("a" in array, true);
```
vs
```js
var array = new TypedObject.uint8.array(5)();
for (let i = 0;i < array.length;i++) assertEq(i in array, true);
for (v of [20, 300, -1, 5, -10, Math.pow(2, 32) - 1, -Math.pow(2, 32),]) assertEq(v in array, false);
array.__proto__[50] = "hello";
assertEq(array.__proto__[50], "hello");
assertEq(50 in array, false);
array.__proto__.a = "world";
assertEq(array.__proto__.a, "world");
assertEq("a" in array, true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/TypedObject/array-hasproperty.js)
<details>
```js
load(libdir + "asserts.js");
eval(`"use strict";
function f1(f=(function () { return typeof this !== "object"; })) { return f; }
assertEq(f1()(), true);
`);
function f2(f=(function () { "use strict"; return (function () { return typeof this !== "object"; }) })) { assertEq(typeof this, "object"); return f; }
assertEq(f2()()(), true);
eval(`"use strict";
function f3(f=(function () { return (function () { return typeof this !== "object"; }) })) { return f; }
assertEq(f3()()(), true);
`);
// These should be okay.
function f4(f=(function () { with (Object) {} }), g=(function () { "use strict"; })) {}
function f5(g=(function () { "use strict"; }), f=(function () { with (Object) {} })) {}
assertThrowsInstanceOf(function () {
eval("'use strict'; function f(a=delete x) { }");
}, SyntaxError);
assertThrowsInstanceOf(function () {
Math.sin(4);
eval("'use strict'; function f(a='\\251') { }");
}, SyntaxError);
assertThrowsInstanceOf(function () {
eval("'use strict'; function f(a='\\251', b=delete x) { }");
}, SyntaxError);
assertThrowsInstanceOf(function () {
eval("'use strict'; function f(a=delete x, b='\\251') { }");
}, SyntaxError);
assertThrowsInstanceOf(function () {
eval("'use strict'; function f(a=(function () { '\\251'; })) { }");
}, SyntaxError);
assertThrowsInstanceOf(function () {
eval("'use strict'; function f(a=(function () { with (Object) {} })) { }");
}, SyntaxError);
assertThrowsInstanceOf(function () {
eval("'use strict'; function f(a=(function (b, b) {})) { }");
}, SyntaxError);
```
vs
```js
load(libdir + "asserts.js");
eval(`"use strict";
function f1(f=(function () { return typeof this !== "object"; })) { return f; }
assertEq(f1()(), true);
`);
function f2(f = function() {
'use strict';
return function() {
return typeof this !== "object";
};
}) {
assertEq(typeof this, "object");
return f;
}
assertEq(f2()()(), true);
eval(`"use strict";
function f3(f=(function () { return (function () { return typeof this !== "object"; }) })) { return f; }
assertEq(f3()()(), true);
`);
function f4(f = function() {
with (Object) {
}
}, g = function() {
'use strict';
}) { }
function f5(g = function() {
'use strict';
}, f = function() {
with (Object) {
}
}) { }
assertThrowsInstanceOf((function() {
eval("'use strict'; function f(a=delete x) { }");
}), SyntaxError);
assertThrowsInstanceOf((function() {
Math.sin(4);
eval("'use strict'; function f(a='\\251') { }");
}), SyntaxError);
assertThrowsInstanceOf((function() {
eval("'use strict'; function f(a='\\251', b=delete x) { }");
}), SyntaxError);
assertThrowsInstanceOf((function() {
eval("'use strict'; function f(a=delete x, b='\\251') { }");
}), SyntaxError);
assertThrowsInstanceOf((function() {
eval("'use strict'; function f(a=(function () { '\\251'; })) { }");
}), SyntaxError);
assertThrowsInstanceOf((function() {
eval("'use strict'; function f(a=(function () { with (Object) {} })) { }");
}), SyntaxError);
assertThrowsInstanceOf((function() {
eval("'use strict'; function f(a=(function (b, b) {})) { }");
}), SyntaxError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/defaults-strict-mode.js)
* [Unexpected Token at line: 4, column: 31: Expected `OpenBrace`; found Ident(Ident("Array"))](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-9.js)
<details>
```js
function bytecode(f) {
if (typeof disassemble !== "function")
return "unavailable";
var d = disassemble(f);
return d.slice(d.indexOf("main:"), d.indexOf("\n\n"));
}
assertEq(bytecode(() => "hello" + "world"),
bytecode(() => "helloworld"));
assertEq(bytecode(() => 2 + "2" + "2"),
bytecode(() => "222"));
assertEq(bytecode(() => "x" + "3"),
bytecode(() => "x3"));
var s = "hoge";
assertEq(bytecode(() => "fo" + "o" + s + "ba" + "r"),
bytecode(() => "foo" + s + "bar"));
assertEq(bytecode(() => "fo" + "o" + 1 + s + 1 + "ba" + "r"),
bytecode(() => "foo1" + s + "1bar"));
assertEq(bytecode(() => 1 + (2 * 2) + "x"),
bytecode(() => 5 + "x"));
assertEq(s + 1 + 2, "hoge12");
assertEq((() => s + 1 + 2)(), "hoge12");
// SpiderMonkey knows that 1 + 1 == "11".
assertEq(bytecode(() => "x" + s + 1 + 1),
bytecode(() => "x" + s + "11"));
var n = 5;
assertEq(1 + n + 1 + "ba" + "r", "7bar");
assertEq(1 + 2 + {valueOf: () => 3, toString: () => 'x'} + 4 + 5,15);
assertEq(1+2+n,8);
assertEq(bytecode(() => 1 + 2 + n + 1 + 2),
bytecode(() => 3 + n + 1 + 2));
assertEq(1 + 2 + n + 1 + 2, 11);
assertEq(bytecode(() => 1 + 2 + s + 1 + 2),
bytecode(() => 3 + s + 1 + 2));
assertEq(1 + 2 + s + 1 + 2, "3hoge12");
assertEq(bytecode(() => ["a" + "b" + n]),
bytecode(() => ["ab" + n]));
var a = ["a" + "b" + n];
assertEq(a[0], "ab5");
```
vs
```js
function bytecode(f) {
if (typeof disassemble !== "function") return "unavailable";
var d = disassemble(f);
return d.slice(d.indexOf("main:"), d.indexOf("\n\n"));
}
assertEq(bytecode(() => "hello" + "world"), bytecode(() => "helloworld"));
assertEq(bytecode(() => 2 + "2" + "2"), bytecode(() => "222"));
assertEq(bytecode(() => "x" + "3"), bytecode(() => "x3"));
var s = "hoge";
assertEq(bytecode(() => "fo" + "o" + s + "ba" + "r"), bytecode(() => "foo" + s + "bar"));
assertEq(bytecode(() => "fo" + "o" + 1 + s + 1 + "ba" + "r"), bytecode(() => "foo1" + s + "1bar"));
assertEq(bytecode(() => 1 + 2 * 2 + "x"), bytecode(() => 5 + "x"));
assertEq(s + 1 + 2, "hoge12");
assertEq(() => s + 1 + 2(), "hoge12");
assertEq(bytecode(() => "x" + s + 1 + 1), bytecode(() => "x" + s + "11"));
var n = 5;
assertEq(1 + n + 1 + "ba" + "r", "7bar");
assertEq(1 + 2 + ({
valueOf: () => 3,
toString: () => 'x',
}) + 4 + 5, 15);
assertEq(1 + 2 + n, 8);
assertEq(bytecode(() => 1 + 2 + n + 1 + 2), bytecode(() => 3 + n + 1 + 2));
assertEq(1 + 2 + n + 1 + 2, 11);
assertEq(bytecode(() => 1 + 2 + s + 1 + 2), bytecode(() => 3 + s + 1 + 2));
assertEq(1 + 2 + s + 1 + 2, "3hoge12");
assertEq(bytecode(() => ["a" + "b" + n,]), bytecode(() => ["ab" + n,]));
var a = ["a" + "b" + n,];
assertEq(a[0], "ab5");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/constant-folding-1.js)
<details>
```js
// A map iterator can cope with removing the next entry.
load(libdir + "iteration.js");
var set = new Set("abcd");
var iter = set[Symbol.iterator]();
var log = "";
for (let x of iter) {
log += x;
if (x === "b")
set.delete("c");
}
assertEq(log, "abd");
```
vs
```js
load(libdir + "iteration.js");
var set = new Set("abcd");
var iter = set[Symbol.iterator]();
var log = "";
for (x of iter) {
log += x;
if (x === "b") set.delete("c");
}
assertEq(log, "abd");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-iterator-remove-2.js)
<details>
```js
/*
* Copyright (C) Rich Moore. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/////. Start CORDIC
var AG_CONST = 0.6072529350;
function FIXED(X)
{
return X * 65536.0;
}
function FLOAT(X)
{
return X / 65536.0;
}
function DEG2RAD(X)
{
return 0.017453 * (X);
}
var Angles = [
FIXED(45.0), FIXED(26.565), FIXED(14.0362), FIXED(7.12502),
FIXED(3.57633), FIXED(1.78991), FIXED(0.895174), FIXED(0.447614),
FIXED(0.223811), FIXED(0.111906), FIXED(0.055953),
FIXED(0.027977)
];
function cordicsincos() {
var X;
var Y;
var TargetAngle;
var CurrAngle;
var Step;
X = FIXED(AG_CONST); /* AG_CONST * cos(0) */
Y = 0; /* AG_CONST * sin(0) */
TargetAngle = FIXED(28.027);
CurrAngle = 0;
for (Step = 0; Step < 12; Step++) {
var NewX;
if (TargetAngle > CurrAngle) {
NewX = X - (Y >> Step);
Y = (X >> Step) + Y;
X = NewX;
CurrAngle += Angles[Step];
} else {
NewX = X + (Y >> Step);
Y = -(X >> Step) + Y;
X = NewX;
CurrAngle -= Angles[Step];
}
}
return CurrAngle;
}
///// End CORDIC
function cordic( runs ) {
var actual;
for ( var i = 0 ; i < runs ; i++ ) {
actual = cordicsincos();
}
assertEq(actual, 1834995.3515519998)
}
cordic(25000);
```
vs
```js
var AG_CONST = 0.6072529350;
function FIXED(X) {
return X * 65536.0;
}
function FLOAT(X) {
return X / 65536.0;
}
function DEG2RAD(X) {
return 0.017453 * X;
}
var Angles = [FIXED(45.0), FIXED(26.565), FIXED(14.0362), FIXED(7.12502), FIXED(3.57633), FIXED(1.78991), FIXED(0.895174), FIXED(0.447614), FIXED(0.223811), FIXED(0.111906), FIXED(0.055953), FIXED(0.027977),];
function cordicsincos() {
var X;
var Y;
var TargetAngle;
var CurrAngle;
var Step;
X = FIXED(AG_CONST);
Y = 0;
TargetAngle = FIXED(28.027);
CurrAngle = 0;
for (Step = 0;Step < 12;Step++) {
var NewX;
if (TargetAngle > CurrAngle) {
NewX = X - Y >> Step;
Y = X >> Step + Y;
X = NewX;
CurrAngle += Angles[Step];
} else {
NewX = X + Y >> Step;
Y = -X >> Step + Y;
X = NewX;
CurrAngle -= Angles[Step];
}
}
return CurrAngle;
}
function cordic(runs) {
var actual;
for (let i = 0;i < runs;i++) {
actual = cordicsincos();
}
assertEq(actual, 1834995.3515519998);
}
cordic(25000);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-math-cordic.js)
* [Unexpected Token at line: 1, column: 0: Expected `{`, `[`, or `(`; found Punct(Pipe)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/gc/bug-1258407.js)
<details>
```js
// Generator-iterators are consumed the first time they are iterated.
function* range(n) {
for (var i = 0; i < n; i++)
yield i;
}
var r = range(10);
var i = 0;
for (var x of r)
assertEq(x, i++);
assertEq(i, 10);
for (var y of r)
throw "FAIL";
assertEq(y, undefined);
```
vs
```js
function *range(n) {
for (let i = 0;i < n;i++) yield i;
}
var r = range(10);
var i = 0;
for (x of r) assertEq(x, i++);
assertEq(i, 10);
for (y of r) throw "FAIL";
assertEq(y, undefined);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/generators-2.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/gc/bug-948423.js)
<details>
```js
// async functions fire onEnterFrame each time they resume, like generators
let g = newGlobal();
g.eval(`
async function timeout(n) {
for (let i = 0; i < n; i++) {
await Promise.resolve(i);
}
}
async function job() {
let racer = timeout(5);
await timeout(3);
await racer;
}
`);
let dbg = Debugger(g);
let log = "";
let nicknames = ["job", "t5", "t3"];
dbg.onEnterFrame = frame => {
if (!("nickname" in frame))
frame.nickname = nicknames.shift() || "FAIL";
log += "(" + frame.nickname;
frame.onPop = completion => { log += ")"; };
};
g.job();
drainJobQueue();
assertEq(log,
"(job)(job(t5)(t5)(t3)(t3))" +
"(t5)(t3)".repeat(3) + "(job)" +
"(t5)(t5)(job)");
```
vs
```js
let g = newGlobal();
g.eval(`
async function timeout(n) {
for (let i = 0; i < n; i++) {
await Promise.resolve(i);
}
}
async function job() {
let racer = timeout(5);
await timeout(3);
await racer;
}
`);
let dbg = Debugger(g);
let log = "";
let nicknames = ["job", "t5", "t3",];
dbg.onEnterFrame = frame => {
if (!"nickname" in frame) frame.nickname = nicknames.shift() || "FAIL";
log += "(" + frame.nickname;
frame.onPop = completion => {
log += ")";
};
};
g.job();
drainJobQueue();
assertEq(log, "(job)(job(t5)(t5)(t3)(t3))" + "(t5)(t3)".repeat(3) + "(job)" + "(t5)(t5)(job)");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/onEnterFrame-async-01.js)
<details>
```js
// An exception thrown from a proxy trap while getting the .iterator method is propagated.
load(libdir + "asserts.js");
load(libdir + "iteration.js");
var p = new Proxy({}, {
get(target, property) {
if (property === Symbol.iterator)
throw "fit";
return undefined;
}
});
assertThrowsValue(function () { for (var v of p) {} }, "fit");
```
vs
```js
load(libdir + "asserts.js");
load(libdir + "iteration.js");
var p = new Proxy(({}), ({
get: (function(target, property) {
if (property === Symbol.iterator) throw "fit";
return undefined;
}),
}));
assertThrowsValue((function() {
for (v of p) {
}
}), "fit");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/proxy-3.js)
<details>
```js
const mainGlobal = this;
const debuggerGlobal = newGlobal();
function Memory({global}) {
this.dbg = new (debuggerGlobal.Debugger);
this.gDO = this.dbg.addDebuggee(global);
}
Memory.prototype = {
constructor: Memory,
attach() { return Promise.resolve('fake attach result'); },
detach() { return Promise.resolve('fake detach result'); },
startRecordingAllocations() {
this.dbg.memory.trackingAllocationSites = true;
return Promise.resolve('fake startRecordingAllocations result');
},
stopRecordingAllocations() {
this.dbg.memory.trackingAllocationSites = false;
return Promise.resolve('fake stopRecordingAllocations result');
},
getAllocations() {
return Promise.resolve({ allocations: this.dbg.memory.drainAllocationsLog() });
}
};
function ok(cond, msg) {
assertEq(!!cond, true, `ok(${uneval(cond)}, ${uneval(msg)})`);
}
const is = assertEq;
function startServerAndGetSelectedTabMemory() {
let memory = new Memory({ global: mainGlobal });
return Promise.resolve({ memory, client: 'fake client' });
}
function destroyServerAndFinish() {
return Promise.resolve('fake destroyServerAndFinish result');
}
function* body() {
let { memory, client } = yield startServerAndGetSelectedTabMemory();
yield memory.attach();
yield memory.startRecordingAllocations();
ok(true, "Can start recording allocations");
// Allocate some objects.
let alloc1, alloc2, alloc3;
/* eslint-disable max-nested-callbacks */
(function outer() {
(function middle() {
(function inner() {
alloc1 = {}; alloc1.line = Error().lineNumber;
alloc2 = []; alloc2.line = Error().lineNumber;
// eslint-disable-next-line new-parens
alloc3 = new function () {}; alloc3.line = Error().lineNumber;
}());
}());
}());
/* eslint-enable max-nested-callbacks */
let response = yield memory.getAllocations();
yield memory.stopRecordingAllocations();
ok(true, "Can stop recording allocations");
// Filter out allocations by library and test code, and get only the
// allocations that occurred in our test case above.
function isTestAllocation(alloc) {
let frame = alloc.frame;
return frame
&& frame.functionDisplayName === "inner"
&& (frame.line === alloc1.line
|| frame.line === alloc2.line
|| frame.line === alloc3.line);
}
let testAllocations = response.allocations.filter(isTestAllocation);
ok(testAllocations.length >= 3,
"Should find our 3 test allocations (plus some allocations for the error "
+ "objects used to get line numbers)");
// For each of the test case's allocations, ensure that the parent frame
// indices are correct. Also test that we did get an allocation at each
// line we expected (rather than a bunch on the first line and none on the
// others, etc).
let expectedLines = new Set([alloc1.line, alloc2.line, alloc3.line]);
for (let alloc of testAllocations) {
let innerFrame = alloc.frame;
ok(innerFrame, "Should get the inner frame");
is(innerFrame.functionDisplayName, "inner");
expectedLines.delete(innerFrame.line);
let middleFrame = innerFrame.parent;
ok(middleFrame, "Should get the middle frame");
is(middleFrame.functionDisplayName, "middle");
let outerFrame = middleFrame.parent;
ok(outerFrame, "Should get the outer frame");
is(outerFrame.functionDisplayName, "outer");
// Not going to test the rest of the frames because they are Task.jsm
// and promise frames and it gets gross. Plus, I wouldn't want this test
// to start failing if they changed their implementations in a way that
// added or removed stack frames here.
}
is(expectedLines.size, 0,
"Should have found all the expected lines");
yield memory.detach();
destroyServerAndFinish(client);
}
const generator = body();
loop(generator.next());
function loop({ value: promise, done }) {
if (done)
return;
promise
.catch(e => loop(generator.throw(e)))
.then(v => { loop(generator.next(v)); })
.catch(e => { print(`Error: ${e}\nstack:\n${e.stack}`); });
}
```
vs
```js
const mainGlobal = this;
const debuggerGlobal = newGlobal();
function Memory({global,}) {
this.dbg = new debuggerGlobal.Debugger();
this.gDO = this.dbg.addDebuggee(global);
}
Memory.prototype = ({
constructor: Memory,
attach: (function() {
return Promise.resolve('fake attach result');
}),
detach: (function() {
return Promise.resolve('fake detach result');
}),
startRecordingAllocations: (function() {
this.dbg.memory.trackingAllocationSites = true;
return Promise.resolve('fake startRecordingAllocations result');
}),
stopRecordingAllocations: (function() {
this.dbg.memory.trackingAllocationSites = false;
return Promise.resolve('fake stopRecordingAllocations result');
}),
getAllocations: (function() {
return Promise.resolve({
allocations: this.dbg.memory.drainAllocationsLog(),
});
}),
});
function ok(cond, msg) {
assertEq(!!cond, true, `ok(${uneval(cond)}, {uneval(msg)})`);
}
const is = assertEq;
function startServerAndGetSelectedTabMemory() {
let memory = new Memory({
global: mainGlobal,
});
return Promise.resolve({
memory,
client: 'fake client',
});
}
function destroyServerAndFinish() {
return Promise.resolve('fake destroyServerAndFinish result');
}
function *body() {
let {memory, client, } = yield startServerAndGetSelectedTabMemory();
yield memory.attach();
yield memory.startRecordingAllocations();
ok(true, "Can start recording allocations");
let alloc1, alloc2, alloc3;
function outer() {
function middle() {
function inner() {
alloc1 = { };
alloc1.line = Error().lineNumber;
alloc2 = [];
alloc2.line = Error().lineNumber;
alloc3 = new function() { }();
alloc3.line = Error().lineNumber;
}();
}();
}();
let response = yield memory.getAllocations();
yield memory.stopRecordingAllocations();
ok(true, "Can stop recording allocations");
function isTestAllocation(alloc) {
let frame = alloc.frame;
return frame && frame.functionDisplayName === "inner" && frame.line === alloc1.line || frame.line === alloc2.line || frame.line === alloc3.line;
}
let testAllocations = response.allocations.filter(isTestAllocation);
ok(testAllocations.length >= 3, "Should find our 3 test allocations (plus some allocations for the error " + "objects used to get line numbers)");
let expectedLines = new Set([alloc1.line, alloc2.line, alloc3.line,]);
for (alloc of testAllocations) {
let innerFrame = alloc.frame;
ok(innerFrame, "Should get the inner frame");
is(innerFrame.functionDisplayName, "inner");
expectedLines.delete(innerFrame.line);
let middleFrame = innerFrame.parent;
ok(middleFrame, "Should get the middle frame");
is(middleFrame.functionDisplayName, "middle");
let outerFrame = middleFrame.parent;
ok(outerFrame, "Should get the outer frame");
is(outerFrame.functionDisplayName, "outer");
}
is(expectedLines.size, 0, "Should have found all the expected lines");
yield memory.detach();
destroyServerAndFinish(client);
}
const generator = body();
loop(generator.next());
function loop({value: promise, done,}) {
if (done) return;
promise.catch(e => loop(generator.throw(e))).then(v => {
loop(generator.next(v));
}).catch(e => {
print(`Error: ${e}\nstack:\n{e.stack}`);
});
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/saved-stacks/1438121-generator.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-iterator-remove-1.js)
<details>
```js
// Test that the same saved stack is only ever allocated once.
const stacks = [];
for (let i = 0; i < 10; i++) {
stacks.push(saveStack());
}
const s = stacks.pop();
for (let stack of stacks) {
assertEq(s, stack);
}
```
vs
```js
const stacks = [];
for (let i = 0;i < 10;i++) {
stacks.push(saveStack());
}
const s = stacks.pop();
for (stack of stacks) {
assertEq(s, stack);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/saved-stacks/same-stack.js)
<details>
```js
// Array.keys() and .entries() on an empty array produce empty iterators
var arr = [];
var ki = arr.keys(), ei = arr.entries();
var p = Object.getPrototypeOf(ki);
assertEq(Object.getPrototypeOf(ei), p);
for (let k of ki)
throw "FAIL";
for (let [k, v] of ei)
throw "FAIL";
```
vs
```js
var arr = [];
var ki = arr.keys(), ei = arr.entries();
var p = Object.getPrototypeOf(ki);
assertEq(Object.getPrototypeOf(ei), p);
for (k of ki) throw "FAIL";
for ([k,v,] of ei) throw "FAIL";
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/array-iterator-empty.js)
<details>
```js
// A break statement leaves a for-of loop.
var log = '';
for (var x of ['a', 'b', 'c']) {
log += x;
if (x === 'b')
break;
}
assertEq(log, "ab");
```
vs
```js
var log = '';
for (x of ['a', 'b', 'c',]) {
log += x;
if (x === 'b') break;
}
assertEq(log, "ab");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/break-1.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/alias-function-not-closed.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug676764.js)
<details>
```js
// for-of works with generators.
function* range(n) {
for (var i = 0; i < n; i++)
yield i;
}
var s = '';
for (var a of range(4))
s += a;
assertEq(s, '0123');
```
vs
```js
function *range(n) {
for (let i = 0;i < n;i++) yield i;
}
var s = '';
for (a of range(4)) s += a;
assertEq(s, '0123');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/generators-1.js)
<details>
```js
// for-of works on arrays.
var a = ['a', 'b', 'c'];
var s = '';
for (var v of a)
s += v;
assertEq(s, 'abc');
```
vs
```js
var a = ['a', 'b', 'c',];
var s = '';
for (v of a) s += v;
assertEq(s, 'abc');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-1.js)
<details>
```js
// A labeled break statement can leave multiple for-loops
var log = '';
for (var i = 0; i < 3; i++) {
a: for (var x of [1, 2, 3]) {
for (var y of ['.', ':']) {
log += x + y;
break a;
}
}
}
assertEq(log, "1.1.1.");
```
vs
```js
var log = '';
for (let i = 0;i < 3;i++) {
a: for (x of [1, 2, 3,]) {
for (y of ['.', ':',]) {
log += x + y;
break a;
}
}
}
assertEq(log, "1.1.1.");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/break-3.js)
* [Unexpected Token at line: 3, column: 19: Expected `OpenBrace`; found Ident(Ident("Array"))](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-6.js)
<details>
```js
// for-of can be used to iterate over a Map twice.
var map = new Map([['a', 0], ['b', 1], ['c', 2]]);
var log = '';
for (let i = 0; i < 2; i++) {
for (let [k, v] of map)
log += k + v;
log += ';'
}
assertEq(log, 'a0b1c2;a0b1c2;');
```
vs
```js
var map = new Map([['a', 0,], ['b', 1,], ['c', 2,],]);
var log = '';
for (let i = 0;i < 2;i++) {
for ([k,v,] of map) log += k + v;
log += ';';
}
assertEq(log, 'a0b1c2;a0b1c2;');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-iterator-1.js)
<details>
```js
function assertThrowsInstanceOf() {}
gczeal(15)
try {
gczeal(10, 2)
} catch (Atomics) {}
for (define of[__defineSetter__]) {
let nonCallable = [{}]
for (let value of nonCallable) assertThrowsInstanceOf(TypeError)
key = {
[Symbol]() {}
}
}
```
vs
```js
function assertThrowsInstanceOf() { }
gczeal(15);
try {
gczeal(10, 2);
} catch (Atomics) {
}
for (define of [__defineSetter__,]) {
let nonCallable = [{ },];
for (value of nonCallable) assertThrowsInstanceOf(TypeError);
key = {
[Symbol]: function() { },
};
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/gc/bug-1278832.js)
<details>
```js
var emptyArray = [];
var denseArray = [1, 2, 3, 4];
var sparseArray = [1,,2,,3,,4];
var bigArray = new Array();
for (var i = 0; i < 128; i++) {
bigArray.push(i);
}
var nonArray = {0:1, 1:2, 2:3, 3:4, length:2};
var indexedGetterArray = new Array();
Object.defineProperty(indexedGetterArray, '2', {get:function () { return 51; }});
var ARRAYS = [emptyArray, denseArray, sparseArray, bigArray, nonArray, indexedGetterArray];
var targetFun = function (a, b, c, d) {
if (a === undefined)
a = 0;
if (b === undefined)
b = 0;
if (c === undefined)
c = 0;
if (d === undefined)
d = 0;
this.count += arguments.length + a + b + c + d;
}
var PERMUTATIONS = ARRAYS.length * ARRAYS.length;
function arrayPermutation(num) {
var idx1 = num % ARRAYS.length;
var idx2 = ((num / ARRAYS.length)|0) % ARRAYS.length;
var resultArray = [];
resultArray.push(ARRAYS[idx1]);
resultArray.push(ARRAYS[idx2]);
return resultArray;
}
var EXPECTED_RESULTS = {
0:0, 1:280, 2:200, 3:2680, 4:100, 5:1080, 6:280, 7:560, 8:480, 9:2960,
10:380, 11:1360, 12:200, 13:480, 14:400, 15:2880, 16:300, 17:1280, 18:2680,
19:2960, 20:2880, 21:5360, 22:2780, 23:3760, 24:100, 25:380, 26:300, 27:2780,
28:200, 29:1180, 30:1080, 31:1360, 32:1280, 33:3760, 34:1180, 35:2160
};
var callerNo = 0;
function generateCaller() {
var fn;
// Salt eval-string with callerNo to make sure eval caching doesn't take effect.
var s = "function caller" + callerNo + "(fn, thisObj, arrays) {" +
" for (var i = 0; i < arrays.length; i++) {" +
" fn.apply(thisObj, arrays[i]);" +
" }" +
"}" +
"fn = caller" + callerNo + ";";
eval(s);
return fn;
};
function main() {
for (var i = 0; i < PERMUTATIONS; i++) {
var obj = {count:0};
var arrs = arrayPermutation(i);
var fn = generateCaller(arrs.length);
// Loop 20 times so baseline compiler has chance to kick in and compile the scripts.
for (var j = 0; j < 20; j++)
fn(targetFun, obj, arrs);
assertEq(obj.count, EXPECTED_RESULTS[i]);
}
}
main();
```
vs
```js
var emptyArray = [];
var denseArray = [1, 2, 3, 4,];
var sparseArray = [1,, 2,, 3,, 4,];
var bigArray = new Array();
for (let i = 0;i < 128;i++) {
bigArray.push(i);
}
var nonArray = ({
0: 1,
1: 2,
2: 3,
3: 4,
length: 2,
});
var indexedGetterArray = new Array();
Object.defineProperty(indexedGetterArray, '2', ({
get: (function() {
return 51;
}),
}));
var ARRAYS = [emptyArray, denseArray, sparseArray, bigArray, nonArray, indexedGetterArray,];
var targetFun = (function(a, b, c, d) {
if (a === undefined) a = 0;
if (b === undefined) b = 0;
if (c === undefined) c = 0;
if (d === undefined) d = 0;
this.count += arguments.length + a + b + c + d;
});
var PERMUTATIONS = ARRAYS.length * ARRAYS.length;
function arrayPermutation(num) {
var idx1 = num % ARRAYS.length;
var idx2 = num / ARRAYS.length | 0 % ARRAYS.length;
var resultArray = [];
resultArray.push(ARRAYS[idx1]);
resultArray.push(ARRAYS[idx2]);
return resultArray;
}
var EXPECTED_RESULTS = ({
0: 0,
1: 280,
2: 200,
3: 2680,
4: 100,
5: 1080,
6: 280,
7: 560,
8: 480,
9: 2960,
10: 380,
11: 1360,
12: 200,
13: 480,
14: 400,
15: 2880,
16: 300,
17: 1280,
18: 2680,
19: 2960,
20: 2880,
21: 5360,
22: 2780,
23: 3760,
24: 100,
25: 380,
26: 300,
27: 2780,
28: 200,
29: 1180,
30: 1080,
31: 1360,
32: 1280,
33: 3760,
34: 1180,
35: 2160,
});
var callerNo = 0;
function generateCaller() {
var fn;
var s = "function caller" + callerNo + "(fn, thisObj, arrays) {" + " for (var i = 0; i < arrays.length; i++) {" + " fn.apply(thisObj, arrays[i]);" + " }" + "}" + "fn = caller" + callerNo + ";";
eval(s);
return fn;
}
;
function main() {
for (let i = 0;i < PERMUTATIONS;i++) {
var obj = {
count: 0,
};
var arrs = arrayPermutation(i);
var fn = generateCaller(arrs.length);
for (let j = 0;j < 20;j++) fn(targetFun, obj, arrs);
assertEq(obj.count, EXPECTED_RESULTS[i]);
}
}
main();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/baseline/funcall-array.js)
<details>
```js
// Superficial tests for iterators created by Array.prototype.iterator
load(libdir + "iteration.js");
var proto = Object.getPrototypeOf([][Symbol.iterator]());
var iterProto = Object.getPrototypeOf(proto);
proto = Object.getPrototypeOf([].keys());
assertEq(Object.getPrototypeOf(proto), iterProto);
proto = Object.getPrototypeOf([].entries());
assertEq(Object.getPrototypeOf(proto), iterProto);
function check(it) {
assertEq(typeof it, 'object');
assertEq(Object.getPrototypeOf(it), proto);
assertEq(Object.getOwnPropertyNames(it).length, 0);
assertEq(it[Symbol.iterator](), it);
// for-in enumerates the iterator's properties.
it.x = 0;
var s = '';
for (var p in it)
s += p + '.';
assertEq(s, 'x.');
}
check([][Symbol.iterator]());
check(Array.prototype[Symbol.iterator].call({}));
check([].keys());
check(Array.prototype.keys.call({}));
check([].entries());
check(Array.prototype.entries.call({}));
```
vs
```js
load(libdir + "iteration.js");
var proto = Object.getPrototypeOf([][Symbol.iterator]());
var iterProto = Object.getPrototypeOf(proto);
proto = Object.getPrototypeOf([].keys());
assertEq(Object.getPrototypeOf(proto), iterProto);
proto = Object.getPrototypeOf([].entries());
assertEq(Object.getPrototypeOf(proto), iterProto);
function check(it) {
assertEq(typeof it, 'object');
assertEq(Object.getPrototypeOf(it), proto);
assertEq(Object.getOwnPropertyNames(it).length, 0);
assertEq(it[Symbol.iterator](), it);
it.x = 0;
var s = '';
for (p in it) s += p + '.';
assertEq(s, 'x.');
}
check([][Symbol.iterator]());
check(Array.prototype[Symbol.iterator].call(({})));
check([].keys());
check(Array.prototype.keys.call(({})));
check([].entries());
check(Array.prototype.entries.call(({})));
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/array-iterator-surfaces-2.js)
<details>
```js
g = newGlobal();
g.parent = this;
function installHook() {
let calledTimes = 0;
function hook(frame) {
calledTimes++;
switch (calledTimes) {
case 1:
// Proxy get trap
assertEq(frame.type, "call");
assertEq(frame.script.displayName.includes("get"), true);
break;
case 2:
// wrapper function. There is no entry for notRun
assertEq(frame.type, "call");
assertEq(frame.script.displayName.includes("wrapper"), true);
break;
case 3:
assertEq(frame.type, "global");
// Force the top-level to return cleanly, so that we can tell
// assertion failures from the intended throwing.
return { return: undefined };
default:
// that's the whole chain.
assertEq(false, true);
}
}
Debugger(parent).onExceptionUnwind = hook;
}
g.eval("(" + installHook + ")()");
var handler = {
get(t, p) {
throw new TypeError;
}
};
function notRun() {}
function wrapper() {
var f = new Proxy(notRun, handler);
new f();
}
wrapper();
```
vs
```js
g = newGlobal();
g.parent = this;
function installHook() {
let calledTimes = 0;
function hook(frame) {
calledTimes++;
switch (calledTimes) {
case 1:
assertEq(frame.type, "call");
assertEq(frame.script.displayName.includes("get"), true);
break;
case 2:
assertEq(frame.type, "call");
assertEq(frame.script.displayName.includes("wrapper"), true);
break;
case 3:
assertEq(frame.type, "global");
return {
return: undefined,
};
default:
assertEq(false, true);
}
}
Debugger(parent).onExceptionUnwind = hook;
}
g.eval("(" + installHook + ")()");
var handler = ({
get: (function(t, p) {
throw new TypeError();
}),
});
function notRun() { }
function wrapper() {
var f = new Proxy(notRun, handler);
new f();
}
wrapper();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/prologueFailure-02.js)
* [Unable to re-interpret from expression to pattern at line: 11, column: 20](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/promise/user-activation-propagation.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug640608.js)
<details>
```js
// set.keys(), .values(), and .entries() on an empty set produce empty iterators
var s = new Set();
var ki = s.keys(), vi = s.values(), ei = s.entries();
var p = Object.getPrototypeOf(ki);
assertEq(Object.getPrototypeOf(vi), p);
assertEq(Object.getPrototypeOf(ei), p);
for (let k of ki)
throw "FAIL";
for (let v of vi)
throw "FAIL";
for (let [k, v] of ei)
throw "FAIL";
```
vs
```js
var s = new Set();
var ki = s.keys(), vi = s.values(), ei = s.entries();
var p = Object.getPrototypeOf(ki);
assertEq(Object.getPrototypeOf(vi), p);
assertEq(Object.getPrototypeOf(ei), p);
for (k of ki) throw "FAIL";
for (v of vi) throw "FAIL";
for ([k,v,] of ei) throw "FAIL";
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-values-1.js)
<details>
```js
// for-of can iterate arguments objects after returning.
load(libdir + "iteration.js");
function f() {
return arguments;
}
var s = '';
var args = f('a', 'b', 'c');
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
for (var v of args)
s += v;
assertEq(s, 'abc');
```
vs
```js
load(libdir + "iteration.js");
function f() {
return arguments;
}
var s = '';
var args = f('a', 'b', 'c');
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
for (v of args) s += v;
assertEq(s, 'abc');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arguments-2.js)
<details>
```js
// Test that SavedFrame instances are frozen and can't be messed with.
// Strict mode so that mutating frozen objects doesn't silently fail.
"use strict";
const s = saveStack();
load(libdir + 'asserts.js');
assertThrowsInstanceOf(() => s.source = "fake.url",
TypeError);
assertThrowsInstanceOf(() => {
Object.defineProperty(s.__proto__, "line", {
get: () => 0
})
}, TypeError);
```
vs
```js
'use strict';
const s = saveStack();
load(libdir + 'asserts.js');
assertThrowsInstanceOf(() => s.source = "fake.url", TypeError);
assertThrowsInstanceOf(() => {
Object.defineProperty(s.__proto__, "line", {
get: () => 0,
});
}, TypeError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/saved-stacks/stacks-are-frozen.js)
<details>
```js
// Using shift to cut values out of an array does not change the next index of an existing iterator.
var a = [1, 2, 3, 4, 5, 6, 7, 8];
var s = '';
for (var v of a) {
s += v;
a.shift();
}
assertEq(s, '1357');
```
vs
```js
var a = [1, 2, 3, 4, 5, 6, 7, 8,];
var s = '';
for (v of a) {
s += v;
a.shift();
}
assertEq(s, '1357');
```
<details>
```js
try { eval("3 ** 4") } catch (e) {
if (!(e instanceof SyntaxError))
throw e;
quit();
}
eval(`
gczeal(8);
for (var k = 0; k < 99; ++k) {
uneval(-(0 ** (Object | 0 * Object)))
}
`)
```
vs
```js
try {
eval("3 ** 4");
} catch (e) {
if (!e instanceof SyntaxError) throw e;
quit();
}
eval(`
gczeal(8);
for (var k = 0; k < 99; ++k) {
uneval(-(0 ** (Object | 0 * Object)))
}
`);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-shrinking-2.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/gc/bug-1259490.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/alias-function-closed.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug658209.js)
<details>
```js
// for-of can be used to iterate over a Set twice.
var set = new Set(['a', 'b', 'c']);
var log = '';
for (let i = 0; i < 2; i++) {
for (let x of set)
log += x;
log += ';'
}
assertEq(log, 'abc;abc;');
```
vs
```js
var set = new Set(['a', 'b', 'c',]);
var log = '';
for (let i = 0;i < 2;i++) {
for (x of set) log += x;
log += ';';
}
assertEq(log, 'abc;abc;');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-iterator-1.js)
<details>
```js
// |jit-test| error:dead object
var P = newGlobal().eval(`
(class extends Promise {
static resolve(o) {
return o;
}
});
`);
Promise.all.call(P, [{
then(r) {
nukeAllCCWs();
r();
}
}]);
```
vs
```js
var P = newGlobal().eval(`
(class extends Promise {
static resolve(o) {
return o;
}
});
`);
Promise.all.call(P, [({
then: (function(r) {
nukeAllCCWs();
r();
}),
}),]);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/promise/bug1406463.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
setJitCompilerOption("ion.warmup.trigger", 30);
var Vec3u16Type = TypedObject.uint16.array(3);
var PairVec3u16Type = new TypedObject.StructType({fst: Vec3u16Type,
snd: Vec3u16Type});
function foo_u16() {
for (var i = 0; i < 5000; i += 10) {
var p = new PairVec3u16Type();
p.fst[(i) % 3] = i;
p.fst[(i+1) % 3] = i+1;
p.fst[(i+2) % 3] = i+2;
p.snd[(i) % 3] = i+3;
p.snd[(i+1) % 3] = i+4;
p.snd[(i+2) % 3] = i+5;
var sum = p.fst[0] + p.fst[1] + p.fst[2];
assertEq(sum, 3*i + 3);
sum = p.snd[0] + p.snd[1] + p.snd[2];
assertEq(sum, 3*i + 12);
}
}
foo_u16();
```
vs
```js
setJitCompilerOption("ion.warmup.trigger", 30);
var Vec3u16Type = TypedObject.uint16.array(3);
var PairVec3u16Type = new TypedObject.StructType(({
fst: Vec3u16Type,
snd: Vec3u16Type,
}));
function foo_u16() {
for (let i = 0;i < 5000;i += 10) {
var p = new PairVec3u16Type();
p.fst[i % 3] = i;
p.fst[i + 1 % 3] = i + 1;
p.fst[i + 2 % 3] = i + 2;
p.snd[i % 3] = i + 3;
p.snd[i + 1 % 3] = i + 4;
p.snd[i + 2 % 3] = i + 5;
var sum = p.fst[0] + p.fst[1] + p.fst[2];
assertEq(sum, 3 * i + 3);
sum = p.snd[0] + p.snd[1] + p.snd[2];
assertEq(sum, 3 * i + 12);
}
}
foo_u16();
```
* [round-trip differed: var s = new Set(Array(1000).fill(0).map((v, k) => k + 1));
do {
var n = [...s].length;
assertEq(n, 1000);
} while (!inIon());
vs var s = new Set(Array(1000).fill(0).map((v, k) => k + 1));
do {
var n = [...s,].length;
assertEq(n, 1000);
} while (!inIon());
;
](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/bug-1381423.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/TypedObject/jit-write-u16-into-u16-array-in-struct.js)
* [Unable to re-interpret from expression to pattern at line: 18, column: 12](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/promise/settle-now-breaks-all-invariants-2.js)
<details>
```js
// getLineOffsets works with extended instructions, such as JSOP_GOTOX.
var g = newGlobal();
g.line0 = null;
var dbg = Debugger(g);
var where;
dbg.onDebuggerStatement = function (frame) {
var s = frame.script;
var offs;
var lineno = g.line0 + where;
offs = s.getLineOffsets(lineno);
for (var i = 0; i < offs.length; i++) {
assertEq(s.getOffsetLocation(offs[i]).lineNumber, lineno);
s.setBreakpoint(offs[i], {hit: function (frame) { g.log += 'B'; }});
}
g.log += 'A';
};
function test(s) {
assertEq(s.charAt(s.length - 1) !== '\n', true);
var count = s.split(/\n/).length; // number of lines in s
g.i = 0;
g.log = '';
where = 1 + count;
g.eval("line0 = Error().lineNumber;\n" +
"debugger;\n" + // line0 + 1
s + // line0 + 2 ... line0 + where
" log += 'C';\n");
assertEq(g.log, 'ABC');
}
function repeat(s) {
return Array((1 << 14) + 1).join(s); // 16K copies of s
}
var long_expr = "i" + repeat(" + i");
var long_throw_stmt = "throw " + long_expr + ";\n";
// long break (JSOP_GOTOX)
test("for (;;) {\n" +
" if (i === 0)\n" +
" break;\n" +
" " + long_throw_stmt +
"}");
// long continue (JSOP_GOTOX)
test("do {\n" +
" if (i === 0)\n" +
" continue;\n" +
" " + long_throw_stmt +
"} while (i !== 0);");
// long if consequent (JSOP_IFEQX)
test("if (i === 2) {\n" +
" " + long_throw_stmt +
"}");
// long catch-block with finally (JSOP_GOSUBX)
test("try {\n" +
" i = 0;\n" +
"} catch (exc) {\n" +
" throw " + long_expr + ";\n" +
"} finally {\n" +
" i = 1;\n" +
"}");
// long case (JSOP_TABLESWITCHX)
test("switch (i) {\n" +
" default:\n" +
" case 1: " + long_throw_stmt +
" case 0: i++; }");
test("switch (i) {\n" +
" case 1: case 2: case 3: " + long_throw_stmt +
" default: i++; }");
// long case (JSOP_LOOKUPSWITCHX)
test("switch ('' + i) {\n" +
" default:\n" +
" case '1': " + long_throw_stmt +
" case '0': i++; }");
test("switch (i) {\n" +
" case '1': case '2': case '3': " + long_throw_stmt +
" default: i++; }");
// long case or case-expression (JSOP_CASEX)
test("switch (i) {\n" +
" case i + 1 - i:\n" +
" default:\n" +
" " + long_throw_stmt +
" case i + i:\n" +
" i++; break; }");
// long case when JSOP_CASE is used (JSOP_DEFAULTX)
test("switch (i) {\n" +
" case i + 1 - i:\n" +
" " + long_throw_stmt +
" default:\n" +
" i++; break; }");
```
vs
```js
var g = newGlobal();
g.line0 = null;
var dbg = Debugger(g);
var where;
dbg.onDebuggerStatement = (function(frame) {
var s = frame.script;
var offs;
var lineno = g.line0 + where;
offs = s.getLineOffsets(lineno);
for (let i = 0;i < offs.length;i++) {
assertEq(s.getOffsetLocation(offs[i]).lineNumber, lineno);
s.setBreakpoint(offs[i], {
hit: function(frame) {
g.log += 'B';
},
});
}
g.log += 'A';
});
function test(s) {
assertEq(s.charAt(s.length - 1) !== '\n', true);
var count = s.split(/\n/).length;
g.i = 0;
g.log = '';
where = 1 + count;
g.eval("line0 = Error().lineNumber;\n" + "debugger;\n" + s + " log += 'C';\n");
assertEq(g.log, 'ABC');
}
function repeat(s) {
return Array(1 << 14 + 1).join(s);
}
var long_expr = "i" + repeat(" + i");
var long_throw_stmt = "throw " + long_expr + ";\n";
test("for (;;) {\n" + " if (i === 0)\n" + " break;\n" + " " + long_throw_stmt + "}");
test("do {\n" + " if (i === 0)\n" + " continue;\n" + " " + long_throw_stmt + "} while (i !== 0);");
test("if (i === 2) {\n" + " " + long_throw_stmt + "}");
test("try {\n" + " i = 0;\n" + "} catch (exc) {\n" + " throw " + long_expr + ";\n" + "} finally {\n" + " i = 1;\n" + "}");
test("switch (i) {\n" + " default:\n" + " case 1: " + long_throw_stmt + " case 0: i++; }");
test("switch (i) {\n" + " case 1: case 2: case 3: " + long_throw_stmt + " default: i++; }");
test("switch ('' + i) {\n" + " default:\n" + " case '1': " + long_throw_stmt + " case '0': i++; }");
test("switch (i) {\n" + " case '1': case '2': case '3': " + long_throw_stmt + " default: i++; }");
test("switch (i) {\n" + " case i + 1 - i:\n" + " default:\n" + " " + long_throw_stmt + " case i + i:\n" + " i++; break; }");
test("switch (i) {\n" + " case i + 1 - i:\n" + " " + long_throw_stmt + " default:\n" + " i++; break; }");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Script-getLineOffsets-06.js)
<details>
```js
try {
[0,0].sort(Array.some)
"".replace(RegExp(), Array.reduce)
} catch (error) {
if (!(error instanceof TypeError && /^\w is not a function$/.test(error.message)))
throw error;
}
```
vs
```js
try {
[0, 0,].sort(Array.some);
"".replace(RegExp(), Array.reduce);
} catch (error) {
if (!error instanceof TypeError && /^\w is not a function$/.test(error.message)) throw error;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/self-hosting/invoke-self-hosted-with-primitive-this.js)
<details>
```js
load(libdir + "asserts.js");
var cases = [
"{",
"{ ;",
"var",
"var x,",
"var x =",
"let x,",
"let x =",
"const",
"const x =",
"const x = 1,",
"if",
"if (",
"if (0) ; else",
"do",
"do ;",
"do ; while",
"do ; while (",
"do ; while (1",
"while",
"while (",
"while (1",
"while (1)",
"for",
"for (",
"for (;",
"for (;;",
"for (;;)",
"for (var",
"for (x",
"for (x in",
"for (x in y",
"for (x in y)",
"for (x of",
"for (x of y",
"for (x of y)",
"switch",
"switch (",
"switch (x",
"switch (x)",
"with",
"with (",
"with (x",
"with (x)",
"a:",
"throw",
"try",
"try {",
"try {} catch",
"try {} catch (",
"try {} catch (exc",
"try {} catch (exc if",
"try {} catch (exc if 1",
"try {} finally",
"try {} finally {",
"function",
"function f",
"function f(",
"function f()",
"function f() {",
"(function",
"(function f",
"(function f(",
"(function f()",
];
for (var s of cases)
assertThrowsInstanceOf(() => Function(s), SyntaxError);
```
vs
```js
load(libdir + "asserts.js");
var cases = ["{", "{ ;", "var", "var x,", "var x =", "let x,", "let x =", "const", "const x =", "const x = 1,", "if", "if (", "if (0) ; else", "do", "do ;", "do ; while", "do ; while (", "do ; while (1", "while", "while (", "while (1", "while (1)", "for", "for (", "for (;", "for (;;", "for (;;)", "for (var", "for (x", "for (x in", "for (x in y", "for (x in y)", "for (x of", "for (x of y", "for (x of y)", "switch", "switch (", "switch (x", "switch (x)", "with", "with (", "with (x", "with (x)", "a:", "throw", "try", "try {", "try {} catch", "try {} catch (", "try {} catch (exc", "try {} catch (exc if", "try {} catch (exc if 1", "try {} finally", "try {} finally {", "function", "function f", "function f(", "function f()", "function f() {", "(function", "(function f", "(function f(", "(function f()",];
for (s of cases) assertThrowsInstanceOf(() => Function(s), SyntaxError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/truncation.js)
<details>
```js
// Slowifying an array while it is being iterated does not affect iteration.
var a = [9, 8, 7, 6, 5, 4, 3];
var log = '';
for (var x of a) {
log += x;
if (x === 6)
a.slow = true;
}
assertEq(log, "9876543");
```
vs
```js
var a = [9, 8, 7, 6, 5, 4, 3,];
var log = '';
for (x of a) {
log += x;
if (x === 6) a.slow = true;
}
assertEq(log, "9876543");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-slow-5.js)
<details>
```js
var path = '';
// trigger off-main-thread compilation
for (var i = 0; i < 11; i++)
path.substr(-1);
// maybe link to the the result of the off-main-thread compilation.
function load(unsigned) {
if (unsigned)
path.substr(-1);
}
(function(global, env) {
'use asm';
var load = env.load;
function _main() {
var $l1 = 0, $l2 = 0, $l3 = 0;
do {
load();
$l1 = $l1 + 1 | 0;
} while (($l1 | 0) != 10);
load(1);
load(1);
do {
load();
$l2 = $l2 + 1 | 0;
} while (($l2 | 0) != 1024);
while (($l3 | 0) < 10000) {
load(1);
$l3 = $l3 + 1 | 0;
}
}
return _main;
})({}, { 'load':load })();
```
vs
```js
var path = '';
for (let i = 0;i < 11;i++) path.substr(-1);
function load(unsigned) {
if (unsigned) path.substr(-1);
}
(function(global, env) {
'use asm';
var load = env.load;
function _main() {
var $l1 = 0, $l2 = 0, $l3 = 0;
do {
load();
$l1 = $l1 + 1 | 0;
} while ($l1 | 0 != 10);
;
load(1);
load(1);
do {
load();
$l2 = $l2 + 1 | 0;
} while ($l2 | 0 != 1024);
;
while ($l3 | 0 < 10000) {
load(1);
$l3 = $l3 + 1 | 0;
}
}
return _main;
})(({}), ({
'load': load,
}))();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/lazyLink-bug1150783.js)
* [Unexpected Token at line: 10, column: 9: Found unexpected token: =; Not at assignment target](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/baseline/setcall.js)
<details>
```js
function foo(x) {
"use strict";
var ok = false;
try {
x.c = 10;
} catch(e) {
ok = true;
}
assertEq(ok, true);
assertEq(x.c, undefined);
}
x = {a:0,b:1};
Object.freeze(x);
foo(x);
```
vs
```js
function foo(x) {
'use strict';
var ok = false;
try {
x.c = 10;
} catch (e) {
ok = true;
}
assertEq(ok, true);
assertEq(x.c, undefined);
}
x = ({
a: 0,
b: 1,
});
Object.freeze(x);
foo(x);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/define-frozen-property-strict.js)
<details>
```js
// A break statement leaves only a single for-of loop.
var log = '';
for (var x of [1, 2, 3]) {
for (var y of ['.', ':']) {
log += x + y;
break;
}
}
assertEq(log, "1.2.3.");
```
vs
```js
var log = '';
for (x of [1, 2, 3,]) {
for (y of ['.', ':',]) {
log += x + y;
break;
}
}
assertEq(log, "1.2.3.");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/break-2.js)
<details>
```js
// new Map(x) throws if x is not iterable (unless x is undefined).
load(libdir + "asserts.js");
var nonIterables = [true, 1, -0, 3.14, NaN, {}, Math, this];
for (let k of nonIterables)
assertThrowsInstanceOf(function () { new Map(k); }, TypeError);
```
vs
```js
load(libdir + "asserts.js");
var nonIterables = [true, 1, -0, 3.14, NaN, ({}), Math, this,];
for (k of nonIterables) assertThrowsInstanceOf(function() {
new Map(k);
}, TypeError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-constructor-4.js)
<details>
```js
load(libdir + "asserts.js");
let foo = {};
for (let method of ["resolve", "reject", "race"]) {
assertErrorMessage(
() => Promise[method].call(foo),
TypeError,
"foo is not a constructor"
);
assertErrorMessage(
() => Promise[method].call(foo, []),
TypeError,
"foo is not a constructor"
);
assertErrorMessage(
() => Promise[method].call({}, [], foo),
TypeError,
"({}) is not a constructor"
);
}
```
vs
```js
load(libdir + "asserts.js");
let foo = ({});
for (method of ["resolve", "reject", "race",]) {
assertErrorMessage(() => Promise[method].call(foo), TypeError, "foo is not a constructor");
assertErrorMessage(() => Promise[method].call(foo, []), TypeError, "foo is not a constructor");
assertErrorMessage(() => Promise[method].call({ }, [], foo), TypeError, "({}) is not a constructor");
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/promise/newpromisecapability-error-message.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/gc/bug-906236.js)
<details>
```js
// Test that Ion->Baseline in-place debug mode bailout can recover the iterator
// from the snapshot in a for-of loop.
g = newGlobal();
g.parent = this;
g.eval("Debugger(parent).onExceptionUnwind=(function() {})");
function* throwInNext() {
yield 1;
yield 2;
yield 3;
throw 42;
}
function f() {
for (var o of throwInNext());
}
var log = "";
try {
f();
} catch (e) {
log += e;
}
assertEq(log, "42");
```
vs
```js
g = newGlobal();
g.parent = this;
g.eval("Debugger(parent).onExceptionUnwind=(function() {})");
function *throwInNext() {
yield 1;
yield 2;
yield 3;
throw 42;
}
function f() {
for (o of throwInNext()) ;
}
var log = "";
try {
f();
} catch (e) {
log += e;
}
assertEq(log, "42");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/onExceptionUnwind-15.js)
<details>
```js
// |jit-test| error: Error
var g = newGlobal();
g.eval('function f(a) { evaluate("f(" + " - 1);", {newContext: true}); }');
var dbg = new Debugger(g);
var frames = [];
dbg.onEnterFrame = function (frame) {
if (frames.length == 3)
return;
frames.push(frame);
for (var f of frames)
f.eval('a').return
};
g.f();
```
vs
```js
var g = newGlobal();
g.eval('function f(a) { evaluate("f(" + " - 1);", {newContext: true}); }');
var dbg = new Debugger(g);
var frames = [];
dbg.onEnterFrame = (function(frame) {
if (frames.length == 3) return;
frames.push(frame);
for (f of frames) f.eval('a').return;
});
g.f();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/bug1148917.js)
<details>
```js
// |jit-test| error: ReferenceError
if (!('oomTest' in this))
a;
enableShellAllocationMetadataBuilder()
oomTest(() => {
newGlobal()
})
gczeal(9, 1);
a;
```
vs
```js
if (!'oomTest' in this) a;
enableShellAllocationMetadataBuilder();
oomTest(() => {
newGlobal();
});
gczeal(9, 1);
a;
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/gc/bug-1215678.js)
* [Unexpected Token at line: 3, column: 32: Expected `function`, `this`, `class`, or `import`; found Keyword(Await)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/promise/settle-now-breaks-all-invariants-8.js)
<details>
```js
// Debugger.Object.prototype.{errorLineNumber,errorColumnNumber} return the
// line number and column number associated with some error object.
var g = newGlobal();
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
var syntaxError = gw.executeInGlobal("\nlet a, a;").throw;
assertEq(syntaxError.errorLineNumber, 2);
assertEq(syntaxError.errorColumnNumber, 7);
var typeError = gw.executeInGlobal("\n1 + f();").throw;
assertEq(typeError.errorLineNumber, 2);
assertEq(typeError.errorColumnNumber, 1);
// Custom errors have no line/column numbers .
var customError = gw.executeInGlobal("\nthrow 1;").throw;
assertEq(customError.errorLineNumber, undefined);
assertEq(customError.errorColumnNumber, undefined);
customError = gw.executeInGlobal("\nthrow { errorLineNumber: 10, errorColumnNumber: 20 };").throw;
assertEq(customError.errorLineNumber, undefined);
assertEq(customError.errorColumnNumber, undefined);
customError = gw.executeInGlobal("\nthrow { lineNumber: 10, columnNumber: 20 };").throw;
assertEq(customError.errorLineNumber, undefined);
assertEq(customError.errorColumnNumber, undefined);
// Ensure that the method works across globals.
g.eval(`var g = newGlobal();
g.eval('var err; \\n' +
'try {\\n' +
' f();\\n' +
'} catch (e) {\\n' +
' err = e;\\n' +
'}');
var err2 = g.err;`);
var otherGlobalError = gw.executeInGlobal("throw err2").throw;
assertEq(otherGlobalError.errorLineNumber, 3);
assertEq(otherGlobalError.errorColumnNumber, 3);
// Ensure that non-error objects return undefined.
const Args = [
"1",
"'blah'",
"({})",
"[]",
"() => 1"
]
for (let arg of Args) {
let nonError = gw.executeInGlobal(`${arg}`).return;
assertEq(nonError.errorLineNumber, undefined);
assertEq(nonError.errorColumnNumber, undefined);
}
```
vs
```js
var g = newGlobal();
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
var syntaxError = gw.executeInGlobal("\nlet a, a;").throw;
assertEq(syntaxError.errorLineNumber, 2);
assertEq(syntaxError.errorColumnNumber, 7);
var typeError = gw.executeInGlobal("\n1 + f();").throw;
assertEq(typeError.errorLineNumber, 2);
assertEq(typeError.errorColumnNumber, 1);
var customError = gw.executeInGlobal("\nthrow 1;").throw;
assertEq(customError.errorLineNumber, undefined);
assertEq(customError.errorColumnNumber, undefined);
customError = gw.executeInGlobal("\nthrow { errorLineNumber: 10, errorColumnNumber: 20 };").throw;
assertEq(customError.errorLineNumber, undefined);
assertEq(customError.errorColumnNumber, undefined);
customError = gw.executeInGlobal("\nthrow { lineNumber: 10, columnNumber: 20 };").throw;
assertEq(customError.errorLineNumber, undefined);
assertEq(customError.errorColumnNumber, undefined);
g.eval(`var g = newGlobal();
g.eval('var err; \\n' +
'try {\\n' +
' f();\\n' +
'} catch (e) {\\n' +
' err = e;\\n' +
'}');
var err2 = g.err;`);
var otherGlobalError = gw.executeInGlobal("throw err2").throw;
assertEq(otherGlobalError.errorLineNumber, 3);
assertEq(otherGlobalError.errorColumnNumber, 3);
const Args = ["1", "'blah'", "({})", "[]", "() => 1",];
for (arg of Args) {
let nonError = gw.executeInGlobal(`${arg}`).return;
assertEq(nonError.errorLineNumber, undefined);
assertEq(nonError.errorColumnNumber, undefined);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Object-errorLineNumber-errorColumnNumber.js)
<details>
```js
// Source.prototype.url can be a string or null.
var g = newGlobal();
var dbg = new Debugger;
var gw = dbg.addDebuggee(g);
for (var fileName of ['file:///var/foo.js', null]) {
g.evaluate("function f(x) { return 2*x; }", {fileName: fileName});
var fw = gw.getOwnPropertyDescriptor('f').value;
assertEq(fw.script.source.url, fileName);
}
```
vs
```js
var g = newGlobal();
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
for (fileName of ['file:///var/foo.js', null,]) {
g.evaluate("function f(x) { return 2*x; }", {
fileName: fileName,
});
var fw = gw.getOwnPropertyDescriptor('f').value;
assertEq(fw.script.source.url, fileName);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Source-url.js)
* [Unexpected Token at line: 3, column: 14: Expected `function`, `this`, `class`, or `import`; found Keyword(Import)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/modules/import-meta-oom.js)
<details>
```js
// Destructuring assignment to eval or arguments in destructuring is a SyntaxError
// in strict mode
load(libdir + "asserts.js");
var patterns = [
"[_]",
"[a, b, _]",
"[[_]]",
"[[], [{}, [_]]]",
"{x:_}",
"{x:y, z:_}",
"{0:_}",
"{_}",
"[..._]"
];
for (var pattern of patterns) {
var stmt = pattern + " = obj";
if (stmt[0] == "{")
stmt = "(" + stmt + ")";
stmt += ";"
// stmt is a legal statement...
Function(stmt);
// ...but not if you replace _ with one of these two names.
for (var name of ["eval", "arguments"]) {
var s = stmt.replace("_", name);
Function(s);
assertThrowsInstanceOf(() => Function("'use strict'; " + s), SyntaxError);
}
}
```
vs
```js
load(libdir + "asserts.js");
var patterns = ["[_]", "[a, b, _]", "[[_]]", "[[], [{}, [_]]]", "{x:_}", "{x:y, z:_}", "{0:_}", "{_}", "[..._]",];
for (pattern of patterns) {
var stmt = pattern + " = obj";
if (stmt[0] == "{") stmt = "(" + stmt + ")";
stmt += ";";
Function(stmt);
for (name of ["eval", "arguments",]) {
var s = stmt.replace("_", name);
Function(s);
assertThrowsInstanceOf(() => Function("'use strict'; " + s), SyntaxError);
}
}
```
<details>
```js
gczeal(7, 1);
enableShellAllocationMetadataBuilder();
var testMap = new Map();
for (var [k, v] of testMap) {}
```
vs
```js
gczeal(7, 1);
enableShellAllocationMetadataBuilder();
var testMap = new Map();
for ([k,v,] of testMap) {
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/gc/bug-1399889.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-889628.js)
<details>
```js
do 1
while(false);
do if (1) {
} while(false);
do if (1) 1
while(false);
do try {
} catch(ex) {
} while(false);
```
vs
```js
do 1;
while (false);
;
do if (1) {
}
while (false);
;
do if (1) 1;
while (false);
;
do try {
} catch (ex) {
}
while (false);
;
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/modifier-do-while.js)
<details>
```js
var g = newGlobal();
var dbg = new Debugger(g);
var visibleFrames = 0;
dbg.onEnterFrame = function (frame) {
print("> " + frame.script.url);
visibleFrames++;
}
g.eval("(" + function iife() {
[1].forEach(function noop() {});
for (let x of [1]) {}
} + ")()");
// 1 for eval, 1 for iife(), 1 for noop()
assertEq(visibleFrames, 3);
```
vs
```js
var g = newGlobal();
var dbg = new Debugger(g);
var visibleFrames = 0;
dbg.onEnterFrame = (function(frame) {
print("> " + frame.script.url);
visibleFrames++;
});
g.eval("(" + (function iife() {
[1,].forEach(function noop() { });
for (x of [1,]) {
}
}) + ")()");
assertEq(visibleFrames, 3);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/onEnterFrame-07.js)
<details>
```js
// |jit-test| error: ReferenceError
var t = {};
function r(y) { return t.y = y; }
function g() {
for (let [x = r(x)] of x) {}
}
r(0);
r(0);
g();
```
vs
```js
var t = ({});
function r(y) {
return t.y = y;
}
function g() {
for ([x = r(x),] of x) {
}
}
r(0);
r(0);
g();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/bug1368360-1.js)
<details>
```js
// onPop fires while the [[GeneratorState]] is still "executing".
//
// This test checks that Debugger doesn't accidentally make it possible to
// reenter a generator frame that's on the stack.
load(libdir + "asserts.js");
let g = newGlobal();
g.eval('function* f() { debugger; yield 1; debugger; yield 2; debugger; }');
let dbg = Debugger(g);
let genObj = g.f();
let hits = 0;
dbg.onDebuggerStatement = frame => {
frame.onPop = completion => {
dbg.removeDebuggee(g); // avoid the DebuggeeWouldRun exception
hits++;
if (hits < 3) {
// We're yielding. Calling .return(), .next(), or .throw() on a
// generator that's currently on the stack fails with a TypeError.
assertThrowsInstanceOf(() => genObj.next(), g.TypeError);
assertThrowsInstanceOf(() => genObj.throw("fit"), g.TypeError);
assertThrowsInstanceOf(() => genObj.return(), g.TypeError);
} else {
// This time we're returning. The generator has already been
// closed, so its methods work but are basically no-ops.
let result = genObj.next();
assertEq(result.done, true);
assertEq(result.value, undefined);
assertThrowsValue(() => genObj.throw("fit"), "fit");
result = genObj.return();
assertEq(result.done, true);
assertEq(result.value, undefined);
}
dbg.addDebuggee(g);
};
};
for (let x of genObj) {}
assertEq(hits, 3);
```
vs
```js
load(libdir + "asserts.js");
let g = newGlobal();
g.eval('function* f() { debugger; yield 1; debugger; yield 2; debugger; }');
let dbg = Debugger(g);
let genObj = g.f();
let hits = 0;
dbg.onDebuggerStatement = frame => {
frame.onPop = completion => {
dbg.removeDebuggee(g);
hits++;
if (hits < 3) {
assertThrowsInstanceOf(() => genObj.next(), g.TypeError);
assertThrowsInstanceOf(() => genObj.throw("fit"), g.TypeError);
assertThrowsInstanceOf(() => genObj.return(), g.TypeError);
} else {
let result = genObj.next();
assertEq(result.done, true);
assertEq(result.value, undefined);
assertThrowsValue(() => genObj.throw("fit"), "fit");
result = genObj.return();
assertEq(result.done, true);
assertEq(result.value, undefined);
}
dbg.addDebuggee(g);
};
};
for (x of genObj) {
}
assertEq(hits, 3);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Frame-onPop-generators-03.js)
<details>
```js
function test(name) {
eval(`
function ${name}(stdlib, foreign, heap) {
"use asm";
var ffi = foreign.t;
return {};
}
${name}(15, 10);
`);
}
test("as");
test("async");
test("await");
test("each");
test("from");
test("get");
test("let");
test("of");
test("set");
test("static");
test("target");
```
vs
```js
function test(name) {
eval(`
function ${name}(stdlib, foreign, heap) {
"use asm";
var ffi = foreign.t;
return {};
}
{name}(15, 10);
`);
}
test("as");
test("async");
test("await");
test("each");
test("from");
test("get");
test("let");
test("of");
test("set");
test("static");
test("target");
```
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
load(libdir + 'array-compare.js');
function strictNestedShadowEval(code, p)
{
"use strict";
function inner(p) { eval(code); }
return arguments;
}
var a1, a2, a3, a4, a5, a6;
for (var i = 0; i < 5; i++)
{
a1 = strictNestedShadowEval("1", 2);
a2 = strictNestedShadowEval("arguments");
a3 = strictNestedShadowEval("p = 2");
a4 = strictNestedShadowEval("p = 2", 17);
a5 = strictNestedShadowEval("arguments[0] = 17");
a6 = strictNestedShadowEval("arguments[0] = 17", 42);
}
assertEq(arraysEqual(a1, ["1", 2]), true);
assertEq(arraysEqual(a2, ["arguments"]), true);
assertEq(arraysEqual(a3, ["p = 2"]), true);
assertEq(arraysEqual(a4, ["p = 2", 17]), true);
assertEq(arraysEqual(a5, ["arguments[0] = 17"]), true);
assertEq(arraysEqual(a6, ["arguments[0] = 17", 42]), true);
```
vs
```js
load(libdir + 'array-compare.js');
function strictNestedShadowEval(code, p) {
'use strict';
function inner(p) {
eval(code);
}
return arguments;
}
var a1, a2, a3, a4, a5, a6;
for (let i = 0;i < 5;i++) {
a1 = strictNestedShadowEval("1", 2);
a2 = strictNestedShadowEval("arguments");
a3 = strictNestedShadowEval("p = 2");
a4 = strictNestedShadowEval("p = 2", 17);
a5 = strictNestedShadowEval("arguments[0] = 17");
a6 = strictNestedShadowEval("arguments[0] = 17", 42);
}
assertEq(arraysEqual(a1, ["1", 2,]), true);
assertEq(arraysEqual(a2, ["arguments",]), true);
assertEq(arraysEqual(a3, ["p = 2",]), true);
assertEq(arraysEqual(a4, ["p = 2", 17,]), true);
assertEq(arraysEqual(a5, ["arguments[0] = 17",]), true);
assertEq(arraysEqual(a6, ["arguments[0] = 17", 42,]), true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/standalone-function-name.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/strict-nested-shadow-eval.js)
<details>
```js
var wm = new WeakMap;
var A = [];
for (var i = 0; i < 1024; ++i) {
var key = {i:i};
wm.set(key, i);
A.push(key);
}
gc();
for (var i in A) {
var key = A[i];
assertEq(wm.has(key), true);
}
```
vs
```js
var wm = new WeakMap();
var A = [];
for (let i = 0;i < 1024;++i) {
var key = {
i: i,
};
wm.set(key, i);
A.push(key);
}
gc();
for (i in A) {
var key = A[i];
assertEq(wm.has(key), true);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/WeakMap-moving-gc.js)
<details>
```js
(function() {
"use strict";
assertEq(eval("this"), undefined);
})();
```
vs
```js
(function() {
'use strict';
assertEq(eval("this"), undefined);
})();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/baseline/bug916039.js)
<details>
```js
var g = newGlobal();
g.eval("azx918 = 1");
for (var x in g) {
assertEq(x, x);
}
```
vs
```js
var g = newGlobal();
g.eval("azx918 = 1");
for (x in g) {
assertEq(x, x);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/bug1420961.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/baseline/bug842430.js)
<details>
```js
// for-of works on a cross-compartment wrapper of a Map.
var g = newGlobal();
var mw = g.eval("new Map([['a', 1], ['b', 2]])");
var log = '';
for (let [k, v] of mw)
log += k + v;
assertEq(log, "a1b2");
```
vs
```js
var g = newGlobal();
var mw = g.eval("new Map([['a', 1], ['b', 2]])");
var log = '';
for ([k,v,] of mw) log += k + v;
assertEq(log, "a1b2");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-iterator-proxies-1.js)
* [Unexpected Token at line: 29, column: 24: Expected `Comma`; found Punct(Exponent)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Debugger-findScripts-uncompleted-01.js)
* [Unable to re-interpret from expression to pattern at line: 18, column: 12](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/promise/settle-now-breaks-all-invariants-3.js)
<details>
```js
// |jit-test| skip-if: !('oomTest' in this)
var x = ``.split();
oomTest(function() {
var lfGlobal = newGlobal({sameZoneAs: this});
for (lfLocal in this) {
if (!(lfLocal in lfGlobal)) {
lfGlobal[lfLocal] = this[lfLocal];
}
}
});
```
vs
```js
var x = ``.split();
oomTest((function() {
var lfGlobal = newGlobal({
sameZoneAs: this,
});
for (lfLocal in this) {
if (!lfLocal in lfGlobal) {
lfGlobal[lfLocal] = this[lfLocal];
}
}
}));
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/gc/bug-1303015.js)
* [Unexpected Token at line: 4, column: 31: Expected `OpenBrace`; found Ident(Ident("Array"))](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-8.js)
<details>
```js
load(libdir + "match.js");
load(libdir + "asserts.js");
var { Pattern, MatchError } = Match;
program = (elts) => Pattern({
type: "Program",
body: elts
});
expressionStatement = (expression) => Pattern({
type: "ExpressionStatement",
expression: expression
});
assignmentExpression = (left, operator, right) => Pattern({
type: "AssignmentExpression",
operator: operator,
left: left,
right: right
});
ident = (name) => Pattern({
type: "Identifier",
name: name
});
importCall = (ident, singleArg) => Pattern({
type: "CallImport",
ident: ident,
arg: singleArg
});
function parseAsClassicScript(source)
{
return Reflect.parse(source);
}
function parseAsModuleScript(source)
{
return Reflect.parse(source, {target: "module"});
}
for (let parse of [parseAsModuleScript, parseAsClassicScript]) {
program([
expressionStatement(
importCall(
ident("import"),
ident("foo")
)
)
]).assert(parse("import(foo);"));
program([
expressionStatement(
assignmentExpression(
ident("x"),
"=",
importCall(
ident("import"),
ident("foo")
)
)
)
]).assert(parse("x = import(foo);"));
}
function assertParseThrowsSyntaxError(source)
{
assertThrowsInstanceOf(() => parseAsClassicScript(source), SyntaxError);
assertThrowsInstanceOf(() => parseAsModuleScript(source), SyntaxError);
}
assertParseThrowsSyntaxError("import");
assertParseThrowsSyntaxError("import(");
assertParseThrowsSyntaxError("import(1,");
assertParseThrowsSyntaxError("import(1, 2");
assertParseThrowsSyntaxError("import(1, 2)");
assertParseThrowsSyntaxError("x = import");
assertParseThrowsSyntaxError("x = import(");
assertParseThrowsSyntaxError("x = import(1,");
assertParseThrowsSyntaxError("x = import(1, 2");
assertParseThrowsSyntaxError("x = import(1, 2)");
```
vs
```js
load(libdir + "match.js");
load(libdir + "asserts.js");
var {Pattern, MatchError,} = Match;
program = elts => Pattern({
type: "Program",
body: elts,
});
expressionStatement = expression => Pattern({
type: "ExpressionStatement",
expression: expression,
});
assignmentExpression = (left, operator, right) => Pattern({
type: "AssignmentExpression",
operator: operator,
left: left,
right: right,
});
ident = name => Pattern({
type: "Identifier",
name: name,
});
importCall = (ident, singleArg) => Pattern({
type: "CallImport",
ident: ident,
arg: singleArg,
});
function parseAsClassicScript(source) {
return Reflect.parse(source);
}
function parseAsModuleScript(source) {
return Reflect.parse(source, {
target: "module",
});
}
for (parse of [parseAsModuleScript, parseAsClassicScript,]) {
program([expressionStatement(importCall(ident("import"), ident("foo"))),]).assert(parse("import(foo);"));
program([expressionStatement(assignmentExpression(ident("x"), "=", importCall(ident("import"), ident("foo")))),]).assert(parse("x = import(foo);"));
}
function assertParseThrowsSyntaxError(source) {
assertThrowsInstanceOf(() => parseAsClassicScript(source), SyntaxError);
assertThrowsInstanceOf(() => parseAsModuleScript(source), SyntaxError);
}
assertParseThrowsSyntaxError("import");
assertParseThrowsSyntaxError("import(");
assertParseThrowsSyntaxError("import(1,");
assertParseThrowsSyntaxError("import(1, 2");
assertParseThrowsSyntaxError("import(1, 2)");
assertParseThrowsSyntaxError("x = import");
assertParseThrowsSyntaxError("x = import(");
assertParseThrowsSyntaxError("x = import(1,");
assertParseThrowsSyntaxError("x = import(1, 2");
assertParseThrowsSyntaxError("x = import(1, 2)");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/modules/dynamic-import-expression.js)
<details>
```js
/* Handle recompilation of arithmetic operations, and on-stack int -> double conversion. */
function add(x, y)
{
var z = x + y;
assertEq(z, 2147483732);
assertEq(z - 10, 2147483722);
}
add(0x7ffffff0, 100);
function mul(x, y)
{
var z = x * y;
assertEq(z, 4294967264);
}
mul(0x7ffffff0, 2);
function div1(x, y)
{
var z = x / y;
assertEq(z + 10, 20);
}
div1(100, 10);
function div2(x, y)
{
var z = x / y;
assertEq(z + 10, 20.5);
}
div2(105, 10);
function uncopy(x, y)
{
var q = x;
x += y;
q++;
assertEq(q, 2147483633);
assertEq(x, 2147483732);
}
uncopy(0x7ffffff0, 100);
function addmore(x, y)
{
var q = (x + 10) + (x + y);
assertEq(q, 4294967374);
x = q;
}
addmore(0x7ffffff0, 100);
```
vs
```js
function add(x, y) {
var z = x + y;
assertEq(z, 2147483732);
assertEq(z - 10, 2147483722);
}
add(0x7ffffff0, 100);
function mul(x, y) {
var z = x * y;
assertEq(z, 4294967264);
}
mul(0x7ffffff0, 2);
function div1(x, y) {
var z = x / y;
assertEq(z + 10, 20);
}
div1(100, 10);
function div2(x, y) {
var z = x / y;
assertEq(z + 10, 20.5);
}
div2(105, 10);
function uncopy(x, y) {
var q = x;
x += y;
q++;
assertEq(q, 2147483633);
assertEq(x, 2147483732);
}
uncopy(0x7ffffff0, 100);
function addmore(x, y) {
var q = x + 10 + x + y;
assertEq(q, 4294967374);
x = q;
}
addmore(0x7ffffff0, 100);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/arith.js)
<details>
```js
// Check whether we respect resumption values when toggling debug mode on->off
// from various points with live scripts on the stack.
var g = newGlobal();
var dbg = new Debugger;
function reset() {
dbg.onEnterFrame = undefined;
dbg.onDebuggerStatement = undefined;
dbg.addDebuggee(g);
g.eval("(" + function test() {
for (i = 0; i < 5; i++)
f(42);
} + ")();");
}
g.eval("" + function f(d) {
return g(d);
});
g.eval("" + function g(d) {
debugger;
return d;
});
function testResumptionValues(handlerSetter) {
// Test normal return.
reset();
handlerSetter(undefined);
assertEq(g.eval("(" + function test() { return f(42); } + ")();"), 42);
// Test forced return.
reset();
handlerSetter({ return: "not 42" });
assertEq(g.eval("(" + function test() { return f(42); } + ")();"), "not 42");
// Test throw.
reset();
handlerSetter({ throw: "thrown 42" });
try {
g.eval("(" + function test() { return f(42); } + ")();");;
} catch (e) {
assertEq(e, "thrown 42");
}
}
// Turn off from within the prologue.
testResumptionValues(function (resumptionVal) {
dbg.onEnterFrame = function (frame) {
if (frame.older) {
if (frame.older.older) {
dbg.removeDebuggee(g);
return resumptionVal;
}
}
};
});
// Turn off from within the epilogue.
testResumptionValues(function (resumptionVal) {
dbg.onEnterFrame = function (frame) {
if (frame.older) {
if (frame.older.older) {
frame.onPop = function () {
dbg.removeDebuggee(g);
return resumptionVal;
};
}
}
};
});
// Turn off from within debugger statement handler.
testResumptionValues(function (resumptionVal) {
dbg.onDebuggerStatement = function (frame) {
dbg.removeDebuggee(g);
return resumptionVal;
};
});
// Turn off from within debug trap handler.
testResumptionValues(function (resumptionVal) {
dbg.onEnterFrame = function (frame) {
if (frame.older) {
if (frame.older.older) {
frame.onStep = function () {
dbg.removeDebuggee(g);
return resumptionVal;
}
}
}
};
});
```
vs
```js
var g = newGlobal();
var dbg = new Debugger();
function reset() {
dbg.onEnterFrame = undefined;
dbg.onDebuggerStatement = undefined;
dbg.addDebuggee(g);
g.eval("(" + function test() {
for (i = 0;i < 5;i++) f(42);
} + ")();");
}
g.eval("" + (function f(d) {
return g(d);
}));
g.eval("" + (function g(d) {
debugger;;
return d;
}));
function testResumptionValues(handlerSetter) {
reset();
handlerSetter(undefined);
assertEq(g.eval("(" + function test() {
return f(42);
} + ")();"), 42);
reset();
handlerSetter({
return: "not 42",
});
assertEq(g.eval("(" + function test() {
return f(42);
} + ")();"), "not 42");
reset();
handlerSetter({
throw: "thrown 42",
});
try {
g.eval("(" + function test() {
return f(42);
} + ")();");
;
} catch (e) {
assertEq(e, "thrown 42");
}
}
testResumptionValues((function(resumptionVal) {
dbg.onEnterFrame = function(frame) {
if (frame.older) {
if (frame.older.older) {
dbg.removeDebuggee(g);
return resumptionVal;
}
}
};
}));
testResumptionValues((function(resumptionVal) {
dbg.onEnterFrame = function(frame) {
if (frame.older) {
if (frame.older.older) {
frame.onPop = function() {
dbg.removeDebuggee(g);
return resumptionVal;
};
}
}
};
}));
testResumptionValues((function(resumptionVal) {
dbg.onDebuggerStatement = function(frame) {
dbg.removeDebuggee(g);
return resumptionVal;
};
}));
testResumptionValues((function(resumptionVal) {
dbg.onEnterFrame = function(frame) {
if (frame.older) {
if (frame.older.older) {
frame.onStep = function() {
dbg.removeDebuggee(g);
return resumptionVal;
};
}
}
};
}));
```
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/bug958432.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/resumption-08.js)
<details>
```js
// String.prototype[@@iterator] and StringIterator.prototype surface tests
load(libdir + "array-compare.js");
load(libdir + "asserts.js");
load(libdir + "iteration.js");
function assertDataDescriptor(actual, expected) {
assertEq(actual.value, expected.value);
assertEq(actual.writable, expected.writable);
assertEq(actual.enumerable, expected.enumerable);
assertEq(actual.configurable, expected.configurable);
}
function isConstructor(o) {
try {
new (new Proxy(o, {construct: () => ({})}));
return true;
} catch(e) {
return false;
}
}
function assertBuiltinFunction(o, name, arity) {
var fn = o[name];
assertDataDescriptor(Object.getOwnPropertyDescriptor(o, name), {
value: fn,
writable: true,
enumerable: false,
configurable: true,
});
assertEq(typeof fn, "function");
assertEq(Object.getPrototypeOf(fn), Function.prototype);
assertEq(isConstructor(fn), false);
assertEq(arraysEqual(Object.getOwnPropertyNames(fn).sort(), ["length", "name"].sort()), true);
assertDataDescriptor(Object.getOwnPropertyDescriptor(fn, "length"), {
value: arity,
writable: false,
enumerable: false,
configurable: true
});
var functionName = typeof name === "symbol"
? String(name).replace(/^Symbol\((.+)\)$/, "[$1]")
: name;
assertDataDescriptor(Object.getOwnPropertyDescriptor(fn, "name"), {
value: functionName,
writable: false,
enumerable: false,
configurable: true
});
}
// String.prototype[@@iterator] is a built-in function
assertBuiltinFunction(String.prototype, Symbol.iterator, 0);
// Test StringIterator.prototype surface
var iter = ""[Symbol.iterator]();
var iterProto = Object.getPrototypeOf(iter);
// StringIterator.prototype inherits from %IteratorPrototype%. Check it's the
// same object as %ArrayIteratorPrototype%'s proto.
assertEq(Object.getPrototypeOf(iterProto),
Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));
// Own properties for StringIterator.prototype: "next"
assertEq(arraysEqual(Object.getOwnPropertyNames(iterProto).sort(), ["next"]), true);
// StringIterator.prototype.next is a built-in function
assertBuiltinFunction(iterProto, "next", 0);
// StringIterator.prototype[@@iterator] is generic and returns |this|
for (var v of [void 0, null, true, false, "", 0, 1, {}, [], iter, iterProto]) {
assertEq(iterProto[Symbol.iterator].call(v), v);
}
// StringIterator.prototype.next is not generic
for (var v of [void 0, null, true, false, "", 0, 1, {}, [], iterProto]) {
assertThrowsInstanceOf(() => iterProto.next.call(v), TypeError);
}
```
vs
```js
load(libdir + "array-compare.js");
load(libdir + "asserts.js");
load(libdir + "iteration.js");
function assertDataDescriptor(actual, expected) {
assertEq(actual.value, expected.value);
assertEq(actual.writable, expected.writable);
assertEq(actual.enumerable, expected.enumerable);
assertEq(actual.configurable, expected.configurable);
}
function isConstructor(o) {
try {
new new Proxy(o, {
construct: () => ({ }),
})();
return true;
} catch (e) {
return false;
}
}
function assertBuiltinFunction(o, name, arity) {
var fn = o[name];
assertDataDescriptor(Object.getOwnPropertyDescriptor(o, name), {
value: fn,
writable: true,
enumerable: false,
configurable: true,
});
assertEq(typeof fn, "function");
assertEq(Object.getPrototypeOf(fn), Function.prototype);
assertEq(isConstructor(fn), false);
assertEq(arraysEqual(Object.getOwnPropertyNames(fn).sort(), ["length", "name",].sort()), true);
assertDataDescriptor(Object.getOwnPropertyDescriptor(fn, "length"), {
value: arity,
writable: false,
enumerable: false,
configurable: true,
});
var functionName = typeof name === "symbol" ? String(name).replace(/^Symbol\((.+)\)$/, "[$1]") : name;
assertDataDescriptor(Object.getOwnPropertyDescriptor(fn, "name"), {
value: functionName,
writable: false,
enumerable: false,
configurable: true,
});
}
assertBuiltinFunction(String.prototype, Symbol.iterator, 0);
var iter = ""[Symbol.iterator]();
var iterProto = Object.getPrototypeOf(iter);
assertEq(Object.getPrototypeOf(iterProto), Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));
assertEq(arraysEqual(Object.getOwnPropertyNames(iterProto).sort(), ["next",]), true);
assertBuiltinFunction(iterProto, "next", 0);
for (v of [void 0, null, true, false, "", 0, 1, {}, [], iter, iterProto,]) {
assertEq(iterProto[Symbol.iterator].call(v), v);
}
for (v of [void 0, null, true, false, "", 0, 1, {}, [], iterProto,]) {
assertThrowsInstanceOf(() => iterProto.next.call(v), TypeError);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/string-iterator-surfaces.js)
* [round-trip differed:
for (x in (function*() {
eval("arguments[0]");
yield;
})())(function() {})
vs for (x in function*() {
eval("arguments[0]");
yield ;
}()) function() { };
](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/bug843985.js)
<details>
```js
// Debugger.Frames for async functions are not GC'd while they're suspended.
// The awaited promise keeps the generator alive, via its reaction lists.
var g = newGlobal();
g.eval(`
// Create a few promises.
var promises = [], resolvers = [];
for (let i = 0; i < 3; i++)
promises.push(new Promise(r => { resolvers.push(r); }));
async function f() {
debugger;
for (let p of promises) {
await p;
debugger;
}
}
`);
var dbg = new Debugger(g);
var hits = 0;
dbg.onDebuggerStatement = function (frame) {
if (hits === 0)
frame.seen = true;
else
assertEq(frame.seen, true);
hits++;
};
let done = false;
g.f().then(_ => { done = true; });
gc();
drainJobQueue();
gc();
// Resolve the promises one by one.
for (let [i, resolve] of g.resolvers.entries()) {
assertEq(hits, 1 + i);
assertEq(done, false);
resolve("x");
gc();
drainJobQueue();
gc();
}
assertEq(hits, 1 + g.resolvers.length);
assertEq(done, true);
```
vs
```js
var g = newGlobal();
g.eval(`
// Create a few promises.
var promises = [], resolvers = [];
for (let i = 0; i < 3; i++)
promises.push(new Promise(r => { resolvers.push(r); }));
async function f() {
debugger;
for (let p of promises) {
await p;
debugger;
}
}
`);
var dbg = new Debugger(g);
var hits = 0;
dbg.onDebuggerStatement = (function(frame) {
if (hits === 0) frame.seen = true;
else assertEq(frame.seen, true);
hits++;
});
let done = false;
g.f().then(_ => {
done = true;
});
gc();
drainJobQueue();
gc();
for ([i,resolve,] of g.resolvers.entries()) {
assertEq(hits, 1 + i);
assertEq(done, false);
resolve("x");
gc();
drainJobQueue();
gc();
}
assertEq(hits, 1 + g.resolvers.length);
assertEq(done, true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Frame-identity-06.js)
<details>
```js
// Changing arguments.length during a for-of loop iterating over arguments affects the loop.
load(libdir + "iteration.js");
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var s;
function f() {
for (var v of arguments) {
s += v;
arguments.length--;
}
}
s = '';
f('a', 'b', 'c', 'd', 'e');
assertEq(s, 'abc');
```
vs
```js
load(libdir + "iteration.js");
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var s;
function f() {
for (v of arguments) {
s += v;
arguments.length--;
}
}
s = '';
f('a', 'b', 'c', 'd', 'e');
assertEq(s, 'abc');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arguments-7.js)
<details>
```js
// Destructuring does not occur when the target of for-of is an empty typed array.
for (var [[x]] of new Int32Array(0))
throw "FAIL";
```
vs
```js
for ([[x,],] of new Int32Array(0)) throw "FAIL";
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/typedarrays-3.js)
<details>
```js
function nonEmptyStack1Helper(o, farble) {
var a = [];
var j = 0;
for (var i in o)
a[j++] = i;
return a.join("");
}
function nonEmptyStack1() {
return nonEmptyStack1Helper({a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8}, "hi");
}
assertEq(nonEmptyStack1(), "abcdefgh");
```
vs
```js
function nonEmptyStack1Helper(o, farble) {
var a = [];
var j = 0;
for (i in o) a[j++] = i;
return a.join("");
}
function nonEmptyStack1() {
return nonEmptyStack1Helper({
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
f: 6,
g: 7,
h: 8,
}, "hi");
}
assertEq(nonEmptyStack1(), "abcdefgh");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/nonEmptyStack1.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/recover-arrays.js)
<details>
```js
// for-of throws if the target is an ArrayBuffer.
load(libdir + "asserts.js");
assertThrowsInstanceOf(function () {
for (var v of new Int8Array([0, 1, 2, 3]).buffer)
throw "FAIL";
}, TypeError);
```
vs
```js
load(libdir + "asserts.js");
assertThrowsInstanceOf((function() {
for (v of new Int8Array([0, 1, 2, 3,]).buffer) throw "FAIL";
}), TypeError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/typedarrays-5.js)
<details>
```js
function f(x, [y]) {}
f(0, []);
// jsfunfuzz-generated
let i = 0;
for (var z of [0, 0, 0]) {
verifyprebarriers();
}
```
vs
```js
function f(x, [y,]) { }
f(0, []);
let i = 0;
for (z of [0, 0, 0,]) {
verifyprebarriers();
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/self-hosting/bug1264575.js)
<details>
```js
// for-of can iterate over typed arrays.
var a = new Int8Array([0, 1, -7, 3])
var s = '';
for (var v of a)
s += v + ',';
assertEq(s, '0,1,-7,3,');
```
vs
```js
var a = new Int8Array([0, 1, -7, 3,]);
var s = '';
for (v of a) s += v + ',';
assertEq(s, '0,1,-7,3,');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/typedarrays-1.js)
<details>
```js
load(libdir + "asserts.js");
const bad_types = [
2112,
{geddy: "lee"},
() => 1,
[],
Array
]
// We only accept strings around here!
for (var badType of bad_types) {
assertThrowsInstanceOf(() => {
Debugger.isCompilableUnit(badType);
}, TypeError);
}
const compilable_units = [
"wubba-lubba-dub-dub",
"'Get Schwifty!'",
"1 + 2",
"function f(x) {}",
"function x(...f,) {", // statements with bad syntax are always compilable
"let x = 100",
";;;;;;;;",
"",
" ",
"\n",
"let x",
]
const non_compilable_units = [
"function f(x) {",
"(...d) =>",
"{geddy:",
"{",
"[1, 2",
"[",
"1 +",
"let x =",
"3 ==",
]
for (var code of compilable_units) {
assertEq(Debugger.isCompilableUnit(code), true);
}
for (var code of non_compilable_units) {
assertEq(Debugger.isCompilableUnit(code), false);
}
// Supplying no arguments should throw a type error
assertThrowsInstanceOf(() => {
Debugger.isCompilableUnit();
}, TypeError);
// Supplying extra arguments should be fine
assertEq(Debugger.isCompilableUnit("", 1, 2, 3, 4, {}, []), true);
```
vs
```js
load(libdir + "asserts.js");
const bad_types = [2112, ({
geddy: "lee",
}), () => 1, [], Array,];
for (badType of bad_types) {
assertThrowsInstanceOf(() => {
Debugger.isCompilableUnit(badType);
}, TypeError);
}
const compilable_units = ["wubba-lubba-dub-dub", "'Get Schwifty!'", "1 + 2", "function f(x) {}", "function x(...f,) {", "let x = 100", ";;;;;;;;", "", " ", "\n", "let x",];
const non_compilable_units = ["function f(x) {", "(...d) =>", "{geddy:", "{", "[1, 2", "[", "1 +", "let x =", "3 ==",];
for (code of compilable_units) {
assertEq(Debugger.isCompilableUnit(code), true);
}
for (code of non_compilable_units) {
assertEq(Debugger.isCompilableUnit(code), false);
}
assertThrowsInstanceOf(() => {
Debugger.isCompilableUnit();
}, TypeError);
assertEq(Debugger.isCompilableUnit("", 1, 2, 3, 4, ({}), []), true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Debugger-isCompilableUnit.js)
* [Unable to re-interpret from expression to pattern at line: 7, column: 13](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/bug1441012.js)
<details>
```js
// Comprehensive test of get/setVariable on many kinds of environments and
// bindings.
load(libdir + "asserts.js");
var cases = [
// global bindings and bindings on the global prototype chain
"x = VAL; @@",
"var x = VAL; @@",
"Object.prototype.x = VAL; @@",
// let and catch bindings
"let x = VAL; @@",
"{ let x = VAL; @@ }",
"try { throw VAL; } catch (x) { @@ }",
"try { throw VAL; } catch (x) { @@ }",
"for (let x of [VAL]) { @@ }",
"switch (0) { default: let x = VAL; @@ }",
// arguments
"function f(x) { @@ } f(VAL);",
"function f([w, x]) { @@ } f([0, VAL]);",
"function f({v: x}) { @@ } f({v: VAL});",
"function f([w, {v: x}]) { @@ } f([0, {v: VAL}]);",
// bindings in functions
"function f() { var x = VAL; @@ } f();",
"function f() { let x = VAL; @@ } f();",
"function f() { function x() {} x = VAL; @@ } f();",
// dynamic bindings
"function f(s) { eval(s); @@ } f('var x = VAL');",
"var x = VAL; function f(s) { eval('var x = 0;'); eval(s); @@ } f('delete x;');",
"function f(obj) { with (obj) { @@ } } f({x: VAL});",
"function f(obj) { with (obj) { @@ } } f(Object.create({x: VAL}));",
"function f(b) { if (b) { function x(){} } x = VAL; @@ } f(1);",
];
var nextval = 1000;
function test(code, debugStmts, followupStmts) {
var val = nextval++;
var hits = 0;
var g = newGlobal();
g.eval("function debugMe() { var x = 'wrong-x'; debugger; }");
g.capture = null;
var dbg = Debugger(g);
dbg.onDebuggerStatement = function (frame) {
if (frame.callee !== null && frame.callee.name == 'debugMe')
frame = frame.older;
var env = frame.environment.find("x");
assertEq(env.getVariable("x"), val)
assertEq(env.setVariable("x", 'ok'), undefined);
assertEq(env.getVariable("x"), 'ok');
// setVariable cannot create new variables.
assertThrowsInstanceOf(function () { env.setVariable("newVar", 0); }, TypeError);
hits++;
};
code = code.replace("@@", debugStmts);
if (followupStmts !== undefined)
code += " " + followupStmts;
code = code.replace(/VAL/g, uneval(val));
g.eval(code);
assertEq(hits, 1);
}
for (var s of cases) {
// Test triggering the debugger right in the scope in which x is bound.
test(s, "debugger; assertEq(x, 'ok');");
// Test calling a function that triggers the debugger.
test(s, "debugMe(); assertEq(x, 'ok');");
// Test triggering the debugger from a scope nested in x's scope.
test(s, "{ let y = 'irrelevant'; (function (z) { { let zz = y; debugger; } })(); } assertEq(x, 'ok');"),
// Test closing over the variable and triggering the debugger later, after
// leaving the variable's scope.
test(s, "capture = {dbg: function () { debugger; }, get x() { return x; }};",
"assertEq(capture.x, VAL); capture.dbg(); assertEq(capture.x, 'ok');");
}
```
vs
```js
load(libdir + "asserts.js");
var cases = ["x = VAL; @@", "var x = VAL; @@", "Object.prototype.x = VAL; @@", "let x = VAL; @@", "{ let x = VAL; @@ }", "try { throw VAL; } catch (x) { @@ }", "try { throw VAL; } catch (x) { @@ }", "for (let x of [VAL]) { @@ }", "switch (0) { default: let x = VAL; @@ }", "function f(x) { @@ } f(VAL);", "function f([w, x]) { @@ } f([0, VAL]);", "function f({v: x}) { @@ } f({v: VAL});", "function f([w, {v: x}]) { @@ } f([0, {v: VAL}]);", "function f() { var x = VAL; @@ } f();", "function f() { let x = VAL; @@ } f();", "function f() { function x() {} x = VAL; @@ } f();", "function f(s) { eval(s); @@ } f('var x = VAL');", "var x = VAL; function f(s) { eval('var x = 0;'); eval(s); @@ } f('delete x;');", "function f(obj) { with (obj) { @@ } } f({x: VAL});", "function f(obj) { with (obj) { @@ } } f(Object.create({x: VAL}));", "function f(b) { if (b) { function x(){} } x = VAL; @@ } f(1);",];
var nextval = 1000;
function test(code, debugStmts, followupStmts) {
var val = nextval++;
var hits = 0;
var g = newGlobal();
g.eval("function debugMe() { var x = 'wrong-x'; debugger; }");
g.capture = null;
var dbg = Debugger(g);
dbg.onDebuggerStatement = function(frame) {
if (frame.callee !== null && frame.callee.name == 'debugMe') frame = frame.older;
var env = frame.environment.find("x");
assertEq(env.getVariable("x"), val);
assertEq(env.setVariable("x", 'ok'), undefined);
assertEq(env.getVariable("x"), 'ok');
assertThrowsInstanceOf(function() {
env.setVariable("newVar", 0);
}, TypeError);
hits++;
};
code = code.replace("@@", debugStmts);
if (followupStmts !== undefined) code += " " + followupStmts;
code = code.replace(/VAL/g, uneval(val));
g.eval(code);
assertEq(hits, 1);
}
for (s of cases) {
test(s, "debugger; assertEq(x, 'ok');");
test(s, "debugMe(); assertEq(x, 'ok');");
test(s, "{ let y = 'irrelevant'; (function (z) { { let zz = y; debugger; } })(); } assertEq(x, 'ok');"), test(s, "capture = {dbg: function () { debugger; }, get x() { return x; }};", "assertEq(capture.x, VAL); capture.dbg(); assertEq(capture.x, 'ok');");
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Environment-variables.js)
<details>
```js
a = [];
for (var i = 0; i < 1000; i++) {
a[i] = i;
}
function foo(x) {
for (var i in x) {
}
}
if (typeof schedulegc != "undefined")
schedulegc(100);
foo(a);
```
vs
```js
a = [];
for (let i = 0;i < 1000;i++) {
a[i] = i;
}
function foo(x) {
for (i in x) {
}
}
if (typeof schedulegc != "undefined") schedulegc(100);
foo(a);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug674391.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/defaults-destructuring-mixed-default-value.js)
<details>
```js
// Test localExportEntries property
function testArrayContents(actual, expected) {
assertEq(actual.length, expected.length);
for (var i = 0; i < actual.length; i++) {
for (var property in expected[i]) {
assertEq(actual[i][property], expected[i][property]);
}
}
}
function testLocalExportEntries(source, expected) {
var module = parseModule(source);
testArrayContents(module.localExportEntries, expected);
}
testLocalExportEntries(
'export var v;',
[{exportName: 'v', moduleRequest: null, importName: null, localName: 'v'}]);
testLocalExportEntries(
'export var v = 0;',
[{exportName: 'v', moduleRequest: null, importName: null, localName: 'v'}]);
testLocalExportEntries(
'export let x = 1;',
[{exportName: 'x', moduleRequest: null, importName: null, localName: 'x'}]);
testLocalExportEntries(
'export const x = 1;',
[{exportName: 'x', moduleRequest: null, importName: null, localName: 'x'}]);
testLocalExportEntries(
'export class foo { constructor() {} };',
[{exportName: 'foo', moduleRequest: null, importName: null, localName: 'foo'}]);
testLocalExportEntries(
'export default function f() {};',
[{exportName: 'default', moduleRequest: null, importName: null, localName: 'f'}]);
testLocalExportEntries(
'export default function() {};',
[{exportName: 'default', moduleRequest: null, importName: null, localName: 'default'}]);
testLocalExportEntries(
'export default 42;',
[{exportName: 'default', moduleRequest: null, importName: null, localName: 'default'}]);
testLocalExportEntries(
'let x = 1; export {x};',
[{exportName: 'x', moduleRequest: null, importName: null, localName: 'x'}]);
testLocalExportEntries(
'let v = 1; export {v as x};',
[{exportName: 'x', moduleRequest: null, importName: null, localName: 'v'}]);
testLocalExportEntries(
'export {x} from "mod";',
[]);
testLocalExportEntries(
'export {v as x} from "mod";',
[]);
testLocalExportEntries(
'export * from "mod";',
[]);
// Test indirectExportEntries property
function testIndirectExportEntries(source, expected) {
var module = parseModule(source);
testArrayContents(module.indirectExportEntries, expected);
}
testIndirectExportEntries(
'export default function f() {};',
[]);
testIndirectExportEntries(
'let x = 1; export {x};',
[]);
testIndirectExportEntries(
'export {x} from "mod";',
[{exportName: 'x', moduleRequest: 'mod', importName: 'x', localName: null}]);
testIndirectExportEntries(
'export {v as x} from "mod";',
[{exportName: 'x', moduleRequest: 'mod', importName: 'v', localName: null}]);
testIndirectExportEntries(
'export * from "mod";',
[]);
testIndirectExportEntries(
'import {v as x} from "mod"; export {x as y};',
[{exportName: 'y', moduleRequest: 'mod', importName: 'v', localName: null}]);
// Test starExportEntries property
function testStarExportEntries(source, expected) {
var module = parseModule(source);
testArrayContents(module.starExportEntries, expected);
}
testStarExportEntries(
'export default function f() {};',
[]);
testStarExportEntries(
'let x = 1; export {x};',
[]);
testStarExportEntries(
'export {x} from "mod";',
[]);
testStarExportEntries(
'export * from "mod";',
[{exportName: null, moduleRequest: 'mod', importName: '*', localName: null}]);
```
vs
```js
function testArrayContents(actual, expected) {
assertEq(actual.length, expected.length);
for (let i = 0;i < actual.length;i++) {
for (property in expected[i]) {
assertEq(actual[i][property], expected[i][property]);
}
}
}
function testLocalExportEntries(source, expected) {
var module = parseModule(source);
testArrayContents(module.localExportEntries, expected);
}
testLocalExportEntries('export var v;', [({
exportName: 'v',
moduleRequest: null,
importName: null,
localName: 'v',
}),]);
testLocalExportEntries('export var v = 0;', [({
exportName: 'v',
moduleRequest: null,
importName: null,
localName: 'v',
}),]);
testLocalExportEntries('export let x = 1;', [({
exportName: 'x',
moduleRequest: null,
importName: null,
localName: 'x',
}),]);
testLocalExportEntries('export const x = 1;', [({
exportName: 'x',
moduleRequest: null,
importName: null,
localName: 'x',
}),]);
testLocalExportEntries('export class foo { constructor() {} };', [({
exportName: 'foo',
moduleRequest: null,
importName: null,
localName: 'foo',
}),]);
testLocalExportEntries('export default function f() {};', [({
exportName: 'default',
moduleRequest: null,
importName: null,
localName: 'f',
}),]);
testLocalExportEntries('export default function() {};', [({
exportName: 'default',
moduleRequest: null,
importName: null,
localName: 'default',
}),]);
testLocalExportEntries('export default 42;', [({
exportName: 'default',
moduleRequest: null,
importName: null,
localName: 'default',
}),]);
testLocalExportEntries('let x = 1; export {x};', [({
exportName: 'x',
moduleRequest: null,
importName: null,
localName: 'x',
}),]);
testLocalExportEntries('let v = 1; export {v as x};', [({
exportName: 'x',
moduleRequest: null,
importName: null,
localName: 'v',
}),]);
testLocalExportEntries('export {x} from "mod";', []);
testLocalExportEntries('export {v as x} from "mod";', []);
testLocalExportEntries('export * from "mod";', []);
function testIndirectExportEntries(source, expected) {
var module = parseModule(source);
testArrayContents(module.indirectExportEntries, expected);
}
testIndirectExportEntries('export default function f() {};', []);
testIndirectExportEntries('let x = 1; export {x};', []);
testIndirectExportEntries('export {x} from "mod";', [({
exportName: 'x',
moduleRequest: 'mod',
importName: 'x',
localName: null,
}),]);
testIndirectExportEntries('export {v as x} from "mod";', [({
exportName: 'x',
moduleRequest: 'mod',
importName: 'v',
localName: null,
}),]);
testIndirectExportEntries('export * from "mod";', []);
testIndirectExportEntries('import {v as x} from "mod"; export {x as y};', [({
exportName: 'y',
moduleRequest: 'mod',
importName: 'v',
localName: null,
}),]);
function testStarExportEntries(source, expected) {
var module = parseModule(source);
testArrayContents(module.starExportEntries, expected);
}
testStarExportEntries('export default function f() {};', []);
testStarExportEntries('let x = 1; export {x};', []);
testStarExportEntries('export {x} from "mod";', []);
testStarExportEntries('export * from "mod";', [({
exportName: null,
moduleRequest: 'mod',
importName: '*',
localName: null,
}),]);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/modules/export-entries.js)
* [Unexpected Token at line: 47, column: 34: Expected `function`, `this`, `class`, or `import`; found Keyword(Await)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/promise/debugger-reaction-does-not-resolve.js)
<details>
```js
setJitCompilerOption("baseline.warmup.trigger", 10);
setJitCompilerOption("ion.warmup.trigger", 20);
function myFloor(x) {
if(x >= 0)
return x - Math.abs(x % 1);
else
return x - Math.abs(1 + (x % 1));
}
function floorRangeTest(x) {
if(10 < x) {
if(x < 100) {
assertEq(Math.floor(x), myFloor(x));
}
}
if(-100 < x) {
if(x < -10) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (-(4294967296 - 1) < x) {
if(x < 10) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (-10 < x) {
if(x < 4294967296) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (-2147483648 < x) {
if(x < 10) {
assertEq(Math.floor(x), myFloor(x));
}
}
if ((-2147483648 -1) < x) {
if(x < 10) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (10 < x) {
if(x < 2147483648) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (10 < x) {
if(x < 2147483649) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (Math.pow(2,31) < x) {
if(x < Math.pow(2,33)) {
assertEq(Math.floor(x), myFloor(x));
}
}
}
var a = [Math.pow(2,31), Math.pow(2,33), -4294967296.4, 214748364.2, -50.4, 50.4];
for(var i = 0; i < 10; i++) {
for (var j = 0; j < a.length; j++) {
floorRangeTest(a[j]);
}
}
for (var j = 0; j < 30; j++) {
(function() {
Math.floor(1.5);
})()
}
for (var j = 0; j < 30; j++) {
(function() {
Math.floor(-1.5);
})()
}
for (var j = 0; j < 30; j++) {
(function() {
Math.floor(-127.5);
})()
}
```
vs
```js
setJitCompilerOption("baseline.warmup.trigger", 10);
setJitCompilerOption("ion.warmup.trigger", 20);
function myFloor(x) {
if (x >= 0) return x - Math.abs(x % 1);
else return x - Math.abs(1 + x % 1);
}
function floorRangeTest(x) {
if (10 < x) {
if (x < 100) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (-100 < x) {
if (x < -10) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (-4294967296 - 1 < x) {
if (x < 10) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (-10 < x) {
if (x < 4294967296) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (-2147483648 < x) {
if (x < 10) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (-2147483648 - 1 < x) {
if (x < 10) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (10 < x) {
if (x < 2147483648) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (10 < x) {
if (x < 2147483649) {
assertEq(Math.floor(x), myFloor(x));
}
}
if (Math.pow(2, 31) < x) {
if (x < Math.pow(2, 33)) {
assertEq(Math.floor(x), myFloor(x));
}
}
}
var a = [Math.pow(2, 31), Math.pow(2, 33), -4294967296.4, 214748364.2, -50.4, 50.4,];
for (let i = 0;i < 10;i++) {
for (let j = 0;j < a.length;j++) {
floorRangeTest(a[j]);
}
}
for (let j = 0;j < 30;j++) {
function() {
Math.floor(1.5);
}();
}
for (let j = 0;j < 30;j++) {
function() {
Math.floor(-1.5);
}();
}
for (let j = 0;j < 30;j++) {
function() {
Math.floor(-127.5);
}();
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/bug1015498.js)
<details>
```js
// Breaking out of a for-of loop over a generator-iterator closes the generator.
load(libdir + "iteration.js");
function* range(n) {
for (var i = 0; i < n; i++)
yield i;
}
var r = range(10);
var s = '';
for (var x of r) {
s += x;
if (x == 4)
break;
}
s += '/';
for (var y of r)
s += y;
assertEq(s, '01234/');
```
vs
```js
load(libdir + "iteration.js");
function *range(n) {
for (let i = 0;i < n;i++) yield i;
}
var r = range(10);
var s = '';
for (x of r) {
s += x;
if (x == 4) break;
}
s += '/';
for (y of r) s += y;
assertEq(s, '01234/');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/generators-5.js)
* [Unexpected Token at line: 36, column: 33: Expected `function`, `this`, `class`, or `import`; found Keyword(Await)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/promise/promise-race-with-default-resolving-internal.js)
<details>
```js
// Error message for redeclaration should show the position where the variable
// was declared.
const npos = -1;
function test_one(fun, filename, name,
[prevLineNumber, prevColumnNumber],
[lineNumber, columnNumber]) {
let caught = false;
try {
fun();
} catch (e) {
assertEq(e.message.includes("redeclaration"), true);
assertEq(e.lineNumber, lineNumber);
assertEq(e.columnNumber, columnNumber);
let notes = getErrorNotes(e);
if (prevLineNumber == npos) {
assertEq(notes.length, 0);
} else {
assertEq(notes.length, 1);
let note = notes[0];
assertEq(note.message,
`Previously declared at line ${prevLineNumber}, column ${prevColumnNumber}`);
assertEq(note.lineNumber, prevLineNumber);
assertEq(note.columnNumber, prevColumnNumber);
if (filename)
assertEq(note.fileName, filename);
}
caught = true;
}
assertEq(caught, true);
}
function test_parse(source, ...args) {
test_one(() => {
Reflect.parse(source, { source: "foo.js" });
}, "foo.js", ...args);
}
function test_eval(source, ...args) {
test_one(() => {
eval(source);
}, undefined, ...args);
}
function test(...args) {
test_parse(...args);
test_eval(...args);
}
// let
test(`
let a, a;
`, "a", [2, 4], [2, 7]);
test(`
let a;
let a;
`, "a", [2, 4], [3, 4]);
test(`
let a;
const a = 1;
`, "a", [2, 4], [3, 6]);
test(`
let a;
var a;
`, "a", [2, 4], [3, 4]);
test(`
let a;
function a() {
}
`, "a", [2, 4], [3, 9]);
test(`
{
let a;
function a() {
}
}
`, "a", [3, 6], [4, 11]);
// const
test(`
const a = 1, a = 2;
`, "a", [2, 6], [2, 13]);
test(`
const a = 1;
const a = 2;
`, "a", [2, 6], [3, 6]);
test(`
const a = 1;
let a;
`, "a", [2, 6], [3, 4]);
test(`
const a = 1;
var a;
`, "a", [2, 6], [3, 4]);
test(`
const a = 1;
function a() {
}
`, "a", [2, 6], [3, 9]);
test(`
{
const a = 1;
function a() {
}
}
`, "a", [3, 8], [4, 11]);
// var
test(`
var a;
let a;
`, "a", [2, 4], [3, 4]);
test(`
var a;
const a = 1;
`, "a", [2, 4], [3, 6]);
// function
test(`
function a() {};
let a;
`, "a", [2, 9], [3, 4]);
test(`
function a() {};
const a = 1;
`, "a", [2, 9], [3, 6]);
// Annex B lexical function
test(`
{
function a() {};
let a;
}
`, "a", [3, 11], [4, 6]);
test(`
{
function a() {};
const a = 1;
}
`, "a", [3, 11], [4, 8]);
// catch parameter
test(`
try {
} catch (a) {
let a;
}
`, "a", [3, 9], [4, 6]);
test(`
try {
} catch (a) {
const a = 1;
}
`, "a", [3, 9], [4, 8]);
test(`
try {
} catch (a) {
function a() {
}
}
`, "a", [3, 9], [4, 11]);
// parameter
test(`
function f(a) {
let a;
}
`, "a", [2, 11], [3, 6]);
test(`
function f(a) {
const a = 1;
}
`, "a", [2, 11], [3, 8]);
test(`
function f([a]) {
let a;
}
`, "a", [2, 12], [3, 6]);
test(`
function f({a}) {
let a;
}
`, "a", [2, 12], [3, 6]);
test(`
function f(...a) {
let a;
}
`, "a", [2, 14], [3, 6]);
test(`
function f(a=1) {
let a;
}
`, "a", [2, 11], [3, 6]);
// eval
// We don't have position information at runtime.
// No note should be shown.
test_eval(`
let a;
eval("var a");
`, "a", [npos, npos], [1, 4]);
```
vs
```js
const npos = -1;
function test_one(fun, filename, name, [prevLineNumber,prevColumnNumber,], [lineNumber,columnNumber,]) {
let caught = false;
try {
fun();
} catch (e) {
assertEq(e.message.includes("redeclaration"), true);
assertEq(e.lineNumber, lineNumber);
assertEq(e.columnNumber, columnNumber);
let notes = getErrorNotes(e);
if (prevLineNumber == npos) {
assertEq(notes.length, 0);
} else {
assertEq(notes.length, 1);
let note = notes[0];
assertEq(note.message, `Previously declared at line ${prevLineNumber}, column {prevColumnNumber}`);
assertEq(note.lineNumber, prevLineNumber);
assertEq(note.columnNumber, prevColumnNumber);
if (filename) assertEq(note.fileName, filename);
}
caught = true;
}
assertEq(caught, true);
}
function test_parse(source, args) {
test_one(() => {
Reflect.parse(source, {
source: "foo.js",
});
}, "foo.js", ...args);
}
function test_eval(source, args) {
test_one(() => {
eval(source);
}, undefined, ...args);
}
function test(args) {
test_parse(...args);
test_eval(...args);
}
test(`
let a, a;
`, "a", [2, 4,], [2, 7,]);
test(`
let a;
let a;
`, "a", [2, 4,], [3, 4,]);
test(`
let a;
const a = 1;
`, "a", [2, 4,], [3, 6,]);
test(`
let a;
var a;
`, "a", [2, 4,], [3, 4,]);
test(`
let a;
function a() {
}
`, "a", [2, 4,], [3, 9,]);
test(`
{
let a;
function a() {
}
}
`, "a", [3, 6,], [4, 11,]);
test(`
const a = 1, a = 2;
`, "a", [2, 6,], [2, 13,]);
test(`
const a = 1;
const a = 2;
`, "a", [2, 6,], [3, 6,]);
test(`
const a = 1;
let a;
`, "a", [2, 6,], [3, 4,]);
test(`
const a = 1;
var a;
`, "a", [2, 6,], [3, 4,]);
test(`
const a = 1;
function a() {
}
`, "a", [2, 6,], [3, 9,]);
test(`
{
const a = 1;
function a() {
}
}
`, "a", [3, 8,], [4, 11,]);
test(`
var a;
let a;
`, "a", [2, 4,], [3, 4,]);
test(`
var a;
const a = 1;
`, "a", [2, 4,], [3, 6,]);
test(`
function a() {};
let a;
`, "a", [2, 9,], [3, 4,]);
test(`
function a() {};
const a = 1;
`, "a", [2, 9,], [3, 6,]);
test(`
{
function a() {};
let a;
}
`, "a", [3, 11,], [4, 6,]);
test(`
{
function a() {};
const a = 1;
}
`, "a", [3, 11,], [4, 8,]);
test(`
try {
} catch (a) {
let a;
}
`, "a", [3, 9,], [4, 6,]);
test(`
try {
} catch (a) {
const a = 1;
}
`, "a", [3, 9,], [4, 8,]);
test(`
try {
} catch (a) {
function a() {
}
}
`, "a", [3, 9,], [4, 11,]);
test(`
function f(a) {
let a;
}
`, "a", [2, 11,], [3, 6,]);
test(`
function f(a) {
const a = 1;
}
`, "a", [2, 11,], [3, 8,]);
test(`
function f([a]) {
let a;
}
`, "a", [2, 12,], [3, 6,]);
test(`
function f({a}) {
let a;
}
`, "a", [2, 12,], [3, 6,]);
test(`
function f(...a) {
let a;
}
`, "a", [2, 14,], [3, 6,]);
test(`
function f(a=1) {
let a;
}
`, "a", [2, 11,], [3, 6,]);
test_eval(`
let a;
eval("var a");
`, "a", [npos, npos,], [1, 4,]);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/redeclaration.js)
<details>
```js
// Replacing Array.prototype.iterator with a generator affects for-of behavior.
load(libdir + "iteration.js");
Array.prototype[Symbol.iterator] = function* () {
for (var i = this.length; --i >= 0; )
yield this[i];
};
var s = '';
for (var v of ['a', 'b', 'c', 'd'])
s += v;
assertEq(s, 'dcba');
```
vs
```js
load(libdir + "iteration.js");
Array.prototype[Symbol.iterator] = (function*() {
for (let i = this.length;--i >= 0;) yield this[i];
});
var s = '';
for (v of ['a', 'b', 'c', 'd',]) s += v;
assertEq(s, 'dcba');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/semantics-03.js)
<details>
```js
// Stepping out of a finally should not appear to
// step backward to some earlier statement.
var g = newGlobal();
g.eval(`function f() {
debugger; // +0
var x = 0; // +1
try { // +2
x = 1; // +3
throw 'something'; // +4
} catch (e) { // +5
x = 2; // +6
} finally { // +7
x = 3; // +8
} // +9
x = 4; // +10
}`); // +11
var dbg = Debugger(g);
let foundLines = '';
dbg.onDebuggerStatement = function(frame) {
let debugLine = frame.script.getOffsetLocation(frame.offset).lineNumber;
frame.onStep = function() {
// Only record a stop when the offset is an entry point.
let foundLine = this.script.getOffsetLocation(this.offset).lineNumber;
if (foundLine != debugLine && this.script.getLineOffsets(foundLine).indexOf(this.offset) >= 0) {
foundLines += "," + (foundLine - debugLine);
}
};
};
g.f();
assertEq(foundLines, ",1,2,3,4,5,6,7,8,10,11");
```
vs
```js
var g = newGlobal();
g.eval(`function f() {
debugger; // +0
var x = 0; // +1
try { // +2
x = 1; // +3
throw 'something'; // +4
} catch (e) { // +5
x = 2; // +6
} finally { // +7
x = 3; // +8
} // +9
x = 4; // +10
}`);
var dbg = Debugger(g);
let foundLines = '';
dbg.onDebuggerStatement = (function(frame) {
let debugLine = frame.script.getOffsetLocation(frame.offset).lineNumber;
frame.onStep = function() {
let foundLine = this.script.getOffsetLocation(this.offset).lineNumber;
if (foundLine != debugLine && this.script.getLineOffsets(foundLine).indexOf(this.offset) >= 0) {
foundLines += "," + foundLine - debugLine;
}
};
});
g.f();
assertEq(foundLines, ",1,2,3,4,5,6,7,8,10,11");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Frame-onStep-11.js)
* [Unexpected Token at line: 3, column: 18: Expected `OpenBrace`; found Ident(Ident("Object"))](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-5.js)
* [Unable to re-interpret from expression to pattern at line: 10, column: 34](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1357075.js)
<details>
```js
function f(x) {
return (x | 0) - (-4294967295 | 0) + -2147483647
}
x = [1, 4294967295]
for (var j = 0; j < 2; ++j) {
for (var k = 0; k < 3; ++k) {
assertEq(f(x[j]), -2147483647 - 2 * j);
}
}
```
vs
```js
function f(x) {
return x | 0 - -4294967295 | 0 + -2147483647;
}
x = [1, 4294967295,];
for (let j = 0;j < 2;++j) {
for (let k = 0;k < 3;++k) {
assertEq(f(x[j]), -2147483647 - 2 * j);
}
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/fold-linear-arith-bug1316830.js)
<details>
```js
var IsPossiblyWrappedTypedArray = getSelfHostedValue("IsPossiblyWrappedTypedArray");
var declareSamples = `
var allTypedArraySamples = [
{ value: new Int8Array(1), expected: true },
{ value: new Uint8Array(1), expected: true },
{ value: new Int16Array(1), expected: true },
{ value: new Uint16Array(1), expected: true },
{ value: new Int32Array(1), expected: true },
{ value: new Uint32Array(1), expected: true },
{ value: new Float32Array(1), expected: true },
{ value: new Float64Array(1), expected: true },
{ value: new Uint8ClampedArray(1), expected: true }
];
var allObjectSamples = [
{ value: new Array(1), expected: false },
{ value: {}, expected: false },
{ value: { length: 1 }, expected: false }
];
`;
// Create a new global to wrap with cross compartment wrappers.
var g = newGlobal();
evaluate(declareSamples)
g.evaluate(declareSamples);
var assertCode = `function (value, expected) {
assertEq(IsPossiblyWrappedTypedArray(value), expected);
return inIon();
}`;
function checkSamples(samples) {
// Create the assert function anew every run so as not to share JIT code,
// type information, etc.
var assert = new Function(`return (${assertCode})`)();
// Prevent Ion compilation of this function so that we don't freeze the
// sample array's type. If we did, IonBuilder's typed-array-length inlining
// would always see a Mixed state, preventing IsPossiblyWrappedTypedArray
// from being inlined.
with ({}) {};
do {
// spinInJit is used to ensure that we at least test all elements in the
// sample vector while running a compiled version of the assert
// function.
var spinInJit = true;
for (var i = 0; i < samples.length; i++) {
var e = samples[i];
if (!e) continue;
spinInJit = spinInJit && assert(e.value, e.expected);
}
} while(!spinInJit);
}
// Check a mix of samples from each type.
function test(a, b, c, d) {
var samples = [
a == -1 ? null : allTypedArraySamples[a],
b == -1 ? null : allObjectSamples[b],
c == -1 ? null : g.allTypedArraySamples[c],
d == -1 ? null : g.allObjectSamples[d],
];
checkSamples(samples);
}
// Check all samples.
checkSamples(allTypedArraySamples);
checkSamples(allObjectSamples);
checkSamples(g.allTypedArraySamples);
checkSamples(g.allObjectSamples);
// Check combinations mixing 2 elements from different types.
test(-1, -1, 0, 0);
test(-1, 0, -1, 0);
test(-1, 0, 0, -1);
test( 0, -1, -1, 0);
test( 0, -1, 0, -1);
test( 0, 0, -1, -1);
test( 0, 0, -1, 0);
// Check combinations mixing 3 elements from different types.
test(-1, 0, 0, 0);
test( 0, -1, 0, 0);
test( 0, 0, -1, 0);
test( 0, 0, 0, -1);
// Check combinations mixing 4 elements from different types.
test( 0, 0, 0, 0);
```
vs
```js
var IsPossiblyWrappedTypedArray = getSelfHostedValue("IsPossiblyWrappedTypedArray");
var declareSamples = `
var allTypedArraySamples = [
{ value: new Int8Array(1), expected: true },
{ value: new Uint8Array(1), expected: true },
{ value: new Int16Array(1), expected: true },
{ value: new Uint16Array(1), expected: true },
{ value: new Int32Array(1), expected: true },
{ value: new Uint32Array(1), expected: true },
{ value: new Float32Array(1), expected: true },
{ value: new Float64Array(1), expected: true },
{ value: new Uint8ClampedArray(1), expected: true }
];
var allObjectSamples = [
{ value: new Array(1), expected: false },
{ value: {}, expected: false },
{ value: { length: 1 }, expected: false }
];
`;
var g = newGlobal();
evaluate(declareSamples);
g.evaluate(declareSamples);
var assertCode = `function (value, expected) {
assertEq(IsPossiblyWrappedTypedArray(value), expected);
return inIon();
}`;
function checkSamples(samples) {
var assert = new Function(`return (${assertCode})`)();
with ({ }) {
}
;
do {
var spinInJit = true;
for (let i = 0;i < samples.length;i++) {
var e = samples[i];
if (!e) continue;
spinInJit = spinInJit && assert(e.value, e.expected);
}
} while (!spinInJit);
;
}
function test(a, b, c, d) {
var samples = [a == -1 ? null : allTypedArraySamples[a], b == -1 ? null : allObjectSamples[b], c == -1 ? null : g.allTypedArraySamples[c], d == -1 ? null : g.allObjectSamples[d],];
checkSamples(samples);
}
checkSamples(allTypedArraySamples);
checkSamples(allObjectSamples);
checkSamples(g.allTypedArraySamples);
checkSamples(g.allObjectSamples);
test(-1, -1, 0, 0);
test(-1, 0, -1, 0);
test(-1, 0, 0, -1);
test(0, -1, -1, 0);
test(0, -1, 0, -1);
test(0, 0, -1, -1);
test(0, 0, -1, 0);
test(-1, 0, 0, 0);
test(0, -1, 0, 0);
test(0, 0, -1, 0);
test(0, 0, 0, -1);
test(0, 0, 0, 0);
```
<details>
```js
// Test for-of with iter.next and monkeypatching.
function* g(n) { for (var i=0; i<n; i++) yield i; }
var GeneratorObjectPrototype = Object.getPrototypeOf(g).prototype;
var GeneratorObjectPrototype_next = GeneratorObjectPrototype.next;
// Monkeypatch next on an iterator.
var inner = g(20);
var n = 0;
for (let x of inner) {
assertEq(x, n++);
if (n == 1) {
inner.next = function() { throw 'not reached'; };
}
}
assertEq(n, 20);
// Monkeypatch next on the prototype.
var inner = g(20);
var n = 0;
for (let x of inner) {
assertEq(x, n++);
if (n == 1) {
GeneratorObjectPrototype.next = function() { throw 'not reached'; };
}
}
assertEq(n, 20);
```
vs
```js
function *g(n) {
for (let i = 0;i < n;i++) yield i;
}
var GeneratorObjectPrototype = Object.getPrototypeOf(g).prototype;
var GeneratorObjectPrototype_next = GeneratorObjectPrototype.next;
var inner = g(20);
var n = 0;
for (x of inner) {
assertEq(x, n++);
if (n == 1) {
inner.next = function() {
throw 'not reached';
};
}
}
assertEq(n, 20);
var inner = g(20);
var n = 0;
for (x of inner) {
assertEq(x, n++);
if (n == 1) {
GeneratorObjectPrototype.next = function() {
throw 'not reached';
};
}
}
assertEq(n, 20);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/self-hosting/is-possibly-wrapped-typed-array.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/next-shenanigans.js)
<details>
```js
function test() {
var funs = [function() {}, new Proxy(function() {}, {}), wrapWithProto(function() {}, null), new Proxy(createIsHTMLDDA(), {})];
var objects = [{}, new Proxy({}, {}), wrapWithProto({}, null)];
var undefs = [createIsHTMLDDA(), wrapWithProto(createIsHTMLDDA(), null)];
for (var fun of funs) {
assertEq(typeof fun, "function")
}
for (var obj of objects) {
assertEq(typeof obj, "object");
}
for (var undef of undefs) {
assertEq(typeof undef, "undefined");
}
}
test();
```
vs
```js
function test() {
var funs = [function() { }, new Proxy(function() { }, { }), wrapWithProto(function() { }, null), new Proxy(createIsHTMLDDA(), { }),];
var objects = [{ }, new Proxy({ }, { }), wrapWithProto({ }, null),];
var undefs = [createIsHTMLDDA(), wrapWithProto(createIsHTMLDDA(), null),];
for (fun of funs) {
assertEq(typeof fun, "function");
}
for (obj of objects) {
assertEq(typeof obj, "object");
}
for (undef of undefs) {
assertEq(typeof undef, "undefined");
}
}
test();
```
* [Unable to re-interpret from expression to pattern at line: 11, column: 11](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/semantics-09.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/cacheir/typeof-proxy.js)
<details>
```js
// for-of on an empty array does nothing.
for (var x of [])
fail();
```
vs
```js
for (x of []) fail();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-5.js)
<details>
```js
// tests calling script functions via Debugger.Object.prototype.getProperty
// to see if they trigger debugger traps
"use strict";
var global = newGlobal();
var dbg = new Debugger(global);
dbg.onDebuggerStatement = onDebuggerStatement;
let obj;
global.eval(`
const obj = {
get prop() {
debugger;
return 42;
}
};
debugger;
`);
function onDebuggerStatement(frame) {
dbg.onDebuggerStatement = onDebuggerStatementGetter;
obj = frame.environment.getVariable("obj");
}
let debuggerRan = false;
assertEq(obj.getProperty("prop").return, 42);
assertEq(debuggerRan, true);
function onDebuggerStatementGetter(frame) {
debuggerRan = true;
}
```
vs
```js
'use strict';
var global = newGlobal();
var dbg = new Debugger(global);
dbg.onDebuggerStatement = onDebuggerStatement;
let obj;
global.eval(`
const obj = {
get prop() {
debugger;
return 42;
}
};
debugger;
`);
function onDebuggerStatement(frame) {
dbg.onDebuggerStatement = onDebuggerStatementGetter;
obj = frame.environment.getVariable("obj");
}
let debuggerRan = false;
assertEq(obj.getProperty("prop").return, 42);
assertEq(debuggerRan, true);
function onDebuggerStatementGetter(frame) {
debuggerRan = true;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Object-getProperty-02.js)
<details>
```js
Object.extend = function(destination, source) {
for (var property in source)
destination[property] = source[property];
};
var Enumerable = {
_each: function(iterator) {
for (var i = 0, length = this.length; i < length; i++)
iterator(this[i]);
},
each: function(iterator, context) {
var index = 0;
this._each(function(value) {
iterator.call(context, value, index++);
});
},
map: function(iterator, context) {
var results = [];
this.each(function(value, index) {
var res = iterator.call(context, value);
results.push(res);
});
return results;
},
invoke: function(method) {
var args = $A(arguments).slice(1);
return this.map(function(value) {
return value[method].apply(value, args);
});
},
};
Object.extend(Array.prototype, Enumerable);
function $A(iterable) {
var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
}
function g() {
return [1, 2, 3, 4, 5].each(function(part) {
return 0;
});
}
function f() {
g();
g();
g();
g();
var result = [[2, 1, 3], [6, 5, 4]];
result = result.invoke('invoke', 'toString', 2);
result[0].join(', ');
};
f();
```
vs
```js
Object.extend = (function(destination, source) {
for (property in source) destination[property] = source[property];
});
var Enumerable = ({
_each: (function(iterator) {
for (let i = 0, length = this.length;i < length;i++) iterator(this[i]);
}),
each: (function(iterator, context) {
var index = 0;
this._each(function(value) {
iterator.call(context, value, index++);
});
}),
map: (function(iterator, context) {
var results = [];
this.each(function(value, index) {
var res = iterator.call(context, value);
results.push(res);
});
return results;
}),
invoke: (function(method) {
var args = $A(arguments).slice(1);
return this.map(function(value) {
return value[method].apply(value, args);
});
}),
});
Object.extend(Array.prototype, Enumerable);
function $A(iterable) {
var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
}
function g() {
return [1, 2, 3, 4, 5,].each(function(part) {
return 0;
});
}
function f() {
g();
g();
g();
g();
var result = [[2, 1, 3,], [6, 5, 4,],];
result = result.invoke('invoke', 'toString', 2);
result[0].join(', ');
}
;
f();
```
<details>
```js
// |jit-test| --ion-gvn=off;
try {
var g = newGlobal();
var dbg = new Debugger(g);
dbg.onExceptionUnwind = function(m) {
do {
m = m.older;
} while (m != null);
};
g.eval("try { throw (function() {});} finally {}");
} catch(e) {
}
```
vs
```js
try {
var g = newGlobal();
var dbg = new Debugger(g);
dbg.onExceptionUnwind = (function(m) {
do {
m = m.older;
} while (m != null);
;
});
g.eval("try { throw (function() {});} finally {}");
} catch (e) {
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug651119.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/bug1323854-2.js)
<details>
```js
// Ensure the correct frame is passed to exception unwind hooks.
var g = newGlobal();
g.debuggeeGlobal = this;
g.eval("(" + function () {
frames = [];
var dbg = Debugger(debuggeeGlobal);
dbg.onEnterFrame = function(frame) {
frames.push(frame);
};
dbg.onExceptionUnwind = function(frame) {
assertEq(frames.indexOf(frame), frames.length - 1);
frames.pop();
assertEq(frame, dbg.getNewestFrame());
}
} + ")()");
function f(n) {
debugger;
n--;
if (n > 0) {
f(n);
} else {
assertEq(g.frames.length, 10);
throw "fit";
}
}
try {
f(10);
assertEq(0, 1);
} catch (e) {
assertEq(e, "fit");
}
assertEq(g.frames.length, 0);
```
vs
```js
var g = newGlobal();
g.debuggeeGlobal = this;
g.eval("(" + (function() {
frames = [];
var dbg = Debugger(debuggeeGlobal);
dbg.onEnterFrame = function(frame) {
frames.push(frame);
};
dbg.onExceptionUnwind = function(frame) {
assertEq(frames.indexOf(frame), frames.length - 1);
frames.pop();
assertEq(frame, dbg.getNewestFrame());
};
}) + ")()");
function f(n) {
debugger;;
n--;
if (n > 0) {
f(n);
} else {
assertEq(g.frames.length, 10);
throw "fit";
}
}
try {
f(10);
assertEq(0, 1);
} catch (e) {
assertEq(e, "fit");
}
assertEq(g.frames.length, 0);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/baseline/bug836742.js)
<details>
```js
// Two for-of loops on the same slow array get distinct iterators.
var a = [1, 2, 3];
a.slow = true;
var s = '';
for (var x of a)
s += x;
for (var y of a)
s += y;
assertEq(s, '123123');
```
vs
```js
var a = [1, 2, 3,];
a.slow = true;
var s = '';
for (x of a) s += x;
for (y of a) s += y;
assertEq(s, '123123');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-slow-2.js)
<details>
```js
var obj = {};
var sym = Symbol();
var notEqual = [
[obj, sym],
[0, {valueOf() { return null; }}],
[0, {toString() { return null; }}],
[null, {valueOf() { return null; }}],
[null, {toString() { return null; }}],
[undefined, {valueOf() { return null; }}],
[undefined, {toString() { return null; }}],
["", {valueOf() { return null; }}],
["", {toString() { return null; }}],
["0", {valueOf() { return null; }}],
["0", {toString() { return null; }}],
[0, {valueOf() { return undefined; }}],
[0, {toString() { return undefined; }}],
[null, {valueOf() { return undefined; }}],
[null, {toString() { return undefined; }}],
[undefined, {valueOf() { return undefined; }}],
[undefined, {toString() { return undefined; }}],
["", {valueOf() { return undefined; }}],
["", {toString() { return undefined; }}],
["0", {valueOf() { return undefined; }}],
["0", {toString() { return undefined; }}],
]
var equal = [
[sym, {valueOf() { return sym; }}],
[sym, {toString() { return sym; }}],
["abc", {valueOf() { return "abc"; }}],
["abc", {toString() { return "abc"; }}],
[1, {valueOf() { return 1; }}],
[1, {toString() { return 1; }}],
[1, {valueOf() { return true; }}],
[1, {toString() { return true; }}],
[true, {valueOf() { return true; }}],
[true, {toString() { return true; }}],
[true, {valueOf() { return 1; }}],
[true, {toString() { return 1; }}],
]
for (var [lhs, rhs] of notEqual) {
assertEq(lhs == rhs, false);
assertEq(rhs == lhs, false);
}
for (var [lhs, rhs] of equal) {
assertEq(lhs == rhs, true);
assertEq(rhs == lhs, true);
}
```
vs
```js
var obj = ({});
var sym = Symbol();
var notEqual = [[obj, sym,], [0, ({
valueOf: (function() {
return null;
}),
}),], [0, ({
toString: (function() {
return null;
}),
}),], [null, ({
valueOf: (function() {
return null;
}),
}),], [null, ({
toString: (function() {
return null;
}),
}),], [undefined, ({
valueOf: (function() {
return null;
}),
}),], [undefined, ({
toString: (function() {
return null;
}),
}),], ["", ({
valueOf: (function() {
return null;
}),
}),], ["", ({
toString: (function() {
return null;
}),
}),], ["0", ({
valueOf: (function() {
return null;
}),
}),], ["0", ({
toString: (function() {
return null;
}),
}),], [0, ({
valueOf: (function() {
return undefined;
}),
}),], [0, ({
toString: (function() {
return undefined;
}),
}),], [null, ({
valueOf: (function() {
return undefined;
}),
}),], [null, ({
toString: (function() {
return undefined;
}),
}),], [undefined, ({
valueOf: (function() {
return undefined;
}),
}),], [undefined, ({
toString: (function() {
return undefined;
}),
}),], ["", ({
valueOf: (function() {
return undefined;
}),
}),], ["", ({
toString: (function() {
return undefined;
}),
}),], ["0", ({
valueOf: (function() {
return undefined;
}),
}),], ["0", ({
toString: (function() {
return undefined;
}),
}),],];
var equal = [[sym, ({
valueOf: (function() {
return sym;
}),
}),], [sym, ({
toString: (function() {
return sym;
}),
}),], ["abc", ({
valueOf: (function() {
return "abc";
}),
}),], ["abc", ({
toString: (function() {
return "abc";
}),
}),], [1, ({
valueOf: (function() {
return 1;
}),
}),], [1, ({
toString: (function() {
return 1;
}),
}),], [1, ({
valueOf: (function() {
return true;
}),
}),], [1, ({
toString: (function() {
return true;
}),
}),], [true, ({
valueOf: (function() {
return true;
}),
}),], [true, ({
toString: (function() {
return true;
}),
}),], [true, ({
valueOf: (function() {
return 1;
}),
}),], [true, ({
toString: (function() {
return 1;
}),
}),],];
for ([lhs,rhs,] of notEqual) {
assertEq(lhs == rhs, false);
assertEq(rhs == lhs, false);
}
for ([lhs,rhs,] of equal) {
assertEq(lhs == rhs, true);
assertEq(rhs == lhs, true);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/object-loose-equality.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var args;
function* upToTen()
{
"use strict";
eval("args = arguments;");
for (var i = 0; i < 9; i++)
yield i;
}
var gen = upToTen();
var i = 0;
for (var v of gen)
{
assertEq(v, i);
i++;
}
assertEq(i, 9);
assertEq(Object.prototype.toString.call(args), "[object Arguments]");
assertEq(args.length, 0);
```
vs
```js
var args;
function *upToTen() {
'use strict';
eval("args = arguments;");
for (let i = 0;i < 9;i++) yield i;
}
var gen = upToTen();
var i = 0;
for (v of gen) {
assertEq(v, i);
i++;
}
assertEq(i, 9);
assertEq(Object.prototype.toString.call(args), "[object Arguments]");
assertEq(args.length, 0);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/strict-args-generator-flushstack.js)
<details>
```js
// for-of does not skip trailing holes; the value is undefined.
var log = "";
for (var x of [1, 2, 3,,])
log += x;
assertEq(log, "123undefined");
```
vs
```js
var log = "";
for (x of [1, 2, 3,,]) log += x;
assertEq(log, "123undefined");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/array-holes-5.js)
<details>
```js
// Changing arguments.length affects a for-of loop iterating over arguments.
load(libdir + "iteration.js");
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var s;
function f() {
arguments.length = 2;
for (var v of arguments)
s += v;
}
s = '';
f('a', 'b', 'c', 'd', 'e');
assertEq(s, 'ab');
```
vs
```js
load(libdir + "iteration.js");
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var s;
function f() {
arguments.length = 2;
for (v of arguments) s += v;
}
s = '';
f('a', 'b', 'c', 'd', 'e');
assertEq(s, 'ab');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arguments-6.js)
* [Unable to re-interpret from expression to pattern at line: 5, column: 17](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/destructuring-exprbody.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/testBug775807.js)
<details>
```js
// Removing and re-adding entries while an iterator is live causes the iterator to visit them again.
var set = new Set(['a']);
var n = 5;
for (let v of set) {
assertEq(v, 'a');
if (n === 0)
break;
set.delete('a');
set.add('a');
n--;
}
assertEq(n, 0);
```
vs
```js
var set = new Set(['a',]);
var n = 5;
for (v of set) {
assertEq(v, 'a');
if (n === 0) break;
set.delete('a');
set.add('a');
n--;
}
assertEq(n, 0);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-iterator-add-remove.js)
<details>
```js
// Debugger.Frame.prototype.live is true for frames on the stack and false for
// frames that have returned
var desc = Object.getOwnPropertyDescriptor(Debugger.Frame.prototype, "live");
assertEq(typeof desc.get, "function");
assertEq(desc.set, undefined);
assertEq(desc.configurable, true);
assertEq(desc.enumerable, false);
var loc;
var g = newGlobal();
g.debuggeeGlobal = this;
g.eval("var hits = 0;");
g.eval("(" + function () {
var a = [];
var dbg = Debugger(debuggeeGlobal);
dbg.onDebuggerStatement = function (frame) {
var loc = debuggeeGlobal.loc;
a[loc] = frame;
for (var i = 0; i < a.length; i++) {
assertEq(a[i] === frame, i === loc);
assertEq(!!(a[i] && a[i].live), i >= loc);
}
hits++;
};
} + ")()");
function f(n) {
loc = n; debugger;
if (n !== 0) {
f(n - 1);
loc = n; debugger;
eval("f(n - 1);");
loc = n; debugger;
}
}
f(4);
assertEq(g.hits, 16 + 8*3 + 4*3 + 2*3 + 1*3);
```
vs
```js
var desc = Object.getOwnPropertyDescriptor(Debugger.Frame.prototype, "live");
assertEq(typeof desc.get, "function");
assertEq(desc.set, undefined);
assertEq(desc.configurable, true);
assertEq(desc.enumerable, false);
var loc;
var g = newGlobal();
g.debuggeeGlobal = this;
g.eval("var hits = 0;");
g.eval("(" + (function() {
var a = [];
var dbg = Debugger(debuggeeGlobal);
dbg.onDebuggerStatement = function(frame) {
var loc = debuggeeGlobal.loc;
a[loc] = frame;
for (let i = 0;i < a.length;i++) {
assertEq(a[i] === frame, i === loc);
assertEq(!!a[i] && a[i].live, i >= loc);
}
hits++;
};
}) + ")()");
function f(n) {
loc = n;
debugger;;
if (n !== 0) {
f(n - 1);
loc = n;
debugger;;
eval("f(n - 1);");
loc = n;
debugger;;
}
}
f(4);
assertEq(g.hits, 16 + 8 * 3 + 4 * 3 + 2 * 3 + 1 * 3);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Frame-live-01.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/testDenseArrayProp.js)
<details>
```js
load(libdir + 'asserts.js');
function test() {
let obj = {
toSource() {
throw 1;
}
};
assertTypeErrorMessage(() => { ctypes.double().value = obj; },
"can't convert <<error converting value to string>> to the type double");
}
if (typeof ctypes === "object")
test();
```
vs
```js
load(libdir + 'asserts.js');
function test() {
let obj = {
toSource: function() {
throw 1;
},
};
assertTypeErrorMessage(() => {
ctypes.double().value = obj;
}, "can't convert <<error converting value to string>> to the type double");
}
if (typeof ctypes === "object") test();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ctypes/conversion-error.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
load(libdir + 'array-compare.js');
function strictEval(code, p)
{
"use strict";
eval(code);
return arguments;
}
var a1, a2, a3, a4, a5, a6;
for (var i = 0; i < 5; i++)
{
a1 = strictEval("1", 2);
a2 = strictEval("arguments");
a3 = strictEval("p = 2");
a4 = strictEval("p = 2", 17);
a5 = strictEval("arguments[0] = 17");
a6 = strictEval("arguments[0] = 17", 42);
}
assertEq(arraysEqual(a1, ["1", 2]), true);
assertEq(arraysEqual(a2, ["arguments"]), true);
assertEq(arraysEqual(a3, ["p = 2"]), true);
assertEq(arraysEqual(a4, ["p = 2", 17]), true);
assertEq(arraysEqual(a5, [17]), true);
assertEq(arraysEqual(a6, [17, 42]), true);
```
vs
```js
load(libdir + 'array-compare.js');
function strictEval(code, p) {
'use strict';
eval(code);
return arguments;
}
var a1, a2, a3, a4, a5, a6;
for (let i = 0;i < 5;i++) {
a1 = strictEval("1", 2);
a2 = strictEval("arguments");
a3 = strictEval("p = 2");
a4 = strictEval("p = 2", 17);
a5 = strictEval("arguments[0] = 17");
a6 = strictEval("arguments[0] = 17", 42);
}
assertEq(arraysEqual(a1, ["1", 2,]), true);
assertEq(arraysEqual(a2, ["arguments",]), true);
assertEq(arraysEqual(a3, ["p = 2",]), true);
assertEq(arraysEqual(a4, ["p = 2", 17,]), true);
assertEq(arraysEqual(a5, [17,]), true);
assertEq(arraysEqual(a6, [17, 42,]), true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/strict-eval.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/baseline/bug843429.js)
<details>
```js
function DiagModule(stdlib, foreign) {
"use asm";
var sqrt = stdlib.Math.sqrt;
var test = foreign.test;
var foo = foreign.foo;
function square(x) {
x = x|0;
return ((x|0)+(x|0))|0;
}
function diag() {
var x = 0.0;
while(1) {
test(1, x);
x = x+1.0
if (x > 15.0)
return 0;
}
return 0;
}
function diag_1() {
foo();
return 0;
}
return { diag: diag, diag_1:diag_1 };
}
var foreign = {
test:function(a,b) {
print(a+":"+b)
var c = [0.0];
if (b > 10)
return c[1];
return c[0];
},
foo:function() {
with({}) {};
gc();
}
}
// make sure foreign is compiled
var fast = DiagModule(this, foreign); // produces AOT-compiled version
print(fast.diag_1()); // 5
gc()
print(fast.diag()); // 5
```
vs
```js
function DiagModule(stdlib, foreign) {
"use asm";
var sqrt = stdlib.Math.sqrt;
var test = foreign.test;
var foo = foreign.foo;
function square(x) {
x = x | 0;
return x | 0 + x | 0 | 0;
}
function diag() {
var x = 0.0;
while (1) {
test(1, x);
x = x + 1.0;
if (x > 15.0) return 0;
}
return 0;
}
function diag_1() {
foo();
return 0;
}
return {
diag: diag,
diag_1: diag_1,
};
}
var foreign = ({
test: (function(a, b) {
print(a + ":" + b);
var c = [0.0,];
if (b > 10) return c[1];
return c[0];
}),
foo: (function() {
with ({ }) {
}
;
gc();
}),
});
var fast = DiagModule(this, foreign);
print(fast.diag_1());
gc();
print(fast.diag());
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/bug860838-4.js)
<details>
```js
// for-of works on a cross-compartment wrapper of a Set.
var g = newGlobal();
var mw = g.eval("new Set(['a', 'b', 1, 2])");
var log = '';
for (let x of mw)
log += x;
assertEq(log, "ab12");
```
vs
```js
var g = newGlobal();
var mw = g.eval("new Set(['a', 'b', 1, 2])");
var log = '';
for (x of mw) log += x;
assertEq(log, "ab12");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-iterator-proxies-1.js)
<details>
```js
// for-of on a slow Array consults the prototype chain when it encounters a hole.
var a = [0, , , 3];
a.slow = true;
Object.prototype[1] = 'peek1';
Array.prototype[2] = 'peek2';
var log = [];
for (var x of a)
log.push(x);
assertEq(log[1], 'peek1');
assertEq(log[2], 'peek2');
assertEq(log.join(), "0,peek1,peek2,3");
```
vs
```js
var a = [0,,, 3,];
a.slow = true;
Object.prototype[1] = 'peek1';
Array.prototype[2] = 'peek2';
var log = [];
for (x of a) log.push(x);
assertEq(log[1], 'peek1');
assertEq(log[2], 'peek2');
assertEq(log.join(), "0,peek1,peek2,3");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/array-holes-slow.js)
<details>
```js
// |jit-test| test-also-no-wasm-baseline; skip-if: !wasmDebuggingIsSupported()
// Tests that wasm module sourceMappingURL section is parsed.
load(libdir + "asserts.js");
load(libdir + "wasm-binary.js");
var g = newGlobal();
var dbg = new Debugger(g);
var gotScript;
dbg.allowWasmBinarySource = true;
dbg.onNewScript = (script) => {
gotScript = script;
}
function toU8(array) {
for (let b of array)
assertEq(b < 256, true);
return Uint8Array.from(array);
}
function varU32(u32) {
assertEq(u32 >= 0, true);
assertEq(u32 < Math.pow(2,32), true);
var bytes = [];
do {
var byte = u32 & 0x7f;
u32 >>>= 7;
if (u32 != 0)
byte |= 0x80;
bytes.push(byte);
} while (u32 != 0);
return bytes;
}
function string(name) {
var nameBytes = name.split('').map(c => {
var code = c.charCodeAt(0);
assertEq(code < 128, true); // TODO
return code;
});
return varU32(nameBytes.length).concat(nameBytes);
}
function appendSourceMappingURL(wasmBytes, url) {
if (!url)
return wasmBytes;
var payload = [...string('sourceMappingURL'), ...string(url)];
return Uint8Array.from([...wasmBytes, userDefinedId, payload.length, ...payload]);
}
g.toWasm = (wast, url) => appendSourceMappingURL(wasmTextToBinary(wast), url);
// The sourceMappingURL section is not present
g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(toWasm('(module (func) (export "" 0))')));`);
assertEq(gotScript.format, "wasm");
assertEq(gotScript.source.sourceMapURL, null);
// The sourceMappingURL section is present
g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(toWasm('(module (func) (export "a" 0))', 'http://example.org/test')));`);
assertEq(gotScript.format, "wasm");
assertEq(gotScript.source.sourceMapURL, 'http://example.org/test');
// The sourceMapURL is read-only for wasm
assertThrowsInstanceOf(() => gotScript.source.sourceMapURL = 'foo', Error);
// The sourceMappingURL section is present, and is still available when wasm
// binary source is disabled.
dbg.allowWasmBinarySource = false;
g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(toWasm('(module (func) (export "a" 0))', 'http://example.org/test2')));`);
assertEq(gotScript.format, "wasm");
assertEq(gotScript.source.sourceMapURL, 'http://example.org/test2');
```
vs
```js
load(libdir + "asserts.js");
load(libdir + "wasm-binary.js");
var g = newGlobal();
var dbg = new Debugger(g);
var gotScript;
dbg.allowWasmBinarySource = true;
dbg.onNewScript = script => {
gotScript = script;
};
function toU8(array) {
for (b of array) assertEq(b < 256, true);
return Uint8Array.from(array);
}
function varU32(u32) {
assertEq(u32 >= 0, true);
assertEq(u32 < Math.pow(2, 32), true);
var bytes = [];
do {
var byte = u32 & 0x7f;
u32 >>>= 7;
if (u32 != 0) byte |= 0x80;
bytes.push(byte);
} while (u32 != 0);
;
return bytes;
}
function string(name) {
var nameBytes = name.split('').map(c => {
var code = c.charCodeAt(0);
assertEq(code < 128, true);
return code;
});
return varU32(nameBytes.length).concat(nameBytes);
}
function appendSourceMappingURL(wasmBytes, url) {
if (!url) return wasmBytes;
var payload = [...string('sourceMappingURL'), ...string(url),];
return Uint8Array.from([...wasmBytes, userDefinedId, payload.length, ...payload,]);
}
g.toWasm = (wast, url) => appendSourceMappingURL(wasmTextToBinary(wast), url);
g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(toWasm('(module (func) (export "" 0))')));`);
assertEq(gotScript.format, "wasm");
assertEq(gotScript.source.sourceMapURL, null);
g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(toWasm('(module (func) (export "a" 0))', 'http://example.org/test')));`);
assertEq(gotScript.format, "wasm");
assertEq(gotScript.source.sourceMapURL, 'http://example.org/test');
assertThrowsInstanceOf(() => gotScript.source.sourceMapURL = 'foo', Error);
dbg.allowWasmBinarySource = false;
g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(toWasm('(module (func) (export "a" 0))', 'http://example.org/test2')));`);
assertEq(gotScript.format, "wasm");
assertEq(gotScript.source.sourceMapURL, 'http://example.org/test2');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/wasm-sourceMappingURL.js)
* [Unexpected Token at line: 4, column: 16: Expected `function`, `this`, `class`, or `import`; found Keyword(Import)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/modules/import-meta.js)
<details>
```js
// A for-of loop over an array stops at the new end of the array if it shrinks during iteration.
function ispal(arr) {
for (var v of arr) {
if (v !== arr.pop())
return false;
}
return true;
}
assertEq(ispal([1, 2, 3, 4, 3, 2, 1]), true);
assertEq(ispal([1, 2, 3, 3, 2, 1]), true);
assertEq(ispal([1, 2, 3, 4, 2, 1]), false);
```
vs
```js
function ispal(arr) {
for (v of arr) {
if (v !== arr.pop()) return false;
}
return true;
}
assertEq(ispal([1, 2, 3, 4, 3, 2, 1,]), true);
assertEq(ispal([1, 2, 3, 3, 2, 1,]), true);
assertEq(ispal([1, 2, 3, 4, 2, 1,]), false);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-shrinking-1.js)
<details>
```js
// Nested for-of loops can iterate over a Map.
var map = new Map([['a', 0], ['b', 1]]);
var log = '';
for (let [k0, v0] of map) {
log += k0 + v0 + ':'
for (let [k1, v1] of map)
log += k1 + v1;
log += ';'
};
assertEq(log, 'a0:a0b1;b1:a0b1;');
```
vs
```js
var map = new Map([['a', 0,], ['b', 1,],]);
var log = '';
for ([k0,v0,] of map) {
log += k0 + v0 + ':';
for ([k1,v1,] of map) log += k1 + v1;
log += ';';
}
;
assertEq(log, 'a0:a0b1;b1:a0b1;');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Map-iterator-2.js)
<details>
```js
// A for-of loop over an array continues to the end if the array grows during iteration.
var a = [0, 1, 1, 0, 1, 0, 0];
var s = '';
for (var v of a) {
s += v;
if (v === 1)
a.push(2);
}
assertEq(s, '0110100222');
```
vs
```js
var a = [0, 1, 1, 0, 1, 0, 0,];
var s = '';
for (v of a) {
s += v;
if (v === 1) a.push(2);
}
assertEq(s, '0110100222');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-growing-1.js)
<details>
```js
// for-of can iterate over float typed arrays containing infinities or NaNs.
var values = [Infinity, -Infinity, -0, NaN];
for (var C of [Float32Array, Float64Array]) {
var i = 0;
for (var v of new C(values))
assertEq(v, values[i++]);
assertEq(i, values.length);
}
```
vs
```js
var values = [Infinity, -Infinity, -0, NaN,];
for (C of [Float32Array, Float64Array,]) {
var i = 0;
for (v of new C(values)) assertEq(v, values[i++]);
assertEq(i, values.length);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/typedarrays-6.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
setJitCompilerOption("ion.warmup.trigger", 30);
var PointType = TypedObject.uint16.array(3);
var VecPointType = PointType.array(3);
function foo() {
for (var i = 0; i < 5000; i += 10) {
var vec = new VecPointType();
var i0 = i % 3;
var i1 = (i+1) % 3;
var i2 = (i+2) % 3;
vec[i0][i0] = i;
vec[i0][i1] = i+1;
vec[i0][i2] = i+2;
vec[i1][i0] = i+3;
vec[i1][i1] = i+4;
vec[i1][i2] = i+5;
vec[i2][i0] = i+6;
vec[i2][i1] = i+7;
vec[i2][i2] = i+8;
var sum = vec[i0][i0] + vec[i0][i1] + vec[i0][i2];
assertEq(sum, 3*i + 3);
sum = vec[i1][i0] + vec[i1][i1] + vec[i1][i2];
assertEq(sum, 3*i + 12);
sum = vec[i2][i0] + vec[i2][i1] + vec[i2][i2];
assertEq(sum, 3*i + 21);
}
}
foo();
```
vs
```js
setJitCompilerOption("ion.warmup.trigger", 30);
var PointType = TypedObject.uint16.array(3);
var VecPointType = PointType.array(3);
function foo() {
for (let i = 0;i < 5000;i += 10) {
var vec = new VecPointType();
var i0 = i % 3;
var i1 = i + 1 % 3;
var i2 = i + 2 % 3;
vec[i0][i0] = i;
vec[i0][i1] = i + 1;
vec[i0][i2] = i + 2;
vec[i1][i0] = i + 3;
vec[i1][i1] = i + 4;
vec[i1][i2] = i + 5;
vec[i2][i0] = i + 6;
vec[i2][i1] = i + 7;
vec[i2][i2] = i + 8;
var sum = vec[i0][i0] + vec[i0][i1] + vec[i0][i2];
assertEq(sum, 3 * i + 3);
sum = vec[i1][i0] + vec[i1][i1] + vec[i1][i2];
assertEq(sum, 3 * i + 12);
sum = vec[i2][i0] + vec[i2][i1] + vec[i2][i2];
assertEq(sum, 3 * i + 21);
}
}
foo();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/TypedObject/jit-write-u16-into-mdim-array.js)
<details>
```js
setJitCompilerOption("ion.forceinlineCaches", 1);
let offsets = [213, 559, 255, 515, 30, 507, 252, 329, 487, 7];
function update_index(i, j) {
var offset = offsets[j % offsets.length];
return i + offset;
}
function compute_index(initial, count) {
for (var i = 0; i < count; i++) {
initial = update_index(initial, i);
}
return initial;
}
// This is written so that the IC added in the bug activates.
function mutate_array(array, count, epsilon = 0) {
var index = 0;
for (var i = 0; i < count; i++) {
index = update_index(index, i);
array[index] = i + epsilon;
}
return array[offsets[0]+offsets[1]] === (1 + epsilon) &&
array[10] === undefined;
}
// Monomorphizing mutate_array to ensure we get the IC chains we want
function create_variant(variant) {
var source = mutate_array.toString().replace("mutate_array", "mutate_array_"+variant);
return source;
}
function test_basic() {
eval(create_variant("basic"));
var x = [];
var count = 100;
assertEq(mutate_array_basic(x, count), true);
var end = compute_index(0, count);
assertEq(x[end], count - 1);
assertEq(x[end - 1], undefined);
}
// Ensure the IC respects frozen.
function test_frozen() {
eval(create_variant("frozen"));
var x = [];
Object.freeze(x);
var count = 100;
assertEq(mutate_array_frozen(x, count), false);
assertEq(x.length, 0);
var end = compute_index(0, count);
var y = [];
assertEq(mutate_array_frozen(y, count), true);
assertEq(y[end], count - 1);
Object.freeze(y);
// After a mutated array is frozen, can't subsequently modify elements
assertEq(mutate_array_frozen(x, count, 10), false);
assertEq(y[end], count - 1);
}
// Let's make sure updates to the array happen as expected.
function test_update() {
eval(create_variant("update"));
var x = [];
var count = 100;
assertEq(mutate_array_update(x, count), true);
var end = compute_index(0, count);
assertEq(x[end], count - 1);
assertEq(x[end - 1], undefined);
var epsilon = 2;
mutate_array_update(x, 200, epsilon);
assertEq(x[end], count -1 + epsilon)
}
// Elements may be non-writable, let us not write them.
function test_nonwritable() {
eval(create_variant("nonwritable"));
var x = [];
var count = 100;
var index = compute_index(0, 10);
Object.defineProperty(x, index, {value: -10, writable: false});
mutate_array_nonwritable(x, count);
assertEq(x[index], -10);
}
// Random indices can get setters, let's make sure we honour those.
function test_setter() {
eval(create_variant("setter"));
var x = [];
var count = 100;
var index = compute_index(0, 80);
var sigil = 0;
Object.defineProperty(x, index, {set(newVal) {sigil++; }});
mutate_array_setter(x, count);
assertEq(sigil, 1);
assertEq(x[index], undefined);
}
// Ensure indexes on the prototype don't break things;
//
function test_proto_indices() {
eval(create_variant("proto_indices"));
var x = [];
var count = 100;
var index = compute_index(0, 80);
x.__proto__[index] = "hello";
mutate_array_proto_indices(x, count);
assertEq(x.__proto__[index], "hello");
assertEq(x[index], 79);
}
test_basic();
test_frozen();
test_update();
test_nonwritable();
test_setter();
test_proto_indices();
```
vs
```js
setJitCompilerOption("ion.forceinlineCaches", 1);
let offsets = [213, 559, 255, 515, 30, 507, 252, 329, 487, 7,];
function update_index(i, j) {
var offset = offsets[j % offsets.length];
return i + offset;
}
function compute_index(initial, count) {
for (let i = 0;i < count;i++) {
initial = update_index(initial, i);
}
return initial;
}
function mutate_array(array, count, epsilon = 0) {
var index = 0;
for (let i = 0;i < count;i++) {
index = update_index(index, i);
array[index] = i + epsilon;
}
return array[offsets[0] + offsets[1]] === 1 + epsilon && array[10] === undefined;
}
function create_variant(variant) {
var source = mutate_array.toString().replace("mutate_array", "mutate_array_" + variant);
return source;
}
function test_basic() {
eval(create_variant("basic"));
var x = [];
var count = 100;
assertEq(mutate_array_basic(x, count), true);
var end = compute_index(0, count);
assertEq(x[end], count - 1);
assertEq(x[end - 1], undefined);
}
function test_frozen() {
eval(create_variant("frozen"));
var x = [];
Object.freeze(x);
var count = 100;
assertEq(mutate_array_frozen(x, count), false);
assertEq(x.length, 0);
var end = compute_index(0, count);
var y = [];
assertEq(mutate_array_frozen(y, count), true);
assertEq(y[end], count - 1);
Object.freeze(y);
assertEq(mutate_array_frozen(x, count, 10), false);
assertEq(y[end], count - 1);
}
function test_update() {
eval(create_variant("update"));
var x = [];
var count = 100;
assertEq(mutate_array_update(x, count), true);
var end = compute_index(0, count);
assertEq(x[end], count - 1);
assertEq(x[end - 1], undefined);
var epsilon = 2;
mutate_array_update(x, 200, epsilon);
assertEq(x[end], count - 1 + epsilon);
}
function test_nonwritable() {
eval(create_variant("nonwritable"));
var x = [];
var count = 100;
var index = compute_index(0, 10);
Object.defineProperty(x, index, {
value: -10,
writable: false,
});
mutate_array_nonwritable(x, count);
assertEq(x[index], -10);
}
function test_setter() {
eval(create_variant("setter"));
var x = [];
var count = 100;
var index = compute_index(0, 80);
var sigil = 0;
Object.defineProperty(x, index, {
set: function(newVal) {
sigil++;
},
});
mutate_array_setter(x, count);
assertEq(sigil, 1);
assertEq(x[index], undefined);
}
function test_proto_indices() {
eval(create_variant("proto_indices"));
var x = [];
var count = 100;
var index = compute_index(0, 80);
x.__proto__[index] = "hello";
mutate_array_proto_indices(x, count);
assertEq(x.__proto__[index], "hello");
assertEq(x[index], 79);
}
test_basic();
test_frozen();
test_update();
test_nonwritable();
test_setter();
test_proto_indices();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/cacheir/bug1494537.js)
<details>
```js
// Basic for-of test with Proxy.
var s = '';
var arr = ['a', 'b', 'c', 'd'];
var p = new Proxy(arr, {});
// Test the same proxy twice.
for (var i = 0; i < 2; i++) {
var j = 0;
for (var x of p)
assertEq(x, arr[j++]);
assertEq(j, arr.length);
}
```
vs
```js
var s = '';
var arr = ['a', 'b', 'c', 'd',];
var p = new Proxy(arr, ({}));
for (let i = 0;i < 2;i++) {
var j = 0;
for (x of p) assertEq(x, arr[j++]);
assertEq(j, arr.length);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/proxy-1.js)
<details>
```js
function f()
{
return (4 >>> 0) > ((0 % (1 == 2)) >>> 0);
}
assertEq(f(), true);
assertEq(f(), true);
```
vs
```js
function f() {
return 4 >>> 0 > 0 % 1 == 2 >>> 0;
}
assertEq(f(), true);
assertEq(f(), true);
```
<details>
```js
load(libdir + "eqArrayHelper.js");
function check(f) {
assertEqArray(f.call(...[null], 1, 2, 3), [1, 2, 3]);
assertEqArray(f.call(...[null], 1, ...[2, 3], 4, ...[5, 6]), [1, 2, 3, 4, 5, 6]);
assertEqArray(f.call(...[null, 1], ...[2, 3], 4, ...[5, 6]), [1, 2, 3, 4, 5, 6]);
assertEqArray(f.call(...[null, 1, ...[2, 3], 4, ...[5, 6]]), [1, 2, 3, 4, 5, 6]);
}
check(function(...x) { return x; });
check((...x) => x);
```
vs
```js
load(libdir + "eqArrayHelper.js");
function check(f) {
assertEqArray(f.call(...[null,], 1, 2, 3), [1, 2, 3,]);
assertEqArray(f.call(...[null,], 1, ...[2, 3,], 4, ...[5, 6,]), [1, 2, 3, 4, 5, 6,]);
assertEqArray(f.call(...[null, 1,], ...[2, 3,], 4, ...[5, 6,]), [1, 2, 3, 4, 5, 6,]);
assertEqArray(f.call(...[null, 1, ...[2, 3,], 4, ...[5, 6,],]), [1, 2, 3, 4, 5, 6,]);
}
check((function(x) {
return x;
}));
check(x => x);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/bug889186.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/basic/spread-call-funcall.js)
<details>
```js
"use strict";
load(libdir + "asserts.js");
load(libdir + "dummyModuleResolveHook.js");
class UniqueError extends Error {}
let a = moduleRepo['a'] = parseModule(`
throw new UniqueError();
`);
let b = moduleRepo['b'] = parseModule(`
import * as ns0 from "a";
`);
a.declarationInstantiation();
assertThrowsInstanceOf(() => a.evaluation(), UniqueError);
b.declarationInstantiation();
assertThrowsInstanceOf(() => b.evaluation(), UniqueError);
```
vs
```js
'use strict';
load(libdir + "asserts.js");
load(libdir + "dummyModuleResolveHook.js");
class UniqueError extends Error {
}
let a = moduleRepo['a'] = parseModule(`
throw new UniqueError();
`);
let b = moduleRepo['b'] = parseModule(`
import * as ns0 from "a";
`);
a.declarationInstantiation();
assertThrowsInstanceOf(() => a.evaluation(), UniqueError);
b.declarationInstantiation();
assertThrowsInstanceOf(() => b.evaluation(), UniqueError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/modules/bug-1476921.js)
<details>
```js
// |jit-test| slow;
function randomRecursion() {
var y = ""
if (rnd(2)) {
var x = 2;
"{" + x + "}";
randomRecursion();
randomRecursion();
return [""];
}
return [""];
}
function thisFunctionIsNeverCalled() {
}
function testOne() {
ox = newGlobal();
var code = randomRecursion()[rnd(3)];
}
initRnd();
gczeal(10, 3);
for (var count = 0; count < 20; count++) {
print(count);
testOne()
}
// ==========================================================================================
// this program is a JavaScript version of Mersenne Twister, with concealment and encapsulation in class,
// an almost straight conversion from the original program, mt19937ar.c,
// translated by y. okada on July 17, 2006.
// Changes by Jesse Ruderman: added "var" keyword in a few spots; added export_mta etc; pasted into fuzz.js.
// in this program, procedure descriptions and comments of original source code were not removed.
// lines commented with //c// were originally descriptions of c procedure. and a few following lines are appropriate JavaScript descriptions.
// lines commented with /* and */ are original comments.
// lines commented with // are additional comments in this JavaScript version.
// before using this version, create at least one instance of MersenneTwister19937 class, and initialize the each state, given below in c comments, of all the instances.
/*
A C-program for MT19937, with initialization improved 2002/1/26.
Coded by Takuji Nishimura and Makoto Matsumoto.
Before using, initialize the state by using init_genrand(seed)
or init_by_array(init_key, key_length).
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Any feedback is very welcome.
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
*/
function MersenneTwister19937()
{
/* Period parameters */
//c//#define N 624
//c//#define M 397
//c//#define MATRIX_A 0x9908b0dfUL /* constant vector a */
//c//#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
//c//#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
var N = 624;
var M = 397;
var MATRIX_A = 0x9908b0df; /* constant vector a */
var UPPER_MASK = 0x80000000; /* most significant w-r bits */
var LOWER_MASK = 0x7fffffff; /* least significant r bits */
//c//static unsigned long mt[N]; /* the array for the state vector */
//c//static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
var mt = new Array(N); /* the array for the state vector */
var mti = N+1; /* mti==N+1 means mt[N] is not initialized */
function unsigned32 (n1) // returns a 32-bits unsiged integer from an operand to which applied a bit operator.
{
return n1 < 0 ? (n1 ^ UPPER_MASK) + UPPER_MASK : n1;
}
function subtraction32 (n1, n2) // emulates lowerflow of a c 32-bits unsiged integer variable, instead of the operator -. these both arguments must be non-negative integers expressible using unsigned 32 bits.
{
return n1 < n2 ? unsigned32((0x100000000 - (n2 - n1)) & 0xffffffff) : n1 - n2;
}
function addition32 (n1, n2) // emulates overflow of a c 32-bits unsiged integer variable, instead of the operator +. these both arguments must be non-negative integers expressible using unsigned 32 bits.
{
return unsigned32((n1 + n2) & 0xffffffff)
}
function multiplication32 (n1, n2) // emulates overflow of a c 32-bits unsiged integer variable, instead of the operator *. these both arguments must be non-negative integers expressible using unsigned 32 bits.
{
var sum = 0;
for (var i = 0; i < 32; ++i){
if ((n1 >>> i) & 0x1){
sum = addition32(sum, unsigned32(n2 << i));
}
}
return sum;
}
/* initializes mt[N] with a seed */
//c//void init_genrand(unsigned long s)
this.init_genrand = function (s)
{
//c//mt[0]= s & 0xffffffff;
mt[0]= unsigned32(s & 0xffffffff);
for (mti=1; mti<N; mti++) {
mt[mti] =
//c//(1812433253 * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
addition32(multiplication32(1812433253, unsigned32(mt[mti-1] ^ (mt[mti-1] >>> 30))), mti);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
//c//mt[mti] &= 0xffffffff;
mt[mti] = unsigned32(mt[mti] & 0xffffffff);
/* for >32 bit machines */
}
}
/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* slight change for C++, 2004/2/26 */
//c//void init_by_array(unsigned long init_key[], int key_length)
this.init_by_array = function (init_key, key_length)
{
//c//int i, j, k;
var i, j, k;
//c//init_genrand(19650218);
this.init_genrand(19650218);
i=1; j=0;
k = (N>key_length ? N : key_length);
for (; k; k--) {
//c//mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525))
//c// + init_key[j] + j; /* non linear */
mt[i] = addition32(addition32(unsigned32(mt[i] ^ multiplication32(unsigned32(mt[i-1] ^ (mt[i-1] >>> 30)), 1664525)), init_key[j]), j);
mt[i] =
//c//mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */
unsigned32(mt[i] & 0xffffffff);
i++; j++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
if (j>=key_length) j=0;
}
for (k=N-1; k; k--) {
//c//mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941))
//c//- i; /* non linear */
mt[i] = subtraction32(unsigned32((dbg=mt[i]) ^ multiplication32(unsigned32(mt[i-1] ^ (mt[i-1] >>> 30)), 1566083941)), i);
//c//mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */
mt[i] = unsigned32(mt[i] & 0xffffffff);
i++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
}
mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */
}
this.export_state = function() { return [mt, mti]; };
this.import_state = function(s) { mt = s[0]; mti = s[1]; };
this.export_mta = function() { return mt; };
this.import_mta = function(_mta) { mt = _mta };
this.export_mti = function() { return mti; };
this.import_mti = function(_mti) { mti = _mti; }
/* generates a random number on [0,0xffffffff]-interval */
//c//unsigned long genrand_int32(void)
this.genrand_int32 = function ()
{
//c//unsigned long y;
//c//static unsigned long mag01[2]={0x0UL, MATRIX_A};
var y;
var mag01 = new Array(0x0, MATRIX_A);
/* mag01[x] = x * MATRIX_A for x=0,1 */
if (mti >= N) { /* generate N words at one time */
//c//int kk;
var kk;
if (mti == N+1) /* if init_genrand() has not been called, */
//c//init_genrand(5489); /* a default initial seed is used */
this.init_genrand(5489); /* a default initial seed is used */
for (kk=0;kk<N-M;kk++) {
//c//y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
//c//mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
y = unsigned32((mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK));
mt[kk] = unsigned32(mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]);
}
for (;kk<N-1;kk++) {
//c//y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
//c//mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
y = unsigned32((mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK));
mt[kk] = unsigned32(mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]);
}
//c//y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
//c//mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
y = unsigned32((mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK));
mt[N-1] = unsigned32(mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]);
mti = 0;
}
y = mt[mti++];
/* Tempering */
//c//y ^= (y >> 11);
//c//y ^= (y << 7) & 0x9d2c5680;
//c//y ^= (y << 15) & 0xefc60000;
//c//y ^= (y >> 18);
y = unsigned32(y ^ (y >>> 11));
y = unsigned32(y ^ ((y << 7) & 0x9d2c5680));
y = unsigned32(y ^ ((y << 15) & 0xefc60000));
y = unsigned32(y ^ (y >>> 18));
return y;
}
/* generates a random number on [0,0x7fffffff]-interval */
//c//long genrand_int31(void)
this.genrand_int31 = function ()
{
//c//return (genrand_int32()>>1);
return (this.genrand_int32()>>>1);
}
/* generates a random number on [0,1]-real-interval */
//c//double genrand_real1(void)
this.genrand_real1 = function ()
{
//c//return genrand_int32()*(1.0/4294967295.0);
return this.genrand_int32()*(1.0/4294967295.0);
/* divided by 2^32-1 */
}
/* generates a random number on [0,1)-real-interval */
//c//double genrand_real2(void)
this.genrand_real2 = function ()
{
//c//return genrand_int32()*(1.0/4294967296.0);
return this.genrand_int32()*(1.0/4294967296.0);
/* divided by 2^32 */
}
/* generates a random number on (0,1)-real-interval */
//c//double genrand_real3(void)
this.genrand_real3 = function ()
{
//c//return ((genrand_int32()) + 0.5)*(1.0/4294967296.0);
return ((this.genrand_int32()) + 0.5)*(1.0/4294967296.0);
/* divided by 2^32 */
}
/* generates a random number on [0,1) with 53-bit resolution*/
//c//double genrand_res53(void)
this.genrand_res53 = function ()
{
//c//unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
var a=this.genrand_int32()>>>5, b=this.genrand_int32()>>>6;
return(a*67108864.0+b)*(1.0/9007199254740992.0);
}
/* These real versions are due to Isaku Wada, 2002/01/09 added */
}
function initRnd() {
var fuzzMT = new MersenneTwister19937;
var fuzzSeed = 53;
fuzzMT.init_genrand(fuzzSeed);
rnd = function (n) { var v = Math.floor(fuzzMT.genrand_real2() * n); return v; };
rnd.rndReal = function() { return fuzzMT.genrand_real2(); };
rnd.fuzzMT = fuzzMT;
}
```
vs
```js
function randomRecursion() {
var y = "";
if (rnd(2)) {
var x = 2;
"{" + x + "}";
randomRecursion();
randomRecursion();
return ["",];
}
return ["",];
}
function thisFunctionIsNeverCalled() { }
function testOne() {
ox = newGlobal();
var code = randomRecursion()[rnd(3)];
}
initRnd();
gczeal(10, 3);
for (let count = 0;count < 20;count++) {
print(count);
testOne();
}
function MersenneTwister19937() {
var N = 624;
var M = 397;
var MATRIX_A = 0x9908b0df;
var UPPER_MASK = 0x80000000;
var LOWER_MASK = 0x7fffffff;
var mt = new Array(N);
var mti = N + 1;
function unsigned32(n1) {
return n1 < 0 ? n1 ^ UPPER_MASK + UPPER_MASK : n1;
}
function subtraction32(n1, n2) {
return n1 < n2 ? unsigned32(0x100000000 - n2 - n1 & 0xffffffff) : n1 - n2;
}
function addition32(n1, n2) {
return unsigned32(n1 + n2 & 0xffffffff);
}
function multiplication32(n1, n2) {
var sum = 0;
for (let i = 0;i < 32;++i) {
if (n1 >>> i & 0x1) {
sum = addition32(sum, unsigned32(n2 << i));
}
}
return sum;
}
this.init_genrand = function(s) {
mt[0] = unsigned32(s & 0xffffffff);
for (mti = 1;mti < N;mti++) {
mt[mti] = addition32(multiplication32(1812433253, unsigned32(mt[mti - 1] ^ mt[mti - 1] >>> 30)), mti);
mt[mti] = unsigned32(mt[mti] & 0xffffffff);
}
};
this.init_by_array = function(init_key, key_length) {
var i, j, k;
this.init_genrand(19650218);
i = 1;
j = 0;
k = N > key_length ? N : key_length;
for (;k;k--) {
mt[i] = addition32(addition32(unsigned32(mt[i] ^ multiplication32(unsigned32(mt[i - 1] ^ mt[i - 1] >>> 30), 1664525)), init_key[j]), j);
mt[i] = unsigned32(mt[i] & 0xffffffff);
i++;
j++;
if (i >= N) {
mt[0] = mt[N - 1];
i = 1;
}
if (j >= key_length) j = 0;
}
for (k = N - 1;k;k--) {
mt[i] = subtraction32(unsigned32(dbg = mt[i] ^ multiplication32(unsigned32(mt[i - 1] ^ mt[i - 1] >>> 30), 1566083941)), i);
mt[i] = unsigned32(mt[i] & 0xffffffff);
i++;
if (i >= N) {
mt[0] = mt[N - 1];
i = 1;
}
}
mt[0] = 0x80000000;
};
this.export_state = function() {
return [mt, mti,];
};
this.import_state = function(s) {
mt = s[0];
mti = s[1];
};
this.export_mta = function() {
return mt;
};
this.import_mta = function(_mta) {
mt = _mta;
};
this.export_mti = function() {
return mti;
};
this.import_mti = function(_mti) {
mti = _mti;
};
this.genrand_int32 = function() {
var y;
var mag01 = new Array(0x0, MATRIX_A);
if (mti >= N) {
var kk;
if (mti == N + 1) this.init_genrand(5489);
for (kk = 0;kk < N - M;kk++) {
y = unsigned32(mt[kk] & UPPER_MASK | mt[kk + 1] & LOWER_MASK);
mt[kk] = unsigned32(mt[kk + M] ^ y >>> 1 ^ mag01[y & 0x1]);
}
for (;kk < N - 1;kk++) {
y = unsigned32(mt[kk] & UPPER_MASK | mt[kk + 1] & LOWER_MASK);
mt[kk] = unsigned32(mt[kk + M - N] ^ y >>> 1 ^ mag01[y & 0x1]);
}
y = unsigned32(mt[N - 1] & UPPER_MASK | mt[0] & LOWER_MASK);
mt[N - 1] = unsigned32(mt[M - 1] ^ y >>> 1 ^ mag01[y & 0x1]);
mti = 0;
}
y = mt[mti++];
y = unsigned32(y ^ y >>> 11);
y = unsigned32(y ^ y << 7 & 0x9d2c5680);
y = unsigned32(y ^ y << 15 & 0xefc60000);
y = unsigned32(y ^ y >>> 18);
return y;
};
this.genrand_int31 = function() {
return this.genrand_int32() >>> 1;
};
this.genrand_real1 = function() {
return this.genrand_int32() * 1.0 / 4294967295.0;
};
this.genrand_real2 = function() {
return this.genrand_int32() * 1.0 / 4294967296.0;
};
this.genrand_real3 = function() {
return this.genrand_int32() + 0.5 * 1.0 / 4294967296.0;
};
this.genrand_res53 = function() {
var a = this.genrand_int32() >>> 5, b = this.genrand_int32() >>> 6;
return a * 67108864.0 + b * 1.0 / 9007199254740992.0;
};
}
function initRnd() {
var fuzzMT = new MersenneTwister19937();
var fuzzSeed = 53;
fuzzMT.init_genrand(fuzzSeed);
rnd = function(n) {
var v = Math.floor(fuzzMT.genrand_real2() * n);
return v;
};
rnd.rndReal = function() {
return fuzzMT.genrand_real2();
};
rnd.fuzzMT = fuzzMT;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/gc/bug-820186.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-39.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/bug658212.js)
<details>
```js
// |jit-test| test-also-no-wasm-baseline; exitstatus: 3; skip-if: !wasmDebuggingIsSupported()
// Checking in debug frame is initialized properly during stack overflow.
var dbg;
(function () { dbg = new (newGlobal().Debugger)(this); })();
var m = new WebAssembly.Module(wasmTextToBinary(`(module
(import "a" "b" (result f64))
;; function that allocated large space for locals on the stack
(func (export "f") ${Array(200).join("(param f64)")} (result f64) (call 0))
)`));
var f = () => i.exports.f();
var i = new WebAssembly.Instance(m, {a: {b: f}});
f();
```
vs
```js
var dbg;
(function() {
dbg = new newGlobal().Debugger(this);
})();
var m = new WebAssembly.Module(wasmTextToBinary(`(module
(import "a" "b" (result f64))
;; function that allocated large space for locals on the stack
(func (export "f") ${Array(200).join("(param f64)")} (result f64) (call 0))
)`));
var f = () => i.exports.f();
var i = new WebAssembly.Instance(m, ({
a: ({
b: f,
}),
}));
f();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/bug1332493.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/optimized-out-03.js)
<details>
```js
// For perf reasons we don't recompile all a debuggee global's scripts when
// Debugger no longer needs to observe all execution for that global. Test that
// things don't crash if we try to run a script with a BaselineScript that was
// compiled with debug instrumentation when the global is no longer a debuggee.
var g = newGlobal();
var dbg = new Debugger(g);
var counter = 0;
dbg.onDebuggerStatement = function (frame) {
counter++;
if (counter == 15)
dbg.onDebuggerStatement = undefined;
};
g.eval("" + function f() {
{
let inner = 42;
debugger;
inner++;
}
});
g.eval("for (var i = 0; i < 20; i++) f()");
```
vs
```js
var g = newGlobal();
var dbg = new Debugger(g);
var counter = 0;
dbg.onDebuggerStatement = (function(frame) {
counter++;
if (counter == 15) dbg.onDebuggerStatement = undefined;
});
g.eval("" + (function f() {
{
let inner = 42;
debugger;;
inner++;
}}));
g.eval("for (var i = 0; i < 20; i++) f()");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/execution-observability-01.js)
<details>
```js
// Debugger should be notified of scripts created with ExecuteInGlobalAndReturnScope.
var g = newGlobal();
var g2 = newGlobal();
var dbg = new Debugger(g, g2);
var log = '';
var canary = 42;
dbg.onNewScript = function (evalScript) {
log += 'e';
dbg.onNewScript = function (clonedScript) {
log += 'c';
clonedScript.setBreakpoint(0, {
hit(frame) {
log += 'b';
assertEq(frame.script, clonedScript);
}
});
};
};
dbg.onDebuggerStatement = function (frame) {
log += 'd';
};
assertEq(log, '');
var evalScopes = g.evalReturningScope("canary = 'dead'; let lex = 42; debugger; // nee", g2);
assertEq(log, 'ecbd');
assertEq(canary, 42);
assertEq(evalScopes.vars.canary, 'dead');
assertEq(evalScopes.lexicals.lex, 42);
```
vs
```js
var g = newGlobal();
var g2 = newGlobal();
var dbg = new Debugger(g, g2);
var log = '';
var canary = 42;
dbg.onNewScript = (function(evalScript) {
log += 'e';
dbg.onNewScript = function(clonedScript) {
log += 'c';
clonedScript.setBreakpoint(0, {
hit: function(frame) {
log += 'b';
assertEq(frame.script, clonedScript);
},
});
};
});
dbg.onDebuggerStatement = (function(frame) {
log += 'd';
});
assertEq(log, '');
var evalScopes = g.evalReturningScope("canary = 'dead'; let lex = 42; debugger; // nee", g2);
assertEq(log, 'ecbd');
assertEq(canary, 42);
assertEq(evalScopes.vars.canary, 'dead');
assertEq(evalScopes.lexicals.lex, 42);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/onNewScript-ExecuteInGlobalAndReturnScope.js)
<details>
```js
// The argument to Set may contain a value multiple times. Duplicates are discarded.
var s = new Set(["testing", "testing", 123]);
assertEq(s.size, 2);
var values = [undefined, null, false, NaN, 0, -0, 6.022e23, -Infinity, "", "xyzzy", {}, Math.sin];
for (let v of values) {
var a = [v, {}, {}, {}, v, {}, v, v];
s = new Set(a);
assertEq(s.size, 5);
assertEq(s.has(v), true);
}
```
vs
```js
var s = new Set(["testing", "testing", 123,]);
assertEq(s.size, 2);
var values = [undefined, null, false, NaN, 0, -0, 6.022e23, -Infinity, "", "xyzzy", ({}), Math.sin,];
for (v of values) {
var a = [v, { }, { }, { }, v, { }, v, v,];
s = new Set(a);
assertEq(s.size, 5);
assertEq(s.has(v), true);
}
```
<details>
```js
// Two for-of loops on the same array get distinct iterators.
var a = [1, 2, 3];
var s = '';
for (var x of a)
s += x;
for (var y of a)
s += y;
assertEq(s, '123123');
```
vs
```js
var a = [1, 2, 3,];
var s = '';
for (x of a) s += x;
for (y of a) s += y;
assertEq(s, '123123');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/collections/Set-constructor-3.js)
<details>
```js
// Distinct generator calls result in distinct Debugger.Frames.
let g = newGlobal();
g.eval(`
function* count(n) {
if (n > 0) {
for (let x of count(n - 1))
yield x;
yield n;
}
}
`);
let log = "";
let dbg = Debugger(g);
let nextId = 0;
function mark(frame) {
if (frame.id === undefined)
frame.id = nextId++;
}
dbg.onEnterFrame = frame => {
mark(frame);
log += frame.id + "[";
frame.onPop = completion => {
mark(frame);
log += "]" + frame.id;
};
};
let j = 0;
for (let k of g.count(5)) {
assertEq(k, ++j);
log += " ";
}
assertEq(log,
// Calling a generator function just returns a generator object
// without running the body at all; hence "0[]0". However, this call
// does evaluate default argument values, if any, so we do report an
// onEnterFrame / onPop for it.
"0[]0" +
// Demanding the first value from the top generator forces
// SpiderMonkey to create all five generator objects (the empty "n[]n"
// pairs) and then demand a value from them (the longer "n[...]n"
// substrings).
"0[1[]11[2[]22[3[]33[4[]44[5[]55[]5]4]3]2]1]0 " +
"0[1[2[3[4[]4]3]2]1]0 " +
"0[1[2[3[]3]2]1]0 " +
"0[1[2[]2]1]0 " +
"0[1[]1]0 " +
"0[]0");
```
vs
```js
let g = newGlobal();
g.eval(`
function* count(n) {
if (n > 0) {
for (let x of count(n - 1))
yield x;
yield n;
}
}
`);
let log = "";
let dbg = Debugger(g);
let nextId = 0;
function mark(frame) {
if (frame.id === undefined) frame.id = nextId++;
}
dbg.onEnterFrame = frame => {
mark(frame);
log += frame.id + "[";
frame.onPop = completion => {
mark(frame);
log += "]" + frame.id;
};
};
let j = 0;
for (k of g.count(5)) {
assertEq(k, ++j);
log += " ";
}
assertEq(log, "0[]0" + "0[1[]11[2[]22[3[]33[4[]44[5[]55[]5]4]3]2]1]0 " + "0[1[2[3[4[]4]3]2]1]0 " + "0[1[2[3[]3]2]1]0 " + "0[1[2[]2]1]0 " + "0[1[]1]0 " + "0[]0");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-3.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Frame-identity-07.js)
<details>
```js
x = evalcx('');
gcslice(10);
for (var p in x) {}
```
vs
```js
x = evalcx('');
gcslice(10);
for (p in x) {
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/gc/bug-1157577.js)
<details>
```js
function test() {
var f;
function gen() {
f = function(){}
}
for (var i in gen()) {}
arguments[arguments.length - 1];
}
test();
```
vs
```js
function test() {
var f;
function gen() {
f = function() { };
}
for (i in gen()) {
}
arguments[arguments.length - 1];
}
test();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/baseline/bug844467.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/closures/t020.js)
<details>
```js
// |jit-test| error:SyntaxError
// Binary: cache/js-dbg-64-1fd6c40d3852-linux
// Flags: --ion-eager
//
var ary = ["\u001Cfoo", "\u001Dfoo", "\u001Efoo", "\u001Ffoo"];
for (var i in ary) {
ary[Number(i)].search("var MYVAR='077';++MYVAR")
}
```
vs
```js
var ary = ["\u001Cfoo", "\u001Dfoo", "\u001Efoo", "\u001Ffoo",];
for (i in ary) {
ary[Number(i)].search("var MYVAR='077';++MYVAR");
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/auto-regress/bug732852.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-string-tagcloud.js)
<details>
```js
// overflows occurring during constant folding
var y = -null - y;
assertEq(y, NaN);
var x = -(void 0);
assertEq(x, NaN);
function overdiv() {
for(var i=0; i<25; i++) {
var a, b;
function f() {
}
a = f();
b = (123 ^ 1) / 1234;
}
}
overdiv();
function overadd() {
var a = 0x7ffffff0;
var b = 100;
return a + b;
}
overadd();
```
vs
```js
var y = -null - y;
assertEq(y, NaN);
var x = -void 0;
assertEq(x, NaN);
function overdiv() {
for (let i = 0;i < 25;i++) {
var a, b;
function f() { }
a = f();
b = 123 ^ 1 / 1234;
}
}
overdiv();
function overadd() {
var a = 0x7ffffff0;
var b = 100;
return a + b;
}
overadd();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/jaeger/recompile/staticoverflow.js)
<details>
```js
// for-of on an empty slow array does nothing.
var a = [];
a.slow = true;
for (var x of a)
fail();
```
vs
```js
var a = [];
a.slow = true;
for (x of a) fail();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-slow-4.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
setJitCompilerOption("ion.warmup.trigger", 30);
var Vec3u32Type = TypedObject.uint32.array(3);
var PairVec3u32Type = new TypedObject.StructType({fst: Vec3u32Type,
snd: Vec3u32Type});
function foo_u32() {
for (var i = 0; i < 5000; i += 10) {
var p = new PairVec3u32Type();
p.fst[(i) % 3] = i;
p.fst[(i+1) % 3] = i+1;
p.fst[(i+2) % 3] = i+2;
p.snd[(i) % 3] = i+3;
p.snd[(i+1) % 3] = i+4;
p.snd[(i+2) % 3] = i+5;
var sum = p.fst[0] + p.fst[1] + p.fst[2];
assertEq(sum, 3*i + 3);
sum = p.snd[0] + p.snd[1] + p.snd[2];
assertEq(sum, 3*i + 12);
}
}
foo_u32();
```
vs
```js
setJitCompilerOption("ion.warmup.trigger", 30);
var Vec3u32Type = TypedObject.uint32.array(3);
var PairVec3u32Type = new TypedObject.StructType(({
fst: Vec3u32Type,
snd: Vec3u32Type,
}));
function foo_u32() {
for (let i = 0;i < 5000;i += 10) {
var p = new PairVec3u32Type();
p.fst[i % 3] = i;
p.fst[i + 1 % 3] = i + 1;
p.fst[i + 2 % 3] = i + 2;
p.snd[i % 3] = i + 3;
p.snd[i + 1 % 3] = i + 4;
p.snd[i + 2 % 3] = i + 5;
var sum = p.fst[0] + p.fst[1] + p.fst[2];
assertEq(sum, 3 * i + 3);
sum = p.snd[0] + p.snd[1] + p.snd[2];
assertEq(sum, 3 * i + 12);
}
}
foo_u32();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/TypedObject/jit-write-u32-into-u32-array-in-struct.js)
<details>
```js
function f(x) {
return Math.imul(1, x >>> 0) / 9 | 0;
}
function g(x) {
return 1 * (x >>> 0) / 9 | 0;
}
function h(x) {
return (x >>> 0) / 9 | 0;
}
assertEq(0, f(4294967296));
assertEq(-238609294, f(2147483648));
assertEq(0, g(4294967296));
assertEq(238609294, g(2147483648));
assertEq(0, h(4294967296));
assertEq(238609294, h(2147483648));
```
vs
```js
function f(x) {
return Math.imul(1, x >>> 0) / 9 | 0;
}
function g(x) {
return 1 * x >>> 0 / 9 | 0;
}
function h(x) {
return x >>> 0 / 9 | 0;
}
assertEq(0, f(4294967296));
assertEq(-238609294, f(2147483648));
assertEq(0, g(4294967296));
assertEq(238609294, g(2147483648));
assertEq(0, h(4294967296));
assertEq(238609294, h(2147483648));
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/bug1186271.js)
<details>
```js
// Test drainAllocationsLog() and byte sizes.
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root);
root.eval(
`
function AsmModule(stdlib, foreign, heap) {
"use asm";
function test() {
return 5|0;
}
return { test: test };
}
const buf = new ArrayBuffer(1024*8);
function Ctor() {}
this.tests = [
{ name: "new UInt8Array(256)", fn: () => new Uint8Array(256) },
{ name: "arguments", fn: function () { return arguments; } },
{ name: "asm.js module", fn: () => AsmModule(this, {}, buf) },
{ name: "/2manyproblemz/g", fn: () => /2manyproblemz/g },
{ name: "iterator", fn: () => [1,2,3][Symbol.iterator]() },
{ name: "Error()", fn: () => Error() },
{ name: "new Ctor", fn: () => new Ctor },
{ name: "{}", fn: () => ({}) },
{ name: "new Date", fn: () => new Date },
{ name: "[1,2,3]", fn: () => [1,2,3] },
];
`
);
for (let { name, fn } of root.tests) {
print("Test: " + name);
dbg.memory.trackingAllocationSites = true;
fn();
let entries = dbg.memory.drainAllocationsLog();
for (let {size} of entries) {
print(" " + size + " bytes");
// We should get some kind of byte size. We aren't testing that in depth
// here, it is tested pretty thoroughly in
// js/src/jit-test/tests/heap-analysis/byteSize-of-object.js.
assertEq(typeof size, "number");
assertEq(size > 0, true);
}
dbg.memory.trackingAllocationSites = false;
}
```
vs
```js
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root);
root.eval(`
function AsmModule(stdlib, foreign, heap) {
"use asm";
function test() {
return 5|0;
}
return { test: test };
}
const buf = new ArrayBuffer(1024*8);
function Ctor() {}
this.tests = [
{ name: "new UInt8Array(256)", fn: () => new Uint8Array(256) },
{ name: "arguments", fn: function () { return arguments; } },
{ name: "asm.js module", fn: () => AsmModule(this, {}, buf) },
{ name: "/2manyproblemz/g", fn: () => /2manyproblemz/g },
{ name: "iterator", fn: () => [1,2,3][Symbol.iterator]() },
{ name: "Error()", fn: () => Error() },
{ name: "new Ctor", fn: () => new Ctor },
{ name: "{}", fn: () => ({}) },
{ name: "new Date", fn: () => new Date },
{ name: "[1,2,3]", fn: () => [1,2,3] },
];
`);
for ({name, fn,} of root.tests) {
print("Test: " + name);
dbg.memory.trackingAllocationSites = true;
fn();
let entries = dbg.memory.drainAllocationsLog();
for ({size, } of entries) {
print(" " + size + " bytes");
assertEq(typeof size, "number");
assertEq(size > 0, true);
}
dbg.memory.trackingAllocationSites = false;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Memory-drainAllocationsLog-17.js)
<details>
```js
// Inserting values in an array does not change the next index of an existing iterator.
var a = [1, 2, 3, 4];
var s = '';
for (var v of a) {
s += v;
if (s.length === 2)
a.unshift('x');
}
assertEq(s, '12234');
```
vs
```js
var a = [1, 2, 3, 4,];
var s = '';
for (v of a) {
s += v;
if (s.length === 2) a.unshift('x');
}
assertEq(s, '12234');
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/arrays-growing-2.js)
<details>
```js
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
load(libdir + 'array-compare.js');
function strictNestedShadowMaybeEval(code, p)
{
"use strict";
function inner(p) { eval(code); }
return arguments;
}
var a1, a2, a3, a4, a5, a6;
for (var i = 0; i < 5; i++)
{
a1 = strictNestedShadowMaybeEval("1", 2);
a2 = strictNestedShadowMaybeEval("arguments");
a3 = strictNestedShadowMaybeEval("p = 2");
a4 = strictNestedShadowMaybeEval("p = 2", 17);
a5 = strictNestedShadowMaybeEval("arguments[0] = 17");
a6 = strictNestedShadowMaybeEval("arguments[0] = 17", 42);
}
assertEq(arraysEqual(a1, ["1", 2]), true);
assertEq(arraysEqual(a2, ["arguments"]), true);
assertEq(arraysEqual(a3, ["p = 2"]), true);
assertEq(arraysEqual(a4, ["p = 2", 17]), true);
assertEq(arraysEqual(a5, ["arguments[0] = 17"]), true);
assertEq(arraysEqual(a6, ["arguments[0] = 17", 42]), true);
```
vs
```js
load(libdir + 'array-compare.js');
function strictNestedShadowMaybeEval(code, p) {
'use strict';
function inner(p) {
eval(code);
}
return arguments;
}
var a1, a2, a3, a4, a5, a6;
for (let i = 0;i < 5;i++) {
a1 = strictNestedShadowMaybeEval("1", 2);
a2 = strictNestedShadowMaybeEval("arguments");
a3 = strictNestedShadowMaybeEval("p = 2");
a4 = strictNestedShadowMaybeEval("p = 2", 17);
a5 = strictNestedShadowMaybeEval("arguments[0] = 17");
a6 = strictNestedShadowMaybeEval("arguments[0] = 17", 42);
}
assertEq(arraysEqual(a1, ["1", 2,]), true);
assertEq(arraysEqual(a2, ["arguments",]), true);
assertEq(arraysEqual(a3, ["p = 2",]), true);
assertEq(arraysEqual(a4, ["p = 2", 17,]), true);
assertEq(arraysEqual(a5, ["arguments[0] = 17",]), true);
assertEq(arraysEqual(a6, ["arguments[0] = 17", 42,]), true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/arguments/strict-nested-shadow-maybe-eval.js)
<details>
```js
// Deleting the .next method makes for-of stop working on arrays.
load(libdir + "asserts.js");
load(libdir + "iteration.js");
var iterProto = Object.getPrototypeOf([][Symbol.iterator]());
delete iterProto.next;
assertThrowsInstanceOf(function () { for (var v of []) ; }, TypeError);
```
vs
```js
load(libdir + "asserts.js");
load(libdir + "iteration.js");
var iterProto = Object.getPrototypeOf([][Symbol.iterator]());
delete iterProto.next;
assertThrowsInstanceOf((function() {
for (v of []) ;
}), TypeError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/semantics-06.js)
<details>
```js
// The Computer Language Shootout
// http://shootout.alioth.debian.org/
// contributed by Isaac Gouy
function partial(n){
var a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0.0;
var twothirds = 2.0/3.0;
var alt = -1.0;
var k2 = k3 = sk = ck = 0.0;
for (var k = 1; k <= n; k++){
k2 = k*k;
k3 = k2*k;
sk = Math.sin(k);
ck = Math.cos(k);
alt = -alt;
a1 += Math.pow(twothirds,k-1);
a2 += Math.pow(k,-0.5);
a3 += 1.0/(k*(k+1.0));
a4 += 1.0/(k3 * sk*sk);
a5 += 1.0/(k3 * ck*ck);
a6 += 1.0/k;
a7 += 1.0/k2;
a8 += alt/k;
a9 += alt/(2*k -1);
}
return [ a1, a2, a3, a4, a5, a6, a7, a8, a9 ];
}
var actual = [];
for (var i = 1024; i <= 16384; i *= 2)
Array.prototype.push.apply(actual, partial(i));
var eps = 1e-12;
var expect = [2.9999999999999987,62.555269219624684,0.9990243902439033,30.174793391263677,42.99468748637077,7.509175672278132,1.6439579810301654,0.6926591377284127,0.785154022830656,2.9999999999999987,89.06036157695789,0.9995119570522216,30.30796333494624,42.99485339033617,8.202078771817716,1.6444459047881168,0.6929030995395857,0.7852760930922243,2.9999999999999987,126.54745783224483,0.999755918965097,30.314167756318135,42.994888939123,8.89510389696629,1.6446899560231332,0.6930251251486118,0.7853371282421086,2.9999999999999987,179.56450569047874,0.9998779445868421,30.314499725429847,42.99489723774016,9.588190046095265,1.644812003986005,0.693086149128997,0.785367645819433,2.9999999999999987,254.54355172132264,0.9999389685688135,30.31451920492601,42.99489939769195,10.281306710008463,1.6448730335545856,0.6931166639131536,0.7853829046083998];
assertEq(actual.length, expect.length);
for (var i = 0; i < expect.length; ++i)
assertEq(Math.abs(actual[i] - expect[i]) < eps, true);
```
vs
```js
function partial(n) {
var a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0.0;
var twothirds = 2.0 / 3.0;
var alt = -1.0;
var k2 = k3 = sk = ck = 0.0;
for (let k = 1;k <= n;k++) {
k2 = k * k;
k3 = k2 * k;
sk = Math.sin(k);
ck = Math.cos(k);
alt = -alt;
a1 += Math.pow(twothirds, k - 1);
a2 += Math.pow(k, -0.5);
a3 += 1.0 / k * k + 1.0;
a4 += 1.0 / k3 * sk * sk;
a5 += 1.0 / k3 * ck * ck;
a6 += 1.0 / k;
a7 += 1.0 / k2;
a8 += alt / k;
a9 += alt / 2 * k - 1;
}
return [a1, a2, a3, a4, a5, a6, a7, a8, a9,];
}
var actual = [];
for (let i = 1024;i <= 16384;i *= 2) Array.prototype.push.apply(actual, partial(i));
var eps = 1e-12;
var expect = [2.9999999999999987, 62.555269219624684, 0.9990243902439033, 30.174793391263677, 42.99468748637077, 7.509175672278132, 1.6439579810301654, 0.6926591377284127, 0.785154022830656, 2.9999999999999987, 89.06036157695789, 0.9995119570522216, 30.30796333494624, 42.99485339033617, 8.202078771817716, 1.6444459047881168, 0.6929030995395857, 0.7852760930922243, 2.9999999999999987, 126.54745783224483, 0.999755918965097, 30.314167756318135, 42.994888939123, 8.89510389696629, 1.6446899560231332, 0.6930251251486118, 0.7853371282421086, 2.9999999999999987, 179.56450569047874, 0.9998779445868421, 30.314499725429847, 42.99489723774016, 9.588190046095265, 1.644812003986005, 0.693086149128997, 0.785367645819433, 2.9999999999999987, 254.54355172132264, 0.9999389685688135, 30.31451920492601, 42.99489939769195, 10.281306710008463, 1.6448730335545856, 0.6931166639131536, 0.7853829046083998,];
assertEq(actual.length, expect.length);
for (let i = 0;i < expect.length;++i) assertEq(Math.abs(actual[i] - expect[i]) < eps, true);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sunspider/check-math-partial-sums.js)
* [Unexpected Token at line: 11, column: 19: Expected `eof`, or `}`; found Punct(Exponent)](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/recover-autounsafe.js)
<details>
```js
// Binary: cache/js-dbg-64-1fd6c40d3852-linux
// Flags: --ion-eager
//
var cnName = 'name';
var cnNameGetter = function() {this.nameGETS++; return this._name;};
obj = (new (function ( ) { } ) );
obj.__defineGetter__(cnName, cnNameGetter);
function lameFunc(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (obj.name) + (y >> 16) + (lsw >> 16);
}
function runSomeTimes(func, iters) {
for (var i = 0; i < iters; ++i) {
result = func(42, 42);
}
}
for (var i = 0; i < 11000; ++i)
runSomeTimes(lameFunc, 1);
```
vs
```js
var cnName = 'name';
var cnNameGetter = (function() {
this.nameGETS++;
return this._name;
});
obj = new (function() { })();
obj.__defineGetter__(cnName, cnNameGetter);
function lameFunc(x, y) {
var lsw = x & 0xFFFF + y & 0xFFFF;
var msw = obj.name + y >> 16 + lsw >> 16;
}
function runSomeTimes(func, iters) {
for (let i = 0;i < iters;++i) {
result = func(42, 42);
}
}
for (let i = 0;i < 11000;++i) runSomeTimes(lameFunc, 1);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/auto-regress/bug732856.js)
<details>
```js
// for-of is defined in terms of basic operations on objects, particularly
// [[Get]] for properties named "iterator" and "next", and [[Call]]. These
// "semantics" tests check that for-of really does appear to be implemented in
// terms of those more basic operations, as required by the spec, even in
// unusual cases.
// Deleting Array.prototype.iterator makes for-of stop working on arrays.
load(libdir + "asserts.js");
load(libdir + "iteration.js");
delete Array.prototype[Symbol.iterator];
assertThrowsInstanceOf(function () { for (var x of []) ; }, TypeError);
```
vs
```js
load(libdir + "asserts.js");
load(libdir + "iteration.js");
delete Array.prototype[Symbol.iterator];
assertThrowsInstanceOf((function() {
for (x of []) ;
}), TypeError);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/for-of/semantics-01.js)
<details>
```js
// Script.prototype.url can be a string or null.
var g = newGlobal();
var dbg = new Debugger;
var gw = dbg.addDebuggee(g);
for (var fileName of ['file:///var/foo.js', null]) {
g.evaluate("function f(x) { return 2*x; }", {fileName: fileName});
var fw = gw.getOwnPropertyDescriptor('f').value;
assertEq(fw.script.url, fileName);
}
```
vs
```js
var g = newGlobal();
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
for (fileName of ['file:///var/foo.js', null,]) {
g.evaluate("function f(x) { return 2*x; }", {
fileName: fileName,
});
var fw = gw.getOwnPropertyDescriptor('f').value;
assertEq(fw.script.url, fileName);
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Script-url.js)
<details>
```js
// |jit-test| error: TypeError
(function() {
for (let z in [true]) {
(new(eval("for(l in[0,0,0,0]){}"))
(((function f(a, b) {
if (a.length == b) {
return (z)
}
f(a, b + 1)
})([,,], 0)), []))
}
})()
```
vs
```js
(function() {
for (z in [true,]) {
new eval("for(l in[0,0,0,0]){}")(function f(a, b) {
if (a.length == b) {
return z;
}
f(a, b + 1);
}([,,], 0), []);
}
})();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/closures/bug540131-2.js)
<details>
```js
// tests calling script functions via Debugger.Object.prototype.setProperty
// to see if they trigger debugger traps
"use strict";
var global = newGlobal();
var dbg = new Debugger(global);
dbg.onDebuggerStatement = onDebuggerStatement;
let obj;
global.eval(`
const obj = {
set prop(val) {
debugger;
this._prop = val;
}
};
debugger;
`);
function onDebuggerStatement(frame) {
dbg.onDebuggerStatement = onDebuggerStatementGetter;
obj = frame.environment.getVariable("obj");
}
let debuggerRan = false;
assertEq(obj.setProperty("prop", 42).return, true);
assertEq(obj.getProperty("_prop").return, 42);
assertEq(debuggerRan, true);
function onDebuggerStatementGetter(frame) {
debuggerRan = true;
}
```
vs
```js
'use strict';
var global = newGlobal();
var dbg = new Debugger(global);
dbg.onDebuggerStatement = onDebuggerStatement;
let obj;
global.eval(`
const obj = {
set prop(val) {
debugger;
this._prop = val;
}
};
debugger;
`);
function onDebuggerStatement(frame) {
dbg.onDebuggerStatement = onDebuggerStatementGetter;
obj = frame.environment.getVariable("obj");
}
let debuggerRan = false;
assertEq(obj.setProperty("prop", 42).return, true);
assertEq(obj.getProperty("_prop").return, 42);
assertEq(debuggerRan, true);
function onDebuggerStatementGetter(frame) {
debuggerRan = true;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/Object-setProperty-02.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/profiler/bug1242840.js)
<details>
```js
// Run debugger in its own global
let g = newGlobal();
g.target = this;
g.evaluate(`
let d = new Debugger;
let gw = d.addDebuggee(target);
d.onDebuggerStatement = function(frame)
{
frame = frame.older;
let res = frame.eval("this");
assertEq(res.return, frame.this);
res = frame.evalWithBindings("this", {x:42});
assertEq(res.return, frame.this);
}
`);
// Debugger statement affects parse so hide in another function
function brk() { debugger; }
function f1() {
var temp = "string";
brk();
}
function f2() {
let temp = "string";
brk();
}
function f3() {
const temp = "string";
brk();
}
f1.call({});
f2.call({});
f3.call({});
```
vs
```js
let g = newGlobal();
g.target = this;
g.evaluate(`
let d = new Debugger;
let gw = d.addDebuggee(target);
d.onDebuggerStatement = function(frame)
{
frame = frame.older;
let res = frame.eval("this");
assertEq(res.return, frame.this);
res = frame.evalWithBindings("this", {x:42});
assertEq(res.return, frame.this);
}
`);
function brk() {
debugger;;
}
function f1() {
var temp = "string";
brk();
}
function f2() {
let temp = "string";
brk();
}
function f3() {
const temp = "string";
brk();
}
f1.call(({}));
f2.call(({}));
f3.call(({}));
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/bug1397049.js)
<details>
```js
var sandbox = evalcx("lazy");
// Ensure we can't change the "lazy" property of the sandbox to an accessor,
// because that'd allow to execute arbitrary side-effects when calling the
// resolve hook of the sandbox.
var err;
try {
Object.defineProperty(sandbox, "lazy", {
get() {
Object.defineProperty(sandbox, "foo", { value: 0 });
}
});
} catch (e) {
err = e;
}
assertEq(err instanceof TypeError, true);
// Don't assert here.
sandbox.foo = 1;
```
vs
```js
var sandbox = evalcx("lazy");
var err;
try {
Object.defineProperty(sandbox, "lazy", ({
get: (function() {
Object.defineProperty(sandbox, "foo", {
value: 0,
});
}),
}));
} catch (e) {
err = e;
}
assertEq(err instanceof TypeError, true);
sandbox.foo = 1;
```
* [Unexpected Token at line: 16, column: 40: Found unexpected token: =; Not at assignment target](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/backup-point-bug1315634.js)
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/baseline/bug1368626.js)
<details>
```js
// IteratorClose in for-await-of with block-scoped function.
// Non-local-jump without target.
(async function() {
for await (let c of []) {
function f() {};
return;
}
})();
(async function() {
for await (let c of []) {
function f() {};
break;
}
})();
(async function() {
for await (let c of []) {
function f() {};
continue;
}
})();
// Non-local-jump with target.
(async function() {
for (let x of []) {
x: for (let y of []) {
for await (let c of []) {
function f() {};
return;
}
}
}
})();
(async function() {
for (let x of []) {
x: for (let y of []) {
for await (let c of []) {
function f() {};
break x;
}
}
}
})();
(async function() {
for (let x of []) {
x: for (let y of []) {
for await (let c of []) {
function f() {};
continue x;
}
}
}
})();
(async function() {
for await (let x of []) {
x: for await (let y of []) {
for await (let c of []) {
function f() {};
return;
}
}
}
})();
(async function() {
for await (let x of []) {
x: for await (let y of []) {
for await (let c of []) {
function f() {};
break x;
}
}
}
})();
(async function() {
for await (let x of []) {
x: for await (let y of []) {
for await (let c of []) {
function f() {};
continue x;
}
}
}
})();
```
vs
```js
(async function() {
for (c of []) {
function f() { }
;
return;
}
})();
(async function() {
for (c of []) {
function f() { }
;
break;
}
})();
(async function() {
for (c of []) {
function f() { }
;
continue;
}
})();
(async function() {
for (x of []) {
x: for (y of []) {
for (c of []) {
function f() { }
;
return;
}
}
}
})();
(async function() {
for (x of []) {
x: for (y of []) {
for (c of []) {
function f() { }
;
break x;
}
}
}
})();
(async function() {
for (x of []) {
x: for (y of []) {
for (c of []) {
function f() { }
;
continue x;
}
}
}
})();
(async function() {
for (x of []) {
x: for (y of []) {
for (c of []) {
function f() { }
;
return;
}
}
}
})();
(async function() {
for (x of []) {
x: for (y of []) {
for (c of []) {
function f() { }
;
break x;
}
}
}
})();
(async function() {
for (x of []) {
x: for (y of []) {
for (c of []) {
function f() { }
;
continue x;
}
}
}
})();
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/auto-regress/bug1454285.js)
<details>
```js
function* gen() {
try {
yield 3;
} finally {
quit();
}
}
try {
for (var i of gen())
foo();
} catch (e) {}
```
vs
```js
function *gen() {
try {
yield 3;
} finally {
quit();
}
}
try {
for (i of gen()) foo();
} catch (e) {
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/baseline/bug842429.js)
<details>
```js
// For perf reasons we don't recompile all a debuggee global's scripts when
// Debugger no longer needs to observe all execution for that global. Test that
// things don't crash if we try to run a script with a BaselineScript that was
// compiled with debug instrumentation when the global is no longer a debuggee.
var g = newGlobal();
var dbg = new Debugger(g);
var counter = 0;
dbg.onDebuggerStatement = function (frame) {
counter++;
if (counter == 15)
dbg.onDebuggerStatement = undefined;
};
g.eval("" + function f() {
{
let inner = 42;
debugger;
inner++;
}
});
g.eval("for (var i = 0; i < 20; i++) f()");
```
vs
```js
var g = newGlobal();
var dbg = new Debugger(g);
var counter = 0;
dbg.onDebuggerStatement = (function(frame) {
counter++;
if (counter == 15) dbg.onDebuggerStatement = undefined;
});
g.eval("" + (function f() {
{
let inner = 42;
debugger;;
inner++;
}}));
g.eval("for (var i = 0; i < 20; i++) f()");
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/debug/onDebuggerStatement-05.js)
<details>
```js
DoWhile( new DoWhileObject( false, true, true, true ) );
function DoWhileObject( out1, out2, out3, in1 ) {}
function DoWhile( object ) {
if ( object.breakOutOne ) {}
innie:
do {
if ( object.breakOutThree ) {}
} while ( false );
}
```
vs
```js
DoWhile(new DoWhileObject(false, true, true, true));
function DoWhileObject(out1, out2, out3, in1) { }
function DoWhile(object) {
if (object.breakOutOne) {
}
innie: do {
if (object.breakOutThree) {
}
} while (false);
;
}
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/baseline/bug842316.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/parser/bug-1263355-37.js)
<details>
```js
timeout(1);
function f0(p0) {
var v0;
var v1;
var v2;
while (v0) {
do {
if (p0) {
if (v0 ^ p0) {
v1 = v2;
continue;
}
break;
}
} while (p0);
}
}
f0(0);
/* Don't assert */
```
vs
```js
timeout(1);
function f0(p0) {
var v0;
var v1;
var v2;
while (v0) {
do {
if (p0) {
if (v0 ^ p0) {
v1 = v2;
continue;
}
break;
}
} while (p0);
;
}
}
f0(0);
```
* [roundtrip differed](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/ion/bug674656.js)
* [Unable to re-interpret from expression to pattern at line: 18, column: 10](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/sharedbuf/slice-same-memory.js)
* [failed to re-parse](https://hg.mozilla.org/mozilla-central/file/tip/js/src/jit-test/tests/auto-regress/bug1276082.js)
<details>
```js
load(libdir + "asm.js");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i+j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i+j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i-j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i-j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i*j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i*j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0; return (i*j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0; return (i*1048576)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0; return (i*-1048576)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0; return (i + (j*4))|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var two30 = 1073741824; return (((two30 * 524288 * 16) + 1) & 1)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i/j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i/j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=1,j=1; return (i/j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i%j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i%j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i<j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i<j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0; return (i<j)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0.0; return (-i)|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0; return (-(i+j))|0 } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0,k=0; k = (i|0)/(k|0) } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0,k=0; k = (i>>>0)/(k>>>0) } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0,k=0; k = (i|0)%(k|0) } return f");
assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0,k=0; k = (i>>>0)%(k>>>0) } return f");
const UINT32_MAX = Math.pow(2,32)-1;
const INT32_MIN = -Math.pow(2,31);
const INT32_MAX = Math.pow(2,31)-1;
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (i*2)|0 } return f"));
assertEq(f(0), 0);
assertEq(f(INT32_MIN), (2*INT32_MIN)|0);
assertEq(f(INT32_MAX), (2*INT32_MAX)|0);
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (2*i)|0 } return f"));
assertEq(f(0), 0);
assertEq(f(INT32_MIN), (2*INT32_MIN)|0);
assertEq(f(INT32_MAX), (2*INT32_MAX)|0);
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (i*1048575)|0 } return f"));
assertEq(f(0), 0);
assertEq(f(2), (1048575*2)|0);
assertEq(f(-1), (1048575*-1)|0);
assertEq(f(INT32_MIN), (1048575*INT32_MIN)|0);
assertEq(f(INT32_MAX), (1048575*INT32_MAX)|0);
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (1048575*i)|0 } return f"));
assertEq(f(0), 0);
assertEq(f(2), (1048575*2)|0);
assertEq(f(-1), (1048575*-1)|0);
assertEq(f(INT32_MIN), (1048575*INT32_MIN)|0);
assertEq(f(INT32_MAX), (1048575*INT32_MAX)|0);
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=0; j=~i; return j|0 } return f"));
assertEq(f(0), ~0);
assertEq(f(3), ~3);
assertEq(f(-3), ~-3);
assertEq(f(INT32_MAX), ~INT32_MAX);
assertEq(f(INT32_MIN), ~INT32_MIN);
assertEq(f(UINT32_MAX), ~UINT32_MAX);
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=+i; var j=0; j=~~i; return j|0 } return f"));
assertEq(f(0), 0);
assertEq(f(3.5), 3);
assertEq(f(-3.5), -3);
assertEq(f(INT32_MAX), INT32_MAX);
assertEq(f(INT32_MIN), INT32_MIN);
assertEq(f(UINT32_MAX), -1);
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=0.0; j=+~~i; return +j } return f"));
assertEq(f(0), 0);
assertEq(f(INT32_MAX), INT32_MAX);
assertEq(f(INT32_MIN), INT32_MIN);
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=0.1; j=+(i>>>0); return +j } return f"));
assertEq(f(0), 0);
assertEq(f(INT32_MAX), INT32_MAX);
assertEq(f(UINT32_MAX), UINT32_MAX);
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (-i)|0 } return f"));
assertEq(f(0), 0);
assertEq(f(-0), 0);
assertEq(f(1), -1);
assertEq(f(INT32_MAX), INT32_MIN+1);
assertEq(f(INT32_MIN), INT32_MIN);
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=+i; return +(-i) } return f"));
assertEq(f(0), -0);
assertEq(f(-0), 0);
assertEq(f(-1), 1);
assertEq(f(1), -1);
assertEq(f(Math.pow(2,50)), -Math.pow(2,50));
assertEq(f(1.54e20), -1.54e20);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i|0) < (j|0))|0 } return f"));
assertEq(f(0, 1), 1);
assertEq(f(1, 0), 0);
assertEq(f(1, 1), 0);
assertEq(f(INT32_MIN, INT32_MAX), 1);
assertEq(f(INT32_MAX, INT32_MIN), 0);
assertEq(f(0, INT32_MAX), 1);
assertEq(f(INT32_MAX, 0), 0);
assertEq(f(INT32_MIN, 0), 1);
assertEq(f(0, INT32_MIN), 0);
assertEq(f(UINT32_MAX, 0), 1);
assertEq(f(0, UINT32_MAX), 0);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i>>>0) < (j>>>0))|0 } return f"));
assertEq(f(0, 1), 1);
assertEq(f(1, 0), 0);
assertEq(f(1, 1), 0);
assertEq(f(INT32_MIN, INT32_MAX), 0);
assertEq(f(INT32_MAX, INT32_MIN), 1);
assertEq(f(0, INT32_MAX), 1);
assertEq(f(INT32_MAX, 0), 0);
assertEq(f(INT32_MIN, 0), 0);
assertEq(f(0, INT32_MIN), 1);
assertEq(f(UINT32_MAX, 0), 0);
assertEq(f(0, UINT32_MAX), 1);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)==(j|0); return k|0 } return f"));
assertEq(f(1,2), 0);
assertEq(f(1,1), 1);
assertEq(f(2,1), 0);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)!=(j|0); return k|0 } return f"));
assertEq(f(1,2), 1);
assertEq(f(1,1), 0);
assertEq(f(2,1), 1);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)<(j|0); return k|0 } return f"));
assertEq(f(1,2), 1);
assertEq(f(1,1), 0);
assertEq(f(1,0), 0);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)>(j|0); return k|0 } return f"));
assertEq(f(1,2), 0);
assertEq(f(1,1), 0);
assertEq(f(1,0), 1);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)<=(j|0); return k|0 } return f"));
assertEq(f(1,2), 1);
assertEq(f(1,1), 1);
assertEq(f(1,0), 0);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)>=(j|0); return k|0 } return f"));
assertEq(f(1,2), 0);
assertEq(f(1,1), 1);
assertEq(f(1,0), 1);
assertEq(asmLink(asmCompile(USE_ASM + "const I=2; function f(i) { i=i|0; var k=0; k=(i|0)<I; return k|0 } return f"))(1), 1);
assertEq(asmLink(asmCompile(USE_ASM + "const I=2; function f(i) { i=i|0; var k=0; k=(i>>>0)<I; return k|0 } return f"))(1), 1);
assertEq(asmLink(asmCompile(USE_ASM + "const I=-2; function f(i) { i=i|0; var k=0; k=(i|0)<I; return k|0 } return f"))(-1), 0);
assertAsmTypeFail(USE_ASM + "const I=-2; function f(i) { i=i|0; var k=0; k=(i>>>0)<I; return k|0 } return f");
assertAsmTypeFail(USE_ASM + "const I=0x80000000; function f(i) { i=i|0; var k=0; k=(i|0)<I; return k|0 } return f");
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i|0)/(j|0))|0 } return f"));
assertEq(f(4,2), 2);
assertEq(f(3,2), 1);
assertEq(f(3,-2), -1);
assertEq(f(-3,-2), 1);
assertEq(f(0, -1), 0);
assertEq(f(0, INT32_MAX), 0);
assertEq(f(0, INT32_MIN), 0);
assertEq(f(INT32_MAX, 0), 0);
assertEq(f(INT32_MIN, 0), 0);
assertEq(f(-1, INT32_MAX), 0);
assertEq(f(-1, INT32_MIN), 0);
assertEq(f(INT32_MAX, -1), -INT32_MAX);
assertEq(f(INT32_MIN, -1), INT32_MIN); // !!
assertEq(f(INT32_MAX, INT32_MAX), 1);
assertEq(f(INT32_MAX, INT32_MIN), 0);
assertEq(f(INT32_MIN, INT32_MAX), -1);
assertEq(f(INT32_MIN, INT32_MIN), 1);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i>>>0)/(j>>>0))|0 } return f"));
assertEq(f(4,2), 2);
assertEq(f(3,2), 1);
assertEq(f(3,-2), 0);
assertEq(f(-3,-2), 0);
assertEq(f(0, -1), 0);
assertEq(f(0, INT32_MAX), 0);
assertEq(f(0, INT32_MIN), 0);
assertEq(f(0, UINT32_MAX), 0);
assertEq(f(INT32_MAX, 0), 0);
assertEq(f(INT32_MIN, 0), 0);
assertEq(f(UINT32_MAX, 0), 0);
assertEq(f(-1, INT32_MAX), 2);
assertEq(f(-1, INT32_MIN), 1);
assertEq(f(-1, UINT32_MAX), 1);
assertEq(f(INT32_MAX, -1), 0);
assertEq(f(INT32_MIN, -1), 0);
assertEq(f(UINT32_MAX, -1), 1);
assertEq(f(INT32_MAX, INT32_MAX), 1);
assertEq(f(INT32_MAX, INT32_MIN), 0);
assertEq(f(UINT32_MAX, INT32_MAX), 2);
assertEq(f(INT32_MAX, UINT32_MAX), 0);
assertEq(f(UINT32_MAX, UINT32_MAX), 1);
assertEq(f(INT32_MIN, INT32_MAX), 1);
assertEq(f(INT32_MIN, UINT32_MAX), 0);
assertEq(f(INT32_MIN, INT32_MIN), 1);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k = 0; k = (i|0)%(j|0)|0; return k|0 } return f"));
assertEq(f(4,2), 0);
assertEq(f(3,2), 1);
assertEq(f(3,-2), 1);
assertEq(f(-3,-2), -1);
assertEq(f(0, -1), 0);
assertEq(f(0, INT32_MAX), 0);
assertEq(f(0, INT32_MIN), 0);
assertEq(f(INT32_MAX, 0), 0);
assertEq(f(INT32_MIN, 0), 0);
assertEq(f(-1, INT32_MAX), -1);
assertEq(f(-1, INT32_MIN), -1);
assertEq(f(INT32_MAX, -1), 0);
assertEq(f(INT32_MIN, -1), 0); // !!
assertEq(f(INT32_MAX, INT32_MAX), 0);
assertEq(f(INT32_MAX, INT32_MIN), INT32_MAX);
assertEq(f(INT32_MIN, INT32_MAX), -1);
assertEq(f(INT32_MIN, INT32_MIN), 0);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k = 0; k = (i|0)%4|0; return k|0 } return f"));
assertEq(f(0), 0);
assertEq(f(-1), -1);
assertEq(f(-3), -3);
assertEq(f(-4), 0);
assertEq(f(INT32_MIN), 0);
assertEq(f(3), 3);
assertEq(f(4), 0);
assertEq(f(INT32_MAX), 3);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k = 0; k = (i>>>0)%(j>>>0)|0; return k|0 } return f"));
assertEq(f(4,2), 0);
assertEq(f(3,2), 1);
assertEq(f(3,-2), 3);
assertEq(f(-3,-2), -3);
assertEq(f(0, -1), 0);
assertEq(f(0, INT32_MAX), 0);
assertEq(f(0, INT32_MIN), 0);
assertEq(f(0, UINT32_MAX), 0);
assertEq(f(INT32_MAX, 0), 0);
assertEq(f(INT32_MIN, 0), 0);
assertEq(f(UINT32_MAX, 0), 0);
assertEq(f(-1, INT32_MAX), 1);
assertEq(f(-1, INT32_MIN), INT32_MAX);
assertEq(f(-1, UINT32_MAX), 0);
assertEq(f(INT32_MAX, -1), INT32_MAX);
assertEq(f(INT32_MIN, -1), INT32_MIN);
assertEq(f(UINT32_MAX, -1), 0);
assertEq(f(INT32_MAX, INT32_MAX), 0);
assertEq(f(INT32_MAX, INT32_MIN), INT32_MAX);
assertEq(f(UINT32_MAX, INT32_MAX), 1);
assertEq(f(INT32_MAX, UINT32_MAX), INT32_MAX);
assertEq(f(UINT32_MAX, UINT32_MAX), 0);
assertEq(f(INT32_MIN, INT32_MAX), 1);
assertEq(f(INT32_MIN, UINT32_MAX), INT32_MIN);
assertEq(f(INT32_MIN, INT32_MIN), 0);
assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (4 / 2)|0 } return f"))(), 2);
assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (3 / 2)|0 } return f"))(), 1);
assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (4 % 2)|0 } return f"))(), 0);
assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (3 % 2)|0 } return f"))(), 1);
assertAsmTypeFail(USE_ASM + "function f() { var i=42,j=1.1; return +(i?i:j) } return f");
assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 0; 1 ? 1 : 1; return 0; } return f"))(), 0);
assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,j=1.1; return +(i?+(i|0):j) } return f"))(), 42);
assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,j=1; return (i?i:j)|0 } return f"))(), 42);
assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,j=1; return 13; return (i?i:j)|0 } return f"))(), 13);
assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (0 > (-(~~1) >>> 0)) | 0; } return f"))(), 0);
assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 0 < 4294967294 | 0; } return f"))(), 1);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i|0)>(j|0)?(i+10)|0:(j+100)|0)|0 } return f"));
assertEq(f(2, 4), 104);
assertEq(f(-2, -4), 8);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j,k) { i=i|0;j=j|0;k=k|0; return ((i|0)>(j|0) ? (i|0)>(k|0) ? i : k : (j|0)>(k|0) ? j : k)|0 } return f"));
assertEq(f(1,2,3), 3);
assertEq(f(1,3,2), 3);
assertEq(f(2,1,3), 3);
assertEq(f(2,3,1), 3);
assertEq(f(3,1,2), 3);
assertEq(f(3,2,1), 3);
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var a=0,b=0; a=i>>>0 < 4294967292; b=(i|0) < -4; return (j ? a : b)|0 } return f"));
assertEq(f(1,true), 1);
assertEq(f(-1,true), 0);
assertEq(f(-5,true), 1);
assertEq(f(1,false), 0);
assertEq(f(-1,false), 0);
assertEq(f(-5,false), 1);
assertAsmTypeFail('glob','imp','b', USE_ASM + HEAP_IMPORTS + "fu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment