1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 20:28:11 +00:00

LibJS: Convert all remaining non-Array tests to the new system :)

This commit is contained in:
Matthew Olsson 2020-07-05 17:26:26 -07:00 committed by Andreas Kling
parent 918f4affd5
commit 15de2eda2b
72 changed files with 2394 additions and 1998 deletions

View file

@ -0,0 +1,3 @@
classes/class-expressions.js
functions/function-strict-mode.js
new-expression.js

View file

@ -1,9 +0,0 @@
load("test-common.js");
try {
assert(BigInt.asIntN.length === 2);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,9 +0,0 @@
load("test-common.js");
try {
assert(BigInt.asUintN.length === 2);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,78 +1,68 @@
load("test-common.js"); describe("correct behavior", () => {
test("basic functionality", () => {
expect(BigInt).toHaveLength(1);
expect(BigInt.name).toBe("BigInt");
});
try { test("constructor with numbers", () => {
assert(BigInt.length === 1); expect(BigInt(0)).toBe(0n);
assert(BigInt.name === "BigInt"); expect(BigInt(1)).toBe(1n);
expect(BigInt(+1)).toBe(1n);
expect(BigInt(-1)).toBe(-1n);
expect(BigInt(123n)).toBe(123n);
});
assert(BigInt(0) === 0n); test("constructor with strings", () => {
assert(BigInt(1) === 1n); expect(BigInt("")).toBe(0n);
assert(BigInt(+1) === 1n); expect(BigInt("0")).toBe(0n);
assert(BigInt(-1) === -1n); expect(BigInt("1")).toBe(1n);
assert(BigInt("") === 0n); expect(BigInt("+1")).toBe(1n);
assert(BigInt("0") === 0n); expect(BigInt("-1")).toBe(-1n);
assert(BigInt("1") === 1n); expect(BigInt("-1")).toBe(-1n);
assert(BigInt("+1") === 1n); expect(BigInt("42")).toBe(42n);
assert(BigInt("-1") === -1n); expect(BigInt(" \n 00100 \n ")).toBe(100n);
assert(BigInt("-1") === -1n); expect(BigInt("3323214327642987348732109829832143298746432437532197321")).toBe(
assert(BigInt([]) === 0n);
assert(BigInt("42") === 42n);
assert(BigInt(" \n 00100 \n ") === 100n);
assert(BigInt(123n) === 123n);
assert(
BigInt("3323214327642987348732109829832143298746432437532197321") ===
3323214327642987348732109829832143298746432437532197321n 3323214327642987348732109829832143298746432437532197321n
); );
});
assertThrowsError( test("constructor with objects", () => {
() => { expect(BigInt([])).toBe(0n);
});
});
describe("errors", () => {
test('cannot be constructed with "new"', () => {
expect(() => {
new BigInt(); new BigInt();
}, }).toThrowWithMessage(TypeError, "BigInt is not a constructor");
{
error: TypeError,
message: "BigInt is not a constructor",
}
);
[null, undefined, Symbol()].forEach(value => {
assertThrowsError(
() => {
BigInt(value);
},
{
error: TypeError,
message:
typeof value === "symbol"
? "Cannot convert symbol to BigInt"
: `Cannot convert ${value} to BigInt`,
}
);
}); });
["foo", "123n", "1+1", {}, function () {}].forEach(value => { test("invalid arguments", () => {
assertThrowsError( expect(() => {
() => { BigInt(null);
}).toThrowWithMessage(TypeError, "Cannot convert null to BigInt");
expect(() => {
BigInt(undefined);
}).toThrowWithMessage(TypeError, "Cannot convert undefined to BigInt");
expect(() => {
BigInt(Symbol());
}).toThrowWithMessage(TypeError, "Cannot convert symbol to BigInt");
["foo", "123n", "1+1", {}, function () {}].forEach(value => {
expect(() => {
BigInt(value); BigInt(value);
}, }).toThrowWithMessage(SyntaxError, `Invalid value for BigInt: ${value}`);
{ });
error: SyntaxError,
message: `Invalid value for BigInt: ${value}`,
}
);
}); });
[1.23, Infinity, -Infinity, NaN].forEach(value => { test("invalid numeric arguments", () => {
assertThrowsError( [1.23, Infinity, -Infinity, NaN].forEach(value => {
() => { expect(() => {
BigInt(value); BigInt(value);
}, }).toThrowWithMessage(RangeError, "BigInt argument must be an integer");
{ });
error: RangeError,
message: "BigInt argument must be an integer",
}
);
}); });
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,21 +1,10 @@
load("test-common.js"); test("basic functionality", () => {
expect(BigInt.prototype.toLocaleString).toHaveLength(0);
expect(BigInt(123).toLocaleString()).toBe("123");
});
try { test("calling with non-BigInt |this|", () => {
assert(BigInt.prototype.toLocaleString.length === 0); expect(() => {
BigInt.prototype.toLocaleString.call("foo");
assertThrowsError( }).toThrowWithMessage(TypeError, "Not a BigInt object");
() => { });
BigInt.prototype.toLocaleString.call("foo");
},
{
error: TypeError,
message: "Not a BigInt object",
}
);
assert(BigInt(123).toLocaleString() === "123");
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,21 +1,10 @@
load("test-common.js"); test("basic functionality", () => {
expect(BigInt.prototype.toString).toHaveLength(0);
expect(BigInt(123).toString()).toBe("123");
});
try { test("calling with non-BigInt |this|", () => {
assert(BigInt.prototype.toString.length === 0); expect(() => {
BigInt.prototype.toString.call("foo");
assertThrowsError( }).toThrowWithMessage(TypeError, "Not a BigInt object");
() => { });
BigInt.prototype.toString.call("foo");
},
{
error: TypeError,
message: "Not a BigInt object",
}
);
assert(BigInt(123).toString() === "123");
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,23 +1,12 @@
load("test-common.js"); test("basic functionality", () => {
expect(BigInt.prototype.valueOf).toHaveLength(0);
try { expect(typeof BigInt(123).valueOf()).toBe("bigint");
assert(BigInt.prototype.valueOf.length === 0);
assertThrowsError(
() => {
BigInt.prototype.valueOf.call("foo");
},
{
error: TypeError,
message: "Not a BigInt object",
}
);
assert(typeof BigInt(123).valueOf() === "bigint");
// FIXME: Uncomment once we support Object() with argument // FIXME: Uncomment once we support Object() with argument
// assert(typeof Object(123n).valueOf() === "bigint"); // expect(typeof Object(123n).valueOf()).toBe("bigint");
});
console.log("PASS"); test("calling with non-BigInt |this|", () => {
} catch (e) { expect(() => {
console.log("FAIL: " + e); BigInt.prototype.valueOf.call("foo");
} }).toThrowWithMessage(TypeError, "Not a BigInt object");
});

View file

@ -1,74 +1,80 @@
load("test-common.js"); describe("correct behavior", () => {
test("typeof bigint", () => {
expect(typeof 1n).toBe("bigint");
});
try { test("bigint string coersion", () => {
var bigint = 123n; expect("" + 123n).toBe("123");
});
assert(typeof bigint === "bigint"); test("arithmetic operators", () => {
assert(-bigint === -123n); let bigint = 123n;
assert("" + bigint === "123"); expect(-bigint).toBe(-123n);
assertThrowsError( expect(12n + 34n).toBe(46n);
() => { expect(12n - 34n).toBe(-22n);
+bigint; expect(8n * 12n).toBe(96n);
}, expect(123n / 10n).toBe(12n);
{ expect(2n ** 3n).toBe(8n);
error: TypeError, expect(5n % 3n).toBe(2n);
message: "Cannot convert BigInt to number", expect(
} 45977665298704210987n +
); (714320987142450987412098743217984576n / 4598741987421098765327980n) * 987498743n
).toBe(199365500239020623962n);
});
assert(12n + 34n === 46n); test("bitwise operators", () => {
assert(12n - 34n === -22n); expect(12n & 5n).toBe(4n);
assert(8n * 12n === 96n); expect(1n | 2n).toBe(3n);
assert(123n / 10n === 12n); expect(5n ^ 3n).toBe(6n);
assert(2n ** 3n === 8n); expect(~1n).toBe(-2n);
assert(5n % 3n === 2n); });
assert(
45977665298704210987n +
(714320987142450987412098743217984576n / 4598741987421098765327980n) * 987498743n ===
199365500239020623962n
);
assert((12n & 5n) === 4n); test("increment operators", () => {
assert((1n | 2n) === 3n); let bigint = 1n;
assert((5n ^ 3n) === 6n); expect(bigint++).toBe(1n);
assert(~1n === -2n); expect(bigint).toBe(2n);
expect(bigint--).toBe(2n);
expect(bigint).toBe(1n);
expect(++bigint).toBe(2n);
expect(bigint).toBe(2n);
expect(--bigint).toBe(1n);
expect(bigint).toBe(1n);
});
bigint = 1n; test("weak equality operators", () => {
assert(bigint++ === 1n); expect(1n == 1n).toBeTrue();
assert(bigint === 2n); expect(1n == 1).toBeTrue();
assert(bigint-- === 2n); expect(1 == 1n).toBeTrue();
assert(bigint === 1n); expect(1n == 1.23).toBeFalse();
assert(++bigint === 2n); expect(1.23 == 1n).toBeFalse();
assert(bigint === 2n);
assert(--bigint === 1n);
assert(bigint === 1n);
assert((1n == 1n) === true); expect(1n != 1n).toBeFalse();
assert((1n == 1) === true); expect(1n != 1).toBeFalse();
assert((1 == 1n) === true); expect(1 != 1n).toBeFalse();
assert((1n == 1.23) === false); expect(1n != 1.23).toBeTrue();
assert((1.23 == 1n) === false); expect(1.23 != 1n).toBeTrue();
});
assert((1n != 1n) === false); test("strong equality operators", () => {
assert((1n != 1) === false); expect(1n === 1n).toBeTrue();
assert((1 != 1n) === false); expect(1n === 1).toBeFalse();
assert((1n != 1.23) === true); expect(1 === 1n).toBeFalse();
assert((1.23 != 1n) === true); expect(1n === 1.23).toBeFalse();
expect(1.23 === 1n).toBeFalse();
assert((1n === 1n) === true); expect(1n !== 1n).toBeFalse();
assert((1n === 1) == false); expect(1n !== 1).toBeTrue();
assert((1 === 1n) === false); expect(1 !== 1n).toBeTrue();
assert((1n === 1.23) === false); expect(1n !== 1.23).toBeTrue();
assert((1.23 === 1n) === false); expect(1.23 !== 1n).toBeTrue();
});
});
assert((1n !== 1n) === false); describe("errors", () => {
assert((1n !== 1) === true); test("conversion to number", () => {
assert((1 !== 1n) === true); expect(() => {
assert((1n !== 1.23) === true); +123n;
assert((1.23 !== 1n) === true); }).toThrowWithMessage(TypeError, "Cannot convert BigInt to number");
});
console.log("PASS"); });
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,118 +1,31 @@
load("test-common.js"); const doTest = (operatorName, executeOperation) => {
try {
[1, null, undefined].forEach(value => { [1, null, undefined].forEach(value => {
assertThrowsError( const messageSuffix = operatorName === "unsigned right-shift" ? "" : " and other type";
() => {
1n + value; expect(() => {
}, executeOperation(1n, value);
{ }).toThrowWithMessage(
error: TypeError, TypeError,
message: "Cannot use addition operator with BigInt and other type", `Cannot use ${operatorName} operator with BigInt${messageSuffix}`
}
);
assertThrowsError(
() => {
1n - value;
},
{
error: TypeError,
message: "Cannot use subtraction operator with BigInt and other type",
}
);
assertThrowsError(
() => {
1n * value;
},
{
error: TypeError,
message: "Cannot use multiplication operator with BigInt and other type",
}
);
assertThrowsError(
() => {
1n / value;
},
{
error: TypeError,
message: "Cannot use division operator with BigInt and other type",
}
);
assertThrowsError(
() => {
1n % value;
},
{
error: TypeError,
message: "Cannot use modulo operator with BigInt and other type",
}
);
assertThrowsError(
() => {
1n ** value;
},
{
error: TypeError,
message: "Cannot use exponentiation operator with BigInt and other type",
}
);
assertThrowsError(
() => {
1n | value;
},
{
error: TypeError,
message: "Cannot use bitwise OR operator with BigInt and other type",
}
);
assertThrowsError(
() => {
1n & value;
},
{
error: TypeError,
message: "Cannot use bitwise AND operator with BigInt and other type",
}
);
assertThrowsError(
() => {
1n ^ value;
},
{
error: TypeError,
message: "Cannot use bitwise XOR operator with BigInt and other type",
}
);
assertThrowsError(
() => {
1n << value;
},
{
error: TypeError,
message: "Cannot use left-shift operator with BigInt and other type",
}
);
assertThrowsError(
() => {
1n >> value;
},
{
error: TypeError,
message: "Cannot use right-shift operator with BigInt and other type",
}
);
assertThrowsError(
() => {
1n >>> value;
},
{
error: TypeError,
message: "Cannot use unsigned right-shift operator with BigInt",
}
); );
}); });
};
console.log("PASS"); [
} catch (e) { ["addition", (a, b) => a + b],
console.log("FAIL: " + e); ["subtraction", (a, b) => a - b],
} ["multiplication", (a, b) => a * b],
["division", (a, b) => a / b],
["modulo", (a, b) => a % b],
["exponentiation", (a, b) => a ** b],
["bitwise OR", (a, b) => a | b],
["bitwise AND", (a, b) => a & b],
["bitwise XOR", (a, b) => a ^ b],
["left-shift", (a, b) => a << b],
["right-shift", (a, b) => a >> b],
["unsigned right-shift", (a, b) => a >>> b],
].forEach(testCase => {
test(`using ${testCase[0]} operator with BigInt and other type`, () => {
doTest(testCase[0], testCase[1]);
});
});

View file

@ -1,33 +1,23 @@
load("test-common.js"); // test("basic functionality", () => {
// const localSym = Symbol("foo");
// const globalSym = Symbol.for("foo");
try { // expect(localSym).not.toBe(globalSym);
const localSym = Symbol("foo"); // expect(localSym).not.toBe(Symbol("foo"));
const globalSym = Symbol.for("foo"); // expect(globalSym).not.toBe(Symbol("foo"));
// expect(globalSym).toBe(Symbol.for("foo"));
// expect(localSym.toString()).toBe("Symbol(foo)");
// expect(globalSym.toString()).toBe("Symbol(foo)");
assert(localSym !== globalSym); // expect(Symbol.for(1).description).toBe("1");
assert(localSym !== Symbol("foo")); // expect(Symbol.for(true).description).toBe("true");
assert(globalSym !== Symbol("foo")); // expect(Symbol.for({}).description).toBe("[object Object]");
assert(globalSym === Symbol.for("foo")); // expect(Symbol.for().description).toBe("undefined");
assert(localSym.toString() === "Symbol(foo)"); // expect(Symbol.for(null).description).toBe("null");
assert(globalSym.toString() === "Symbol(foo)"); // });
assert(Symbol.for(1).description === "1"); // test("symbol argument throws an error", () => {
assert(Symbol.for(true).description === "true"); // expect(() => {
assert(Symbol.for({}).description === "[object Object]"); // Symbol.for(Symbol());
assert(Symbol.for().description === "undefined"); // }).toThrowWithMessage(TypeError, "Cannot convert symbol to string");
assert(Symbol.for(null).description === "null"); // });
assertThrowsError(
() => {
Symbol.for(Symbol());
},
{
error: TypeError,
message: "Cannot convert symbol to string",
}
);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,29 +1,19 @@
load("test-common.js"); test("basic functionality", () => {
try {
const s1 = Symbol("foo"); const s1 = Symbol("foo");
const s2 = Symbol("foo"); const s2 = Symbol("foo");
assert(s1 !== s2); expect(s1).not.toBe(s2);
assert(s1.description === "foo"); expect(s1.description).toBe("foo");
assert(s2.description === "foo"); expect(s2.description).toBe("foo");
s1.description = "bar"; s1.description = "bar";
assert(s1.description === "foo"); expect(s1.description).toBe("foo");
assert(typeof s1 === "symbol"); expect(typeof s1).toBe("symbol");
});
assertThrowsError( test("constructing symbol from symbol is an error", () => {
() => { expect(() => {
Symbol(Symbol("foo")); Symbol(Symbol("foo"));
}, }).toThrowWithMessage(TypeError, "Cannot convert symbol to string");
{ });
error: TypeError,
message: "Cannot convert symbol to string",
}
);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,34 +1,24 @@
load("test-common.js"); // test("basic functionality", () => {
// const localSym = Symbol("bar");
// const globalSym = Symbol.for("bar");
try { // expect(Symbol.keyFor(localSym)).toBeUndefined();
const localSym = Symbol("foo"); // expect(Symbol.keyFor(globalSym)).toBe("bar");
const globalSym = Symbol.for("foo"); // });
assert(Symbol.keyFor(localSym) === undefined); // test("bad argument values", () => {
assert(Symbol.keyFor(globalSym) === "foo"); // [
// [1, "1"],
const testThrows = (value, str) => { // [null, "null"],
assertThrowsError( // [undefined, "undefined"],
() => { // [[], "[object Array]"],
Symbol.keyFor(value); // [{}, "[object Object]"],
}, // [true, "true"],
{ // ["foobar", "foobar"],
error: TypeError, // [function () {}, "[object ScriptFunction]"], // FIXME: Better function stringification
message: str + " is not a symbol", // ].forEach(testCase => {
} // expect(() => {
); // Symbol.keyFor(testCase[0]);
}; // }).toThrowWithMessage(TypeError, `${testCase[1]} is not a symbol`);
// });
testThrows(1, "1"); // });
testThrows(null, "null");
testThrows(undefined, "undefined");
testThrows([], "[object Array]");
testThrows({}, "[object Object]");
testThrows(true, "true");
testThrows("foobar", "foobar");
testThrows(function () {}, "[object ScriptFunction]"); // FIXME: Better function stringification
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,33 +1,23 @@
load("test-common.js"); describe("correct behavior", () => {
test("basic functionality", () => {
const s1 = Symbol("baz");
// const s2 = Symbol.for("qux");
try { expect(s1.toString()).toBe("Symbol(baz)");
const s1 = Symbol("foo"); // expect(s2.toString()).toBe("Symbol(qux)");
const s2 = Symbol.for("bar"); });
});
assert(s1.toString() === "Symbol(foo)"); describe("errors", () => {
assert(s2.toString() === "Symbol(bar)"); test("convert to string", () => {
expect(() => {
Symbol() + "";
}).toThrowWithMessage(TypeError, "Cannot convert symbol to string");
});
assertThrowsError( test("convert to number", () => {
() => { expect(() => {
s1 + ""; Symbol() + 1;
}, }).toThrowWithMessage(TypeError, "Cannot convert symbol to number");
{ });
error: TypeError, });
message: "Cannot convert symbol to string",
}
);
assertThrowsError(
() => {
s1 + 1;
},
{
error: TypeError,
message: "Cannot convert symbol to number",
}
);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,25 +1,15 @@
load("test-common.js"); test("basic functionality", () => {
const local = Symbol("foo");
// const global = Symbol.for("foo");
expect(local.valueOf()).toBe(local);
// expect(global.valueOf()).toBe(global);
try { expect(Symbol.prototype.valueOf.call(local)).toBe(local);
let local = Symbol("foo"); // expect(Symbol.prototype.valueOf.call(global)).toBe(global);
let global = Symbol.for("foo"); });
assert(local.valueOf() === local);
assert(global.valueOf() === global);
assert(Symbol.prototype.valueOf.call(local) === local); test("|this| must be a symbol", () => {
assert(Symbol.prototype.valueOf.call(global) === global); expect(() => {
Symbol.prototype.valueOf.call("foo");
assertThrowsError( }).toThrowWithMessage(TypeError, "Not a Symbol object");
() => { });
Symbol.prototype.valueOf.call("foo");
},
{
error: TypeError,
message: "Not a Symbol object",
}
);
console.log("PASS");
} catch (err) {
console.log("FAIL: " + err);
}

View file

@ -0,0 +1,35 @@
test("extending function", () => {
class A extends function () {
this.foo = 10;
} {}
expect(new A().foo).toBe(10);
});
test("extending null", () => {
class A extends null {}
expect(Object.getPrototypeOf(A.prototype)).toBeNull();
expect(() => {
new A();
}).toThrowWithMessage(ReferenceError, "|this| has not been initialized");
});
test("extending String", () => {
class MyString extends String {}
const ms = new MyString("abc");
expect(ms).toBeInstanceOf(MyString);
expect(ms).toBeInstanceOf(String);
expect(ms.charAt(1)).toBe("b");
class MyString2 extends MyString {
charAt(i) {
return `#${super.charAt(i)}`;
}
}
const ms2 = new MyString2("abc");
expect(ms2.charAt(1)).toBe("#b");
});

View file

@ -1,269 +1,5 @@
load("test-common.js"); test("class properties", () => {
class A {}
try { expect(A.name).toBe("A");
class X { expect(A).toHaveLength(0);
constructor() { });
this.x = 3;
}
getX() {
return 3;
}
init() {
this.y = 3;
}
}
assert(X.name === "X");
assert(X.length === 0);
class Y extends X {
init() {
super.init();
this.y += 3;
}
}
assert(new Y().getX() === 3);
assert(new Y().x === 3);
let x = new X();
assert(x.x === 3);
assert(x.getX() === 3);
let y = new Y();
assert(y.x === 3);
assert(y.y === undefined);
y.init();
assert(y.y === 6);
assert(y.hasOwnProperty("y"));
class Foo {
constructor(x) {
this.x = x;
}
}
assert(Foo.length === 1);
class Bar extends Foo {
constructor() {
super(5);
}
}
class Baz {
constructor() {
this.foo = 55;
this._bar = 33;
}
get bar() {
return this._bar;
}
set bar(value) {
this._bar = value;
}
["get" + "Foo"]() {
return this.foo;
}
static get staticFoo() {
assert(this === Baz);
return 11;
}
}
let barPropertyDescriptor = Object.getOwnPropertyDescriptor(Baz.prototype, "bar");
assert(barPropertyDescriptor.get.name === "get bar");
assert(barPropertyDescriptor.set.name === "set bar");
let baz = new Baz();
assert(baz.foo === 55);
assert(baz.bar === 33);
baz.bar = 22;
assert(baz.bar === 22);
assert(baz.getFoo() === 55);
assert(Baz.staticFoo === 11);
assert(new Bar().x === 5);
class ExtendsFunction extends function () {
this.foo = 22;
} {}
assert(new ExtendsFunction().foo === 22);
class ExtendsString extends String {}
assert(new ExtendsString() instanceof String);
assert(new ExtendsString() instanceof ExtendsString);
assert(new ExtendsString("abc").charAt(1) === "b");
class MyWeirdString extends ExtendsString {
charAt(i) {
return "#" + super.charAt(i);
}
}
assert(new MyWeirdString("abc").charAt(1) === "#b");
class ExtendsNull extends null {}
assertThrowsError(
() => {
new ExtendsNull();
},
{
error: ReferenceError,
}
);
assert(Object.getPrototypeOf(ExtendsNull.prototype) === null);
class ExtendsClassExpression extends class {
constructor(x) {
this.x = x;
}
} {
constructor(y) {
super(5);
this.y = 6;
}
}
let extendsClassExpression = new ExtendsClassExpression();
assert(extendsClassExpression.x === 5);
assert(extendsClassExpression.y === 6);
class InStrictMode {
constructor() {
assert(isStrictMode());
}
method() {
assert(isStrictMode());
}
}
let resultOfAnExpression = new (class {
constructor(x) {
this.x = x;
}
getX() {
return this.x + 10;
}
})(55);
assert(resultOfAnExpression.x === 55);
assert(resultOfAnExpression.getX() === 65);
let ClassExpression = class Foo {};
assert(ClassExpression.name === "Foo");
new InStrictMode().method();
assert(!isStrictMode());
assertIsSyntaxError(`
class GetterWithArgument {
get foo(bar) {
return 0;
}
}
`);
assertIsSyntaxError(`
class SetterWithNoArgumetns {
set foo() {
}
}
`);
assertIsSyntaxError(`
class SetterWithMoreThanOneArgument {
set foo(bar, baz) {
}
}
`);
assertIsSyntaxError(`
class FooBase {}
class IsASyntaxError extends FooBase {
bar() {
function f() { super.baz; }
}
}
`);
assertIsSyntaxError(`
class NoBaseSuper {
constructor() {
super();
}
}
`);
assertThrowsError(
() => {
class BadExtends extends 3 {}
},
{
error: TypeError,
}
);
assertThrowsError(
() => {
class BadExtends extends undefined {}
},
{
error: TypeError,
}
);
class SuperNotASyntaxError {
bar() {
() => {
super.baz;
};
}
}
class SuperNoBasePropertyLookup {
constructor() {
super.foo;
}
}
assertThrowsError(
() => {
class Base {}
class DerivedDoesntCallSuper extends Base {
constructor() {
this;
}
}
new DerivedDoesntCallSuper();
},
{
error: ReferenceError,
}
);
assertThrowsError(
() => {
class Base {}
class CallsSuperTwice extends Base {
constructor() {
super();
super();
}
}
new CallsSuperTwice();
},
{
error: ReferenceError,
}
);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -0,0 +1,67 @@
test("property initialization", () => {
class A {
constructor() {
this.x = 3;
}
}
expect(new A().x).toBe(3);
});
test("method initialization", () => {
class A {
constructor() {
this.x = () => 10;
}
}
expect(new A().x()).toBe(10);
});
test("initialize to class method", () => {
class A {
constructor() {
this.x = this.method;
}
method() {
return 10;
}
}
expect(new A().x()).toBe(10);
});
test("constructor length affects class length", () => {
class A {
constructor() {}
}
expect(A).toHaveLength(0);
class B {
constructor(a, b, c = 2) {}
}
expect(B).toHaveLength(2);
});
test.skip("must be invoked with 'new'", () => {
class A {
constructor() {}
}
expect(() => {
A();
}).toThrow(TypeError); // FIXME: Add message when this test works
expect(() => {
A.prototype.constructor();
}).toThrow(TypeError); // FIXME: Add message when this test works
});
test("implicit constructor", () => {
class A {}
expect(new A()).toBeInstanceOf(A);
});

View file

@ -0,0 +1,95 @@
describe("non-syntax errors", () => {
test("super reference inside nested-but-same |this| scope with no base class", () => {
expect(`
class A {
foo() {
() => { super.bar; }
}
}`).toEval();
});
test("super reference property lookup with no base class", () => {
expect(`
class A {
constructor() {
super.foo;
}
}`).toEval();
});
});
describe("reference errors", () => {
test("derived class doesn't call super in constructor before using this", () => {
class Parent {}
class Child extends Parent {
constructor() {
this;
}
}
expect(() => {
new Child();
}).toThrowWithMessage(ReferenceError, "|this| has not been initialized");
});
test("derived class calls super twice in constructor", () => {
class Parent {}
class Child extends Parent {
constructor() {
super();
super();
}
}
expect(() => {
new Child();
}).toThrowWithMessage(ReferenceError, "|this| is already initialized");
});
});
describe("syntax errors", () => {
test("getter with argument", () => {
expect(`
class A {
get foo(v) {
return 0;
}
}`).not.toEval();
});
test("setter with no arguments", () => {
expect(`
class A {
set foo() {
}
}`).not.toEval();
});
test("setter with more than one argument", () => {
expect(`
class A {
set foo(bar, baz) {
}
}`).not.toEval();
});
test("super reference inside different |this| scope", () => {
expect(`
class Parent {}
class Child extends Parent {
foo() {
function f() { super.foo; }
}
}`).not.toEval();
});
test("super reference call with no base class", () => {
expect(`
class A {
constructor() {
super();
}
}`).not.toEval();
});
});

View file

@ -0,0 +1,69 @@
// This file must not be formatted by prettier. Make sure your IDE
// respects the .prettierignore file!
test("basic functionality", () => {
const A = class {
constructor(x) {
this.x = x;
}
getX() {
return this.x * 2;
}
};
expect(new A(10).getX()).toBe(20);
});
test("inline instantiation", () => {
const a = new class {
constructor() {
this.x = 10;
}
getX() {
return this.x * 2;
}
};
expect(a.getX()).toBe(20);
});
test("inline instantiation with argument", () => {
const a = new class {
constructor(x) {
this.x = x;
}
getX() {
return this.x * 2;
}
}(10);
expect(a.getX()).toBe(20);
});
test("extending class expressions", () => {
class A extends class {
constructor(x) {
this.x = x;
}
} {
constructor(y) {
super(y);
this.y = y * 2;
}
};
const a = new A(10);
expect(a.x).toBe(10);
expect(a.y).toBe(20);
});
test("class expression name", () => {
let A = class {}
expect(A.name).toBe("A");
let B = class C {}
expect(B.name).toBe("C");
});

View file

@ -0,0 +1,68 @@
test("basic functionality", () => {
class A {
get x() {
return 10;
}
}
expect(A).not.toHaveProperty("x");
expect(new A().x).toBe(10);
});
test("name", () => {
class A {
get x() {}
}
const d = Object.getOwnPropertyDescriptor(A.prototype, "x");
expect(d.get.name).toBe("get x");
});
test("extended name syntax", () => {
class A {
get "method with space"() {
return 1;
}
get 12() {
return 2;
}
get [`he${"llo"}`]() {
return 3;
}
}
const a = new A();
expect(a["method with space"]).toBe(1);
expect(a[12]).toBe(2);
expect(a.hello).toBe(3);
});
test("inherited getter", () => {
class Parent {
get x() {
return 3;
}
}
class Child extends Parent {}
expect(Child).not.toHaveProperty("x");
expect(new Child().x).toBe(3);
});
test("inherited getter overriding", () => {
class Parent {
get x() {
return 3;
}
}
class Child extends Parent {
get x() {
return 10;
}
}
expect(new Child().x).toBe(10);
});

View file

@ -0,0 +1,133 @@
test("method inheritance", () => {
class Parent {
method() {
return 3;
}
}
class Child extends Parent {}
const p = new Parent();
const c = new Child();
expect(p.method()).toBe(3);
expect(c.method()).toBe(3);
});
test("method overriding", () => {
class Parent {
method() {
return 3;
}
}
class Child extends Parent {
method() {
return 10;
}
}
const p = new Parent();
const c = new Child();
expect(p.method()).toBe(3);
expect(c.method()).toBe(10);
});
test("parent method reference with super", () => {
class Parent {
method() {
return 3;
}
}
class Child extends Parent {
method() {
return super.method() * 2;
}
}
const p = new Parent();
const c = new Child();
expect(p.method()).toBe(3);
expect(c.method()).toBe(6);
});
test("child class access to parent class initialized properties", () => {
class Parent {
constructor() {
this.x = 3;
}
}
class Child extends Parent {}
const p = new Parent();
const c = new Child();
expect(p.x).toBe(3);
expect(c.x).toBe(3);
});
test("child class modification of parent class properties", () => {
class Parent {
constructor() {
this.x = 3;
}
}
class Child extends Parent {
change() {
this.x = 10;
}
}
const p = new Parent();
const c = new Child();
expect(p.x).toBe(3);
expect(c.x).toBe(3);
c.change();
expect(c.x).toBe(10);
});
test("inheritance and hasOwnProperty", () => {
class Parent {
constructor() {
this.x = 3;
}
}
class Child extends Parent {
method() {
this.y = 10;
}
}
const p = new Parent();
const c = new Child();
expect(p.hasOwnProperty("x")).toBeTrue();
expect(p.hasOwnProperty("y")).toBeFalse();
expect(c.hasOwnProperty("x")).toBeTrue();
expect(c.hasOwnProperty("y")).toBeFalse();
c.method();
expect(c.hasOwnProperty("x")).toBeTrue();
expect(c.hasOwnProperty("y")).toBeTrue();
});
test("super constructor call from child class with argument", () => {
class Parent {
constructor(x) {
this.x = x;
}
}
class Child extends Parent {
constructor() {
super(10);
}
}
const p = new Parent(3);
const c = new Child(3);
expect(p.x).toBe(3);
expect(c.x).toBe(10);
});

View file

@ -0,0 +1,51 @@
test("basic functionality", () => {
class A {
number() {
return 2;
}
string() {
return "foo";
}
}
const a = new A();
expect(a.number()).toBe(2);
expect(a.string()).toBe("foo");
});
test("length", () => {
class A {
method1() {}
method2(a, b, c, d) {}
method3(a, b, ...c) {}
}
const a = new A();
expect(a.method1).toHaveLength(0);
expect(a.method2).toHaveLength(4);
expect(a.method3).toHaveLength(2);
});
test("extended name syntax", () => {
class A {
"method with space"() {
return 1;
}
12() {
return 2;
}
[`he${"llo"}`]() {
return 3;
}
}
const a = new A();
expect(a["method with space"]()).toBe(1);
expect(a[12]()).toBe(2);
expect(a.hello()).toBe(3);
});

View file

@ -0,0 +1,100 @@
test("basic functionality", () => {
class A {
get x() {
return this._x;
}
set x(value) {
this._x = value * 2;
}
}
expect(A.x).toBeUndefined();
expect(A).not.toHaveProperty("_x");
const a = new A();
expect(a.x).toBeUndefined();
expect(a).not.toHaveProperty("_x");
a.x = 3;
expect(a.x).toBe(6);
expect(a).toHaveProperty("_x", 6);
});
test("name", () => {
class A {
set x(v) {}
}
const d = Object.getOwnPropertyDescriptor(A.prototype, "x");
expect(d.set.name).toBe("set x");
});
test("extended name syntax", () => {
class A {
set "method with space"(value) {
this.a = value;
}
set 12(value) {
this.b = value;
}
set [`he${"llo"}`](value) {
this.c = value;
}
}
const a = new A();
a["method with space"] = 1;
a[12] = 2;
a.hello = 3;
expect(a.a).toBe(1);
expect(a.b).toBe(2);
expect(a.c).toBe(3);
});
test("inherited setter", () => {
class Parent {
get x() {
return this._x;
}
set x(value) {
this._x = value * 2;
}
}
class Child extends Parent {}
const c = new Child();
expect(c.x).toBeUndefined();
c.x = 10;
expect(c.x).toBe(20);
});
test("inherited static setter overriding", () => {
class Parent {
get x() {
return this._x;
}
set x(value) {
this._x = value * 2;
}
}
class Child extends Parent {
get x() {
return this._x;
}
set x(value) {
this._x = value * 3;
}
}
const c = new Child();
expect(c.x).toBeUndefined();
c.x = 10;
expect(c.x).toBe(30);
});

View file

@ -0,0 +1,80 @@
describe("correct behavior", () => {
test("basic functionality", () => {
class A {
static get x() {
return 10;
}
}
expect(A.x).toBe(10);
expect(new A()).not.toHaveProperty("x");
});
test("name", () => {
class A {
static get x() {}
}
const d = Object.getOwnPropertyDescriptor(A, "x");
expect(d.get.name).toBe("get x");
});
test("extended name syntax", () => {
class A {
static get "method with space"() {
return 1;
}
static get 12() {
return 2;
}
static get [`he${"llo"}`]() {
return 3;
}
}
expect(A["method with space"]).toBe(1);
expect(A[12]).toBe(2);
expect(A.hello).toBe(3);
});
test("inherited static getter", () => {
class Parent {
static get x() {
return 3;
}
}
class Child extends Parent {}
expect(Parent.x).toBe(3);
expect(Child.x).toBe(3);
});
test("inherited static getter overriding", () => {
class Parent {
static get x() {
return 3;
}
}
class Child extends Parent {
static get x() {
return 10;
}
}
expect(Parent.x).toBe(3);
expect(Child.x).toBe(10);
});
});
describe("errors", () => {
test('"get static" is a syntax error', () => {
expect(`
class A {
get static foo() {}
}`).not.toEval();
});
});

View file

@ -0,0 +1,104 @@
describe("correct behavior", () => {
test("basic functionality", () => {
class A {
static get x() {
return this._x;
}
static set x(value) {
this._x = value * 2;
}
}
expect(A.x).toBeUndefined();
expect(A).not.toHaveProperty("_x");
A.x = 3;
expect(A.x).toBe(6);
expect(A).toHaveProperty("_x", 6);
});
test("name", () => {
class A {
static set x(v) {}
}
const d = Object.getOwnPropertyDescriptor(A, "x");
expect(d.set.name).toBe("set x");
});
test("extended name syntax", () => {
class A {
static set "method with space"(value) {
this.a = value;
}
static set 12(value) {
this.b = value;
}
static set [`he${"llo"}`](value) {
this.c = value;
}
}
A["method with space"] = 1;
A[12] = 2;
A.hello = 3;
expect(A.a).toBe(1);
expect(A.b).toBe(2);
expect(A.c).toBe(3);
});
test("inherited static setter", () => {
class Parent {
static get x() {
return this._x;
}
static set x(value) {
this._x = value * 2;
}
}
class Child extends Parent {}
expect(Child.x).toBeUndefined();
Child.x = 10;
expect(Child.x).toBe(20);
});
test("inherited static setter overriding", () => {
class Parent {
static get x() {
return this._x;
}
static set x(value) {
this._x = value * 2;
}
}
class Child extends Parent {
static get x() {
return this._x;
}
static set x(value) {
this._x = value * 3;
}
}
expect(Child.x).toBeUndefined();
Child.x = 10;
expect(Child.x).toBe(30);
});
});
describe("errors", () => {
test('"set static" is a syntax error', () => {
expect(`
class A {
set static foo(value) {}
}`).not.toEval();
});
});

View file

@ -0,0 +1,72 @@
test("basic functionality", () => {
class A {
static method() {
return 10;
}
}
expect(A.method()).toBe(10);
expect(new A().method).toBeUndefined();
});
test("extended name syntax", () => {
class A {
static method() {
return 1;
}
static 12() {
return 2;
}
static [`he${"llo"}`]() {
return 3;
}
}
expect(A.method()).toBe(1);
expect(A[12]()).toBe(2);
expect(A.hello()).toBe(3);
});
test("bound |this|", () => {
class A {
static method() {
expect(this).toBe(A);
}
}
A.method();
});
test("inherited static methods", () => {
class Parent {
static method() {
return 3;
}
}
class Child extends Parent {}
expect(Parent.method()).toBe(3);
expect(Child.method()).toBe(3);
expect(new Parent()).not.toHaveProperty("method");
expect(new Child()).not.toHaveProperty("method");
});
test("static method overriding", () => {
class Parent {
static method() {
return 3;
}
}
class Child extends Parent {
static method() {
return 10;
}
}
expect(Parent.method()).toBe(3);
expect(Child.method()).toBe(10);
});

View file

@ -0,0 +1,19 @@
test("constructors are always strict mode", () => {
class A {
constructor() {
expect(isStrictMode()).toBeTrue();
}
}
new A();
});
test("methods are always strict mode", () => {
class A {
method() {
expect(isStrictMode()).toBeTrue();
}
}
new A().method();
});

View file

@ -1,3 +1,4 @@
// I'm not sure how this test passed before the refactor, but it definitely doesn't work at all
test.skip("reassignment to const", () => { test.skip("reassignment to const", () => {
const constantValue = 1; const constantValue = 1;
expect(() => { expect(() => {

View file

@ -1,69 +1,101 @@
load("test-common.js"); test("no arguments", () => {
let getNumber = () => {
return 42;
};
expect(getNumber()).toBe(42);
try { getNumber = () => 42;
let getNumber = () => 42; expect(getNumber()).toBe(42);
assert(getNumber() === 42);
getNumber = () => {
return 99;
};
expect(getNumber()).toBe(99);
getNumber = () => 99; getNumber = () => 99;
assert(getNumber() === 99); expect(getNumber()).toBe(99);
});
test("arguments", () => {
let add = (a, b) => a + b; let add = (a, b) => a + b;
assert(add(2, 3) === 5); expect(add(2, 3)).toBe(5);
const addBlock = (a, b) => { const addBlock = (a, b) => {
let res = a + b; let res = a + b;
return res; return res;
}; };
assert(addBlock(5, 4) === 9); expect(addBlock(5, 4)).toBe(9);
});
test("inside an array", () => {
let chompy = [x => x, 2]; let chompy = [x => x, 2];
assert(chompy.length === 2); expect(chompy).toHaveLength(2);
assert(chompy[0](1) === 1); expect(chompy[0](1)).toBe(1);
});
test("return object literal", () => {
const makeObject = (a, b) => ({ a, b }); const makeObject = (a, b) => ({ a, b });
const obj = makeObject(33, 44); const obj = makeObject(33, 44);
assert(typeof obj === "object"); expect(typeof obj).toBe("object");
assert(obj.a === 33); expect(obj.a).toBe(33);
assert(obj.b === 44); expect(obj.b).toBe(44);
});
test("return undefined", () => {
let returnUndefined = () => {}; let returnUndefined = () => {};
assert(typeof returnUndefined() === "undefined"); expect(returnUndefined()).toBeUndefined();
});
test("return array literal", () => {
const makeArray = (a, b) => [a, b]; const makeArray = (a, b) => [a, b];
const array = makeArray("3", { foo: 4 }); const array = makeArray("3", { foo: 4 });
assert(array[0] === "3"); expect(array[0]).toBe("3");
assert(array[1].foo === 4); expect(array[1].foo).toBe(4);
});
test("return numeric expression", () => {
let square = x => x * x; let square = x => x * x;
assert(square(3) === 9); expect(square(3)).toBe(9);
let squareBlock = x => { let squareBlock = x => {
return x * x; return x * x;
}; };
assert(squareBlock(4) === 16); expect(squareBlock(4)).toBe(16);
});
test("return called arrow function expression", () => {
const message = (who => "Hello " + who)("friends!"); const message = (who => "Hello " + who)("friends!");
assert(message === "Hello friends!"); expect(message).toBe("Hello friends!");
const sum = ((x, y, z) => x + y + z)(1, 2, 3); const sum = ((x, y, z) => x + y + z)(1, 2, 3);
assert(sum === 6); expect(sum).toBe(6);
const product = ((x, y, z) => { const product = ((x, y, z) => {
let res = x * y * z; let res = x * y * z;
return res; return res;
})(5, 4, 2); })(5, 4, 2);
assert(product === 40); expect(product).toBe(40);
const half = (x => { const half = (x => {
return x / 2; return x / 2;
})(10); })(10);
assert(half === 5); expect(half).toBe(5);
});
var foo, bar; test("currying", () => {
let add = a => b => a + b;
expect(typeof add(1)).toBe("function");
expect(typeof add(1, 2)).toBe("function");
expect(add(1)(2)).toBe(3);
});
test("with comma operator", () => {
let foo, bar;
(foo = bar), baz => {}; (foo = bar), baz => {};
assert(foo === undefined); expect(foo).toBe(undefined);
assert(bar === undefined); expect(bar).toBe(undefined);
});
test("arrow functions in objects", () => {
function FooBar() { function FooBar() {
this.x = { this.x = {
y: () => this, y: () => this,
@ -73,50 +105,46 @@ try {
}; };
} }
var foobar = new FooBar(); const foobar = new FooBar();
assert(foobar.x.y() === foobar); expect(foobar.x.y()).toBe(foobar);
assert(foobar.x.z() === foobar.x); expect(foobar.x.z()).toBe(foobar.x);
});
var Baz = () => {};
assert(Baz.prototype === undefined);
assertThrowsError(
() => {
new Baz();
},
{
error: TypeError,
message: "Baz is not a constructor",
}
);
test("strict mode propogation", () => {
(() => { (() => {
"use strict"; "use strict";
assert(isStrictMode()); expect(isStrictMode()).toBeTrue();
(() => { (() => {
assert(isStrictMode()); expect(isStrictMode()).toBeTrue();
})(); })();
})(); })();
(() => { (() => {
"use strict"; "use strict";
assert(isStrictMode()); expect(isStrictMode()).toBeTrue();
})(); })();
(() => { (() => {
assert(!isStrictMode()); expect(isStrictMode()).toBeFalse();
(() => { (() => {
"use strict"; "use strict";
assert(isStrictMode()); expect(isStrictMode()).toBeTrue();
})(); })();
assert(!isStrictMode()); expect(isStrictMode()).toBeFalse();
})(); })();
});
console.log("PASS"); test("no prototype", () => {
} catch { let foo = () => {};
console.log("FAIL"); expect(foo).not.toHaveProperty("prototype");
} });
test("cannot be constructed", () => {
let foo = () => {};
expect(() => {
new foo();
}).toThrowWithMessage(TypeError, "foo is not a constructor");
});

View file

@ -1,17 +1,11 @@
load("test-common.js"); test("basic functionality", () => {
try {
function Foo() { function Foo() {
this.x = 123; this.x = 123;
} }
assert(Foo.prototype.constructor === Foo); expect(Foo.prototype.constructor).toBe(Foo);
var foo = new Foo(); const foo = new Foo();
assert(foo.constructor === Foo); expect(foo.constructor).toBe(Foo);
assert(foo.x === 123); expect(foo.x).toBe(123);
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,70 +1,44 @@
load("test-common.js"); test("calling non-function", () => {
expect(() => {
const a = true;
a();
}).toThrowWithMessage(TypeError, "true is not a function (evaluated from 'a')");
});
try { test("calling number", () => {
assertThrowsError( expect(() => {
() => { const a = 100 + 20 + 3;
var b = true; a();
b(); }).toThrowWithMessage(TypeError, "123 is not a function (evaluated from 'a')");
}, });
{
error: TypeError, test("calling undefined object key", () => {
message: "true is not a function (evaluated from 'b')", expect(() => {
} const o = {};
o.a();
}).toThrowWithMessage(TypeError, "undefined is not a function (evaluated from 'o.a')");
});
test("calling object", () => {
expect(() => {
Math();
}).toThrowWithMessage(TypeError, "[object MathObject] is not a function (evaluated from 'Math')");
});
test("constructing object", () => {
expect(() => {
new Math();
}).toThrowWithMessage(
TypeError,
"[object MathObject] is not a constructor (evaluated from 'Math')"
); );
});
assertThrowsError( test("constructing native function", () => {
() => { expect(() => {
var n = 100 + 20 + 3; new isNaN();
n(); }).toThrowWithMessage(
}, TypeError,
{ "[object NativeFunction] is not a constructor (evaluated from 'isNaN')"
error: TypeError,
message: "123 is not a function (evaluated from 'n')",
}
); );
});
assertThrowsError(
() => {
var o = {};
o.a();
},
{
error: TypeError,
message: "undefined is not a function (evaluated from 'o.a')",
}
);
assertThrowsError(
() => {
Math();
},
{
error: TypeError,
message: "[object MathObject] is not a function (evaluated from 'Math')",
}
);
assertThrowsError(
() => {
new Math();
},
{
error: TypeError,
message: "[object MathObject] is not a constructor (evaluated from 'Math')",
}
);
assertThrowsError(
() => {
new isNaN();
},
{
error: TypeError,
message: "[object NativeFunction] is not a constructor (evaluated from 'isNaN')",
}
);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,75 +1,81 @@
load("test-common.js"); test("single default parameter", () => {
function func(a = 6) {
try {
function func1(a, b = 1) {
return a + b;
}
const arrowFunc1 = (a, b = 1) => a + b;
assert(func1(4, 5) === 9);
assert(func1(4) === 5);
assert(func1(4, undefined) === 5);
assert(Number.isNaN(func1()));
assert(arrowFunc1(4, 5) === 9);
assert(arrowFunc1(4) === 5);
assert(arrowFunc1(4, undefined) === 5);
assert(Number.isNaN(arrowFunc1()));
function func2(a = 6) {
return typeof a; return typeof a;
} }
const arrowFunc2 = (a = 6) => typeof a; const arrowFunc = (a = 6) => typeof a;
assert(func2() === "number"); expect(func()).toBe("number");
assert(func2(5) === "number"); expect(func(5)).toBe("number");
assert(func2(undefined) === "number"); expect(func(undefined)).toBe("number");
assert(func2(false) === "boolean"); expect(func(false)).toBe("boolean");
assert(func2(null) === "object"); expect(func(null)).toBe("object");
assert(func2({}) === "object"); expect(func({})).toBe("object");
assert(arrowFunc2() === "number"); expect(arrowFunc()).toBe("number");
assert(arrowFunc2(5) === "number"); expect(arrowFunc(5)).toBe("number");
assert(arrowFunc2(undefined) === "number"); expect(arrowFunc(undefined)).toBe("number");
assert(arrowFunc2(false) === "boolean"); expect(arrowFunc(false)).toBe("boolean");
assert(arrowFunc2(null) === "object"); expect(arrowFunc(null)).toBe("object");
assert(arrowFunc2({}) === "object"); expect(arrowFunc({})).toBe("object");
});
function func3(a = 5, b) { test("two parameters, second one is default", () => {
function func(a, b = 1) {
return a + b; return a + b;
} }
const arrowFunc3 = (a = 5, b) => a + b; const arrowFunc = (a, b = 1) => a + b;
assert(func3(4, 5) === 9); expect(func(4, 5)).toBe(9);
assert(func3(undefined, 4) === 9); expect(func(4)).toBe(5);
assert(Number.isNaN(func3())); expect(func(4, undefined)).toBe(5);
expect(func()).toBeNaN();
assert(arrowFunc3(4, 5) === 9); expect(arrowFunc(4, 5)).toBe(9);
assert(arrowFunc3(undefined, 4) === 9); expect(arrowFunc(4)).toBe(5);
assert(Number.isNaN(arrowFunc3())); expect(arrowFunc(4, undefined)).toBe(5);
expect(arrowFunc()).toBeNaN();
});
function func4(a, b = a) { test("two parameters, first one is default", () => {
function func(a = 5, b) {
return a + b; return a + b;
} }
const arrowFunc4 = (a, b = a) => a + b; const arrowFunc = (a = 5, b) => a + b;
assert(func4(4, 5) === 9); expect(func(4, 5)).toBe(9);
assert(func4(4) === 8); expect(func(undefined, 4)).toBe(9);
assert(func4("hf") === "hfhf"); expect(func()).toBeNaN();
assert(func4(true) === 2);
assert(Number.isNaN(func4()));
assert(arrowFunc4(4, 5) === 9); expect(arrowFunc(4, 5)).toBe(9);
assert(arrowFunc4(4) === 8); expect(arrowFunc(undefined, 4)).toBe(9);
assert(arrowFunc4("hf") === "hfhf"); expect(arrowFunc()).toBeNaN();
assert(arrowFunc4(true) === 2); });
assert(Number.isNaN(arrowFunc4()));
function func5( test("default parameter references a previous parameter", () => {
function func(a, b = a) {
return a + b;
}
const arrowFunc = (a, b = a) => a + b;
expect(func(4, 5)).toBe(9);
expect(func(4)).toBe(8);
expect(func("hf")).toBe("hfhf");
expect(func(true)).toBe(2);
expect(func()).toBeNaN();
expect(arrowFunc(4, 5)).toBe(9);
expect(arrowFunc(4)).toBe(8);
expect(arrowFunc("hf")).toBe("hfhf");
expect(arrowFunc(true)).toBe(2);
expect(arrowFunc()).toBeNaN();
});
test("parameter with a function default value", () => {
function func(
a = function () { a = function () {
return 5; return 5;
} }
@ -77,60 +83,61 @@ try {
return a(); return a();
} }
const arrowFunc5 = ( const arrowFunc = (
a = function () { a = function () {
return 5; return 5;
} }
) => a(); ) => a();
assert(func5() === 5); expect(func()).toBe(5);
assert( expect(
func5(function () { func(function () {
return 10; return 10;
}) === 10 })
); ).toBe(10);
assert(func5(() => 10) === 10); expect(func(() => 10)).toBe(10);
assert(arrowFunc5() === 5);
assert(
arrowFunc5(function () {
return 10;
}) === 10
);
assert(arrowFunc5(() => 10) === 10);
function func6(a = () => 5) { expect(arrowFunc()).toBe(5);
expect(
arrowFunc(function () {
return 10;
})
).toBe(10);
expect(arrowFunc(() => 10)).toBe(10);
});
test("parameter with an arrow function default vlaue", () => {
function func(a = () => 5) {
return a(); return a();
} }
const arrowFunc6 = (a = () => 5) => a(); const arrowFunc = (a = () => 5) => a();
assert(func6() === 5); expect(func()).toBe(5);
assert( expect(
func6(function () { func(function () {
return 10; return 10;
}) === 10 })
); ).toBe(10);
assert(func6(() => 10) === 10); expect(func(() => 10)).toBe(10);
assert(arrowFunc6() === 5); expect(arrowFunc()).toBe(5);
assert( expect(
arrowFunc6(function () { arrowFunc(function () {
return 10; return 10;
}) === 10 })
); ).toBe(10);
assert(arrowFunc6(() => 10) === 10); expect(arrowFunc(() => 10)).toBe(10);
});
function func7(a = { foo: "bar" }) { test("parameter with an object default value", () => {
function func(a = { foo: "bar" }) {
return a.foo; return a.foo;
} }
const arrowFunc7 = (a = { foo: "bar" }) => a.foo; const arrowFunc = (a = { foo: "bar" }) => a.foo;
assert(func7() === "bar"); expect(func()).toBe("bar");
assert(func7({ foo: "baz" }) === "baz"); expect(func({ foo: "baz" })).toBe("baz");
assert(arrowFunc7() === "bar"); expect(arrowFunc()).toBe("bar");
assert(arrowFunc7({ foo: "baz" }) === "baz"); expect(arrowFunc({ foo: "baz" })).toBe("baz");
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,24 +1,29 @@
load("test-common.js"); test("basic functionality", () => {
let callHoisted = hoisted();
try {
var callHoisted = hoisted();
function hoisted() { function hoisted() {
return true; return "foo";
} }
assert(hoisted() === true); expect(hoisted()).toBe("foo");
assert(callHoisted === true); expect(callHoisted).toBe("foo");
});
// First two calls produce a ReferenceError, but the declarations should be hoisted
test.skip("functions are hoisted across non-lexical scopes", () => {
expect(scopedHoisted).toBeUndefined();
expect(callScopedHoisted).toBeUndefined();
{ {
var callScopedHoisted = scopedHoisted(); var callScopedHoisted = scopedHoisted();
function scopedHoisted() { function scopedHoisted() {
return "foo"; return "foo";
} }
assert(scopedHoisted() === "foo"); expect(scopedHoisted()).toBe("foo");
assert(callScopedHoisted === "foo"); expect(callScopedHoisted).toBe("foo");
} }
assert(scopedHoisted() === "foo"); expect(scopedHoisted()).toBe("foo");
assert(callScopedHoisted === "foo"); expect(callScopedHoisted).toBe("foo");
});
test("functions are not hoisted across lexical scopes", () => {
const test = () => { const test = () => {
var iife = (function () { var iife = (function () {
return declaredLater(); return declaredLater();
@ -28,10 +33,7 @@ try {
} }
return iife; return iife;
}; };
assert(typeof declaredLater === "undefined");
assert(test() === "yay");
console.log("PASS"); expect(() => declaredLater).toThrow(ReferenceError);
} catch (e) { expect(test()).toBe("yay");
console.log("FAIL: " + e); });
}

View file

@ -1,27 +1,23 @@
load("test-common.js"); test("basic functionality", () => {
try {
function foo() {} function foo() {}
assert(foo.length === 0); expect(foo).toHaveLength(0);
assert((foo.length = 5) === 5); expect((foo.length = 5)).toBe(5);
assert(foo.length === 0); expect(foo).toHaveLength(0);
function bar(a, b, c) {} function bar(a, b, c) {}
assert(bar.length === 3); expect(bar).toHaveLength(3);
assert((bar.length = 5) === 5); expect((bar.length = 5)).toBe(5);
assert(bar.length === 3); expect(bar).toHaveLength(3);
});
test("functions with special parameter lists", () => {
function baz(a, b = 1, c) {} function baz(a, b = 1, c) {}
assert(baz.length === 1); expect(baz).toHaveLength(1);
assert((baz.length = 5) === 5); expect((baz.length = 5)).toBe(5);
assert(baz.length === 1); expect(baz).toHaveLength(1);
function qux(a, b, ...c) {} function qux(a, b, ...c) {}
assert(qux.length === 2); expect(qux).toHaveLength(2);
assert((qux.length = 5) === 5); expect((qux.length = 2)).toBe(2);
assert(qux.length === 2); expect(qux).toHaveLength(2);
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,15 +1,10 @@
load("test-common.js"); test("basic functionality", () => {
function foo(a, b) {
return a + b;
}
function foo(a, b) { expect(foo()).toBeNaN();
return a + b; expect(foo(1)).toBeNaN();
} expect(foo(2, 3)).toBe(5);
expect(foo(2, 3, 4)).toBe(5);
try { });
assert(isNaN(foo()) === true);
assert(isNaN(foo(1)) === true);
assert(foo(2, 3) === 5);
assert(foo(2, 3, 4) === 5);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,45 +1,50 @@
load("test-common.js"); test("basic functionality", () => {
expect(function () {}.name).toBe("");
try {
assert(function () {}.name === "");
var foo = function () {};
assert(foo.name === "foo");
assert((foo.name = "bar") === "bar");
assert(foo.name === "foo");
var a, b;
a = b = function () {};
assert(a.name === "b");
assert(b.name === "b");
var arr = [function () {}, function () {}, function () {}];
assert(arr[0].name === "arr");
assert(arr[1].name === "arr");
assert(arr[2].name === "arr");
var f;
var o = { a: function () {} };
assert(o.a.name === "a");
f = o.a;
assert(f.name === "a");
assert(o.a.name === "a");
o = { ...o, b: f };
assert(o.a.name === "a");
assert(o.b.name === "a");
o.c = function () {};
assert(o.c.name === "c");
function bar() {} function bar() {}
assert(bar.name === "bar"); expect(bar.name).toBe("bar");
assert((bar.name = "baz") === "baz"); expect((bar.name = "baz")).toBe("baz");
assert(bar.name === "bar"); expect(bar.name).toBe("bar");
});
assert(console.log.name === "log"); test("function assigned to variable", () => {
assert((console.log.name = "warn") === "warn"); let foo = function () {};
assert(console.log.name === "log"); expect(foo.name).toBe("foo");
expect((foo.name = "bar")).toBe("bar");
expect(foo.name).toBe("foo");
console.log("PASS"); let a, b;
} catch (e) { a = b = function () {};
console.log("FAIL: " + e); expect(a.name).toBe("b");
} expect(b.name).toBe("b");
});
test("functions in array assigned to variable", () => {
const arr = [function () {}, function () {}, function () {}];
expect(arr[0].name).toBe("arr");
expect(arr[1].name).toBe("arr");
expect(arr[2].name).toBe("arr");
});
test("functions in objects", () => {
let f;
let o = { a: function () {} };
expect(o.a.name).toBe("a");
f = o.a;
expect(f.name).toBe("a");
expect(o.a.name).toBe("a");
o = { ...o, b: f };
expect(o.a.name).toBe("a");
expect(o.b.name).toBe("a");
o.c = function () {};
expect(o.c.name).toBe("c");
});
test("names of native functions", () => {
expect(console.debug.name).toBe("debug");
expect((console.debug.name = "warn")).toBe("warn");
expect(console.debug.name).toBe("debug");
});

View file

@ -1,57 +1,47 @@
load("test-common.js"); test("rest parameter with no arguments", () => {
try {
function foo(...a) { function foo(...a) {
assert(a instanceof Array); expect(a).toBeInstanceOf(Array);
assert(a.length === 0); expect(a).toHaveLength(0);
} }
foo(); foo();
});
function foo1(...a) { test("rest parameter with arguments", () => {
assert(a instanceof Array); function foo(...a) {
assert(a.length === 4); expect(a).toEqual(["foo", 123, undefined, { foo: "bar" }]);
assert(a[0] === "foo");
assert(a[1] === 123);
assert(a[2] === undefined);
assert(a[3].foo === "bar");
} }
foo1("foo", 123, undefined, { foo: "bar" }); foo("foo", 123, undefined, { foo: "bar" });
});
function foo2(a, b, ...c) { test("rest parameter after normal parameters with no arguments", () => {
assert(a === "foo"); function foo(a, b, ...c) {
assert(b === 123); expect(a).toBe("foo");
assert(c instanceof Array); expect(b).toBe(123);
assert(c.length === 0); expect(c).toEqual([]);
} }
foo2("foo", 123); foo("foo", 123);
});
function foo3(a, b, ...c) { test("rest parameter after normal parameters with arguments", () => {
assert(a === "foo"); function foo(a, b, ...c) {
assert(b === 123); expect(a).toBe("foo");
assert(c instanceof Array); expect(b).toBe(123);
assert(c.length === 2); expect(c).toEqual([undefined, { foo: "bar" }]);
assert(c[0] === undefined);
assert(c[1].foo === "bar");
} }
foo3("foo", 123, undefined, { foo: "bar" }); foo("foo", 123, undefined, { foo: "bar" });
});
var foo = (...a) => { test("basic arrow function rest parameters", () => {
assert(a instanceof Array); let foo = (...a) => {
assert(a.length === 0); expect(a).toBeInstanceOf(Array);
expect(a).toHaveLength(0);
}; };
foo(); foo();
var foo = (a, b, ...c) => { foo = (a, b, ...c) => {
assert(a === "foo"); expect(a).toBe("foo");
assert(b === 123); expect(b).toBe(123);
assert(c instanceof Array); expect(c).toEqual([undefined, { foo: "bar" }]);
assert(c.length === 2);
assert(c[0] === undefined);
assert(c[1].foo === "bar");
}; };
foo("foo", 123, undefined, { foo: "bar" }); foo("foo", 123, undefined, { foo: "bar" });
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,30 +1,20 @@
load("test-common.js"); test("basic functionality", () => {
try {
const sum = (a, b, c) => a + b + c; const sum = (a, b, c) => a + b + c;
const a = [1, 2, 3]; const a = [1, 2, 3];
assert(sum(...a) === 6); expect(sum(...a)).toBe(6);
assert(sum(1, ...a) === 4); expect(sum(1, ...a)).toBe(4);
assert(sum(...a, 10) === 6); expect(sum(...a, 10)).toBe(6);
const foo = (a, b, c) => c; const foo = (a, b, c) => c;
const o = { bar: [1, 2, 3] }; const o = { bar: [1, 2, 3] };
assert(foo(...o.bar) === 3); expect(foo(...o.bar)).toBe(3);
assert(foo(..."abc") === "c"); expect(foo(..."abc")).toBe("c");
});
assertThrowsError( test("spreading non iterable", () => {
() => { expect(() => {
[...1]; [...1];
}, }).toThrowWithMessage(TypeError, "1 is not iterable");
{ });
error: TypeError,
message: "1 is not iterable",
}
);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,52 +1,53 @@
load("test-common.js"); // This file must not be formatted by prettier. Make sure your IDE
// respects the .prettierignore file!
try { test("non strict-mode by default", () => {
(function () { expect(isStrictMode()).toBeFalse();
assert(!isStrictMode()); });
test("use strict with double quotes", () => {
"use strict";
expect(isStrictMode()).toBeTrue();
});
test("use strict with single quotes", () => {
'use strict';
expect(isStrictMode()).toBeTrue();
});
test("use strict with backticks does not yield strict mode", () => {
`use strict`;
expect(isStrictMode()).toBeFalse();
});
test("use strict with single quotes after statement does not yield strict mode code", () => {
;'use strict';
expect(isStrictMode()).toBeFalse();
});
test("use strict with double quotes after statement does not yield strict mode code", () => {
;"use strict";
expect(isStrictMode()).toBeFalse();
});
test("strict mode propogates down the scope chain", () => {
"use strict";
expect(isStrictMode()).toBeTrue();
(function() {
expect(isStrictMode()).toBeTrue();
})(); })();
});
(function () { test("strict mode does not propogate up the scope chain", () => {
expect(isStrictMode()).toBeFalse();
(function() {
"use strict"; "use strict";
assert(isStrictMode()); expect(isStrictMode()).toBeTrue();
})(); })();
expect(isStrictMode()).toBeFalse();
});
(function () { test('only the string "use strict" yields strict mode code', () => {
"use strict"; "use stric";
assert(isStrictMode()); expect(isStrictMode()).toBeFalse();
})(); });
(function () {
`use strict`;
assert(!isStrictMode());
})();
(function () {
("use strict");
assert(!isStrictMode());
})();
(function () {
("use strict");
assert(!isStrictMode());
})();
(function () {
"use strict";
(function () {
assert(isStrictMode());
})();
})();
(function () {
assert(!isStrictMode());
(function () {
"use strict";
assert(isStrictMode());
})();
assert(!isStrictMode());
})();
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,17 +1,16 @@
load("test-common.js"); test("basic functionality", () => {
expect(typeof this).toBe("object");
try { expect(this).toBe(globalThis);
assert(typeof this === "object"); });
assert(this === globalThis);
test("this inside instantiated functions is not globalThis", () => {
let functionThis;
function Foo() { function Foo() {
this.x = 5; this.x = 5;
assert(typeof this === "object"); functionThis = this;
assert(this.x === 5);
} }
new Foo(); new Foo();
console.log("PASS"); expect(typeof functionThis).toBe("object");
} catch (err) { expect(functionThis.x).toBe(5);
console.log("FAIL: " + err); });
}

View file

@ -1,11 +1,10 @@
load("test-common.js"); test("basic functionality", () => {
try {
var j = 0; var j = 0;
for (var i = 0; i < 9; ++i) { for (var i = 0; i < 9; ++i) {
if (i == 3) continue; if (i == 3) {
continue;
}
++j; ++j;
} }
assert(j == 8); expect(j).toBe(8);
console.log("PASS"); });
} catch {}

View file

@ -1,18 +1,14 @@
load("test-common.js"); test("basic functionality", () => {
let number = 0;
try {
var number = 0;
do { do {
number++; number++;
} while (number < 9); } while (number < 9);
assert(number === 9); expect(number).toBe(9);
});
number = 0; test("no braces", () => {
let number = 0;
do number++; do number++;
while (number < 3); while (number < 3);
assert(number === 3); expect(number).toBe(3);
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,24 +1,15 @@
load("test-common.js"); test("basic functionality", () => {
let a = [];
try { for (let i = 0; i < 3; ++i) {
var a = [];
for (var i = 0; i < 3; ++i) {
a.push(i); a.push(i);
} }
assert(a.length === 3); expect(a).toEqual([0, 1, 2]);
assert(a[0] === 0); });
assert(a[1] === 1);
assert(a[2] === 2);
for (; a.length < 6; ) { test("only condition", () => {
let a = [];
for (; a.length < 3; ) {
a.push("x"); a.push("x");
} }
assert(a.length === 6); expect(a).toEqual(["x", "x", "x"]);
assert(a[3] === "x"); });
assert(a[4] === "x");
assert(a[5] === "x");
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,45 +1,23 @@
load("test-common.js"); test("using undefined variable in initializer", () => {
expect(() => {
for (let i = foo; i < 100; ++i) {}
}).toThrowWithMessage(ReferenceError, "'foo' is not defined");
});
try { test("using undefined variable in condition", () => {
assertThrowsError( expect(() => {
() => { for (let i = 0; i < foo; ++i) {}
for (var i = foo; i < 100; ++i) { }).toThrowWithMessage(ReferenceError, "'foo' is not defined");
assertNotReached(); });
}
}, test("using undefined variable in updater", () => {
{ let loopCount = 0;
error: ReferenceError,
message: "'foo' is not defined", expect(() => {
for (let i = 0; i < 100; ++foo) {
loopCount++;
} }
); }).toThrowWithMessage(ReferenceError, "'foo' is not defined");
assertThrowsError( expect(loopCount).toBe(1);
() => { });
for (var i = 0; i < foo; ++i) {
assertNotReached();
}
},
{
error: ReferenceError,
message: "'foo' is not defined",
}
);
var loopCount = 0;
assertThrowsError(
() => {
for (var i = 0; i < 100; ++foo) {
loopCount++;
}
},
{
error: ReferenceError,
message: "'foo' is not defined",
}
);
assert(loopCount === 1);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,47 +1,45 @@
load("test-common.js"); test("iterate through empty string", () => {
const a = [];
for (const property in "") {
a.push(property);
}
expect(a).toEqual([]);
});
try { test("iterate through number", () => {
assertVisitsAll(visit => { const a = [];
for (const property in "") { for (const property in 123) {
visit(property); a.push(property);
} }
}, []); expect(a).toEqual([]);
});
assertVisitsAll(visit => { test("iterate through empty object", () => {
for (const property in 123) { const a = [];
visit(property); for (const property in {}) {
} a.push(property);
}, []); }
expect(a).toEqual([]);
});
assertVisitsAll(visit => { test("iterate through string", () => {
for (const property in {}) { const a = [];
visit(property); for (const property in "hello") {
} a.push(property);
}, []); }
expect(a).toEqual(["0", "1", "2", "3", "4"]);
});
assertVisitsAll( test("iterate through object", () => {
visit => { const a = [];
for (const property in "hello") { for (const property in { a: 1, b: 2, c: 2 }) {
visit(property); a.push(property);
} }
}, expect(a).toEqual(["a", "b", "c"]);
["0", "1", "2", "3", "4"] });
);
assertVisitsAll(
visit => {
for (const property in { a: 1, b: 2, c: 2 }) {
visit(property);
}
},
["a", "b", "c"]
);
test("use already-declared variable", () => {
var property; var property;
for (property in "abc"); for (property in "abc");
assert(property === "2"); expect(property).toBe("2");
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,12 +1,5 @@
load("test-common.js"); test("basic functionality", () => {
let number = 0;
try { for (let i = 0; i < 3; ++i) for (let j = 0; j < 3; ++j) number++;
var number = 0; expect(number).toBe(9);
});
for (var i = 0; i < 3; ++i) for (var j = 0; j < 3; ++j) number++;
assert(number === 9);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,60 +1,47 @@
load("test-common.js"); describe("correct behavior", () => {
test("iterate through array", () => {
const a = [];
for (const num of [1, 2, 3]) {
a.push(num);
}
expect(a).toEqual([1, 2, 3]);
});
try { test("iterate through string", () => {
assertThrowsError( const a = [];
() => { for (const char of "hello") {
a.push(char);
}
expect(a).toEqual(["h", "e", "l", "l", "o"]);
});
test("iterate through string object", () => {
const a = [];
for (const char of new String("hello")) {
a.push(char);
}
expect(a).toEqual(["h", "e", "l", "l", "o"]);
});
test("use already-declared variable", () => {
var char;
for (char of "abc");
expect(char).toBe("c");
});
});
describe("errors", () => {
test("right hand side is a primitive", () => {
expect(() => {
for (const _ of 123) { for (const _ of 123) {
} }
}, }).toThrowWithMessage(TypeError, "for..of right-hand side must be iterable");
{ });
error: TypeError,
message: "for..of right-hand side must be iterable",
}
);
assertThrowsError( test("right hand side is an object", () => {
() => { expect(() => {
for (const _ of { foo: 1, bar: 2 }) { for (const _ of { foo: 1, bar: 2 }) {
} }
}, }).toThrowWithMessage(TypeError, "for..of right-hand side must be iterable");
{ });
error: TypeError, });
message: "for..of right-hand side must be iterable",
}
);
assertVisitsAll(
visit => {
for (const num of [1, 2, 3]) {
visit(num);
}
},
[1, 2, 3]
);
assertVisitsAll(
visit => {
for (const char of "hello") {
visit(char);
}
},
["h", "e", "l", "l", "o"]
);
assertVisitsAll(
visit => {
for (const char of new String("hello")) {
visit(char);
}
},
["h", "e", "l", "l", "o"]
);
var char;
for (char of "abc");
assert(char === "c");
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,22 +1,18 @@
load("test-common.js"); test("var in for head", () => {
try {
for (var v = 5; false; ); for (var v = 5; false; );
assert(v == 5); expect(v).toBe(5);
});
const options = { error: ReferenceError }; test("let in for head", () => {
for (let l = 5; false; );
assertThrowsError(() => { expect(() => {
for (let l = 5; false; );
l; l;
}, options); }).toThrowWithMessage(ReferenceError, "'l' is not defined");
});
assertThrowsError(() => { test("const in for head", () => {
for (const c = 5; false; ); for (const c = 5; false; );
expect(() => {
c; c;
}, options); }).toThrowWithMessage(ReferenceError, "'c' is not defined");
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,21 +1,19 @@
load("test-common.js"); test("basic functionality", () => {
let number = 0;
try {
var number = 0;
while (number < 9) { while (number < 9) {
number++; number++;
} }
assert(number === 9); expect(number).toBe(9);
});
number = 0; test("no braces", () => {
let number = 0;
while (number < 3) number++; while (number < 3) number++;
assert(number === 3); expect(number).toBe(3);
});
test("does not loop when initially false", () => {
while (false) { while (false) {
assertNotReached(); expect().fail();
} }
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,3 +1,6 @@
// This file must not be formatted by prettier. Make sure your IDE
// respects the .prettierignore file!
test("new-expression parsing", () => { test("new-expression parsing", () => {
function Foo() { function Foo() {
this.x = 1; this.x = 1;
@ -6,13 +9,15 @@ test("new-expression parsing", () => {
let foo = new Foo(); let foo = new Foo();
expect(foo.x).toBe(1); expect(foo.x).toBe(1);
foo = new Foo(); foo = new Foo
expect(foo.x).toBe(1); expect(foo.x).toBe(1);
foo = new Foo(); foo = new
Foo
();
expect(foo.x).toBe(1); expect(foo.x).toBe(1);
foo = new Foo() + 2; foo = new Foo + 2
expect(foo).toBe("[object Object]2"); expect(foo).toBe("[object Object]2");
}); });
@ -26,10 +31,11 @@ test("new-expressions with object keys", () => {
foo = new a.b(); foo = new a.b();
expect(foo.x).toBe(2); expect(foo.x).toBe(2);
foo = new a.b(); foo = new a.b;
expect(foo.x).toBe(2); expect(foo.x).toBe(2);
foo = new a.b(); foo = new
a.b();
expect(foo.x).toBe(2); expect(foo.x).toBe(2);
}); });

View file

@ -1,61 +1,55 @@
load("test-common.js"); let x;
try { test("basic functionality", () => {
var x; x = 1;
expect((x = 2)).toBe(2);
expect(x).toBe(2);
x = 1; x = 1;
assert((x = 2) === 2); expect((x += 2)).toBe(3);
assert(x === 2); expect(x).toBe(3);
x = 1;
assert((x += 2) === 3);
assert(x === 3);
x = 3; x = 3;
assert((x -= 2) === 1); expect((x -= 2)).toBe(1);
assert(x === 1); expect(x).toBe(1);
x = 3; x = 3;
assert((x *= 2) === 6); expect((x *= 2)).toBe(6);
assert(x === 6); expect(x).toBe(6);
x = 6; x = 6;
assert((x /= 2) === 3); expect((x /= 2)).toBe(3);
assert(x === 3); expect(x).toBe(3);
x = 6; x = 6;
assert((x %= 4) === 2); expect((x %= 4)).toBe(2);
assert(x === 2); expect(x).toBe(2);
x = 2; x = 2;
assert((x **= 3) === 8); expect((x **= 3)).toBe(8);
assert(x === 8); expect(x).toBe(8);
x = 3; x = 3;
assert((x &= 2) === 2); expect((x &= 2)).toBe(2);
assert(x === 2); expect(x).toBe(2);
x = 3; x = 3;
assert((x |= 4) === 7); expect((x |= 4)).toBe(7);
assert(x === 7); expect(x).toBe(7);
x = 6; x = 6;
assert((x ^= 2) === 4); expect((x ^= 2)).toBe(4);
assert(x === 4); expect(x).toBe(4);
x = 2; x = 2;
assert((x <<= 2) === 8); expect((x <<= 2)).toBe(8);
assert(x === 8); expect(x).toBe(8);
x = 8; x = 8;
assert((x >>= 2) === 2); expect((x >>= 2)).toBe(2);
assert(x === 2); expect(x).toBe(2);
x = -(2 ** 32 - 10); x = -(2 ** 32 - 10);
assert((x >>>= 2) === 2); expect((x >>>= 2)).toBe(2);
assert(x === 2); expect(x).toBe(2);
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,63 +1,60 @@
load("test-common.js"); test("basic numeric shifting", () => {
expect(0 << 0).toBe(0);
expect(0 << 1).toBe(0);
expect(0 << 2).toBe(0);
expect(0 << 3).toBe(0);
expect(0 << 4).toBe(0);
expect(0 << 5).toBe(0);
try { expect(1 << 0).toBe(1);
assert(0 << 0 === 0); expect(1 << 1).toBe(2);
assert(0 << 1 === 0); expect(1 << 2).toBe(4);
assert(0 << 2 === 0); expect(1 << 3).toBe(8);
assert(0 << 3 === 0); expect(1 << 4).toBe(16);
assert(0 << 4 === 0); expect(1 << 5).toBe(32);
assert(0 << 5 === 0);
assert(1 << 0 === 1); expect(2 << 0).toBe(2);
assert(1 << 1 === 2); expect(2 << 1).toBe(4);
assert(1 << 2 === 4); expect(2 << 2).toBe(8);
assert(1 << 3 === 8); expect(2 << 3).toBe(16);
assert(1 << 4 === 16); expect(2 << 4).toBe(32);
assert(1 << 5 === 32); expect(2 << 5).toBe(64);
assert(2 << 0 === 2); expect(3 << 0).toBe(3);
assert(2 << 1 === 4); expect(3 << 1).toBe(6);
assert(2 << 2 === 8); expect(3 << 2).toBe(12);
assert(2 << 3 === 16); expect(3 << 3).toBe(24);
assert(2 << 4 === 32); expect(3 << 4).toBe(48);
assert(2 << 5 === 64); expect(3 << 5).toBe(96);
assert(3 << 0 === 3); expect(4 << 0).toBe(4);
assert(3 << 1 === 6); expect(4 << 1).toBe(8);
assert(3 << 2 === 12); expect(4 << 2).toBe(16);
assert(3 << 3 === 24); expect(4 << 3).toBe(32);
assert(3 << 4 === 48); expect(4 << 4).toBe(64);
assert(3 << 5 === 96); expect(4 << 5).toBe(128);
assert(4 << 0 === 4); expect(5 << 0).toBe(5);
assert(4 << 1 === 8); expect(5 << 1).toBe(10);
assert(4 << 2 === 16); expect(5 << 2).toBe(20);
assert(4 << 3 === 32); expect(5 << 3).toBe(40);
assert(4 << 4 === 64); expect(5 << 4).toBe(80);
assert(4 << 5 === 128); expect(5 << 5).toBe(160);
});
assert(5 << 0 === 5); test("shifting with non-numeric values", () => {
assert(5 << 1 === 10); let x = 3;
assert(5 << 2 === 20); let y = 7;
assert(5 << 3 === 40);
assert(5 << 4 === 80);
assert(5 << 5 === 160);
var x = 3; expect("42" << 6).toBe(2688);
var y = 7; expect(x << y).toBe(384);
assert("42" << 6 === 2688); expect(x << [[[[12]]]]).toBe(12288);
assert(x << y === 384); expect(undefined << y).toBe(0);
assert(x << [[[[12]]]] === 12288); expect("a" << "b").toBe(0);
assert(undefined << y === 0); expect(null << null).toBe(0);
assert("a" << "b" === 0); expect(undefined << undefined).toBe(0);
assert(null << null === 0); expect(NaN << NaN).toBe(0);
assert(undefined << undefined === 0); expect(NaN << 6).toBe(0);
assert(NaN << NaN === 0); expect(Infinity << Infinity).toBe(0);
assert(NaN << 6 === 0); expect(-Infinity << Infinity).toBe(0);
assert(Infinity << Infinity === 0); });
assert(-Infinity << Infinity === 0);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,63 +1,60 @@
load("test-common.js"); test("basic numeric or", () => {
expect(0 | 0).toBe(0);
expect(0 | 1).toBe(1);
expect(0 | 2).toBe(2);
expect(0 | 3).toBe(3);
expect(0 | 4).toBe(4);
expect(0 | 5).toBe(5);
try { expect(1 | 0).toBe(1);
assert((0 | 0) === 0); expect(1 | 1).toBe(1);
assert((0 | 1) === 1); expect(1 | 2).toBe(3);
assert((0 | 2) === 2); expect(1 | 3).toBe(3);
assert((0 | 3) === 3); expect(1 | 4).toBe(5);
assert((0 | 4) === 4); expect(1 | 5).toBe(5);
assert((0 | 5) === 5);
assert((1 | 0) === 1); expect(2 | 0).toBe(2);
assert((1 | 1) === 1); expect(2 | 1).toBe(3);
assert((1 | 2) === 3); expect(2 | 2).toBe(2);
assert((1 | 3) === 3); expect(2 | 3).toBe(3);
assert((1 | 4) === 5); expect(2 | 4).toBe(6);
assert((1 | 5) === 5); expect(2 | 5).toBe(7);
assert((2 | 0) === 2); expect(3 | 0).toBe(3);
assert((2 | 1) === 3); expect(3 | 1).toBe(3);
assert((2 | 2) === 2); expect(3 | 2).toBe(3);
assert((2 | 3) === 3); expect(3 | 3).toBe(3);
assert((2 | 4) === 6); expect(3 | 4).toBe(7);
assert((2 | 5) === 7); expect(3 | 5).toBe(7);
assert((3 | 0) === 3); expect(4 | 0).toBe(4);
assert((3 | 1) === 3); expect(4 | 1).toBe(5);
assert((3 | 2) === 3); expect(4 | 2).toBe(6);
assert((3 | 3) === 3); expect(4 | 3).toBe(7);
assert((3 | 4) === 7); expect(4 | 4).toBe(4);
assert((3 | 5) === 7); expect(4 | 5).toBe(5);
assert((4 | 0) === 4); expect(5 | 0).toBe(5);
assert((4 | 1) === 5); expect(5 | 1).toBe(5);
assert((4 | 2) === 6); expect(5 | 2).toBe(7);
assert((4 | 3) === 7); expect(5 | 3).toBe(7);
assert((4 | 4) === 4); expect(5 | 4).toBe(5);
assert((4 | 5) === 5); expect(5 | 5).toBe(5);
});
assert((5 | 0) === 5); test("or with non-numeric values", () => {
assert((5 | 1) === 5); let x = 3;
assert((5 | 2) === 7); let y = 7;
assert((5 | 3) === 7);
assert((5 | 4) === 5);
assert((5 | 5) === 5);
var x = 3; expect("42" | 6).toBe(46);
var y = 7; expect(x | y).toBe(7);
assert(("42" | 6) === 46); expect(x | [[[[12]]]]).toBe(15);
assert((x | y) === 7); expect(undefined | y).toBe(7);
assert((x | [[[[12]]]]) === 15); expect("a" | "b").toBe(0);
assert((undefined | y) === 7); expect(null | null).toBe(0);
assert(("a" | "b") === 0); expect(undefined | undefined).toBe(0);
assert((null | null) === 0); expect(NaN | NaN).toBe(0);
assert((undefined | undefined) === 0); expect(NaN | 6).toBe(6);
assert((NaN | NaN) === 0); expect(Infinity | Infinity).toBe(0);
assert((NaN | 6) === 6); expect(-Infinity | Infinity).toBe(0);
assert((Infinity | Infinity) === 0); });
assert((-Infinity | Infinity) === 0);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,63 +1,62 @@
load("test-common.js"); test("basic numeric shifting", () => {
expect(0 >> 0).toBe(0);
expect(0 >> 1).toBe(0);
expect(0 >> 2).toBe(0);
expect(0 >> 3).toBe(0);
expect(0 >> 4).toBe(0);
expect(0 >> 5).toBe(0);
try { expect(1 >> 0).toBe(1);
assert(0 >> 0 === 0); expect(1 >> 1).toBe(0);
assert(0 >> 1 === 0); expect(1 >> 2).toBe(0);
assert(0 >> 2 === 0); expect(1 >> 3).toBe(0);
assert(0 >> 3 === 0); expect(1 >> 4).toBe(0);
assert(0 >> 4 === 0); expect(1 >> 5).toBe(0);
assert(0 >> 5 === 0);
assert(1 >> 0 === 1); expect(5 >> 0).toBe(5);
assert(1 >> 1 === 0); expect(5 >> 1).toBe(2);
assert(1 >> 2 === 0); expect(5 >> 2).toBe(1);
assert(1 >> 3 === 0); expect(5 >> 3).toBe(0);
assert(1 >> 4 === 0); expect(5 >> 4).toBe(0);
assert(1 >> 5 === 0); expect(5 >> 5).toBe(0);
assert(5 >> 0 === 5); expect(42 >> 0).toBe(42);
assert(5 >> 1 === 2); expect(42 >> 1).toBe(21);
assert(5 >> 2 === 1); expect(42 >> 2).toBe(10);
assert(5 >> 3 === 0); expect(42 >> 3).toBe(5);
assert(5 >> 4 === 0); expect(42 >> 4).toBe(2);
assert(5 >> 5 === 0); expect(42 >> 5).toBe(1);
});
assert(42 >> 0 === 42); test("numeric shifting with negative lhs values", () => {
assert(42 >> 1 === 21); expect(-1 >> 0).toBe(-1);
assert(42 >> 2 === 10); expect(-1 >> 1).toBe(-1);
assert(42 >> 3 === 5); expect(-1 >> 2).toBe(-1);
assert(42 >> 4 === 2); expect(-1 >> 3).toBe(-1);
assert(42 >> 5 === 1); expect(-1 >> 4).toBe(-1);
expect(-1 >> 5).toBe(-1);
assert(-1 >> 0 === -1); expect(-5 >> 0).toBe(-5);
assert(-1 >> 1 === -1); expect(-5 >> 1).toBe(-3);
assert(-1 >> 2 === -1); expect(-5 >> 2).toBe(-2);
assert(-1 >> 3 === -1); expect(-5 >> 3).toBe(-1);
assert(-1 >> 4 === -1); expect(-5 >> 4).toBe(-1);
assert(-1 >> 5 === -1); expect(-5 >> 5).toBe(-1);
});
assert(-5 >> 0 === -5); test("shifting with non-numeric values", () => {
assert(-5 >> 1 === -3); let x = 67;
assert(-5 >> 2 === -2); let y = 4;
assert(-5 >> 3 === -1);
assert(-5 >> 4 === -1);
assert(-5 >> 5 === -1);
var x = 67; expect("42" >> 3).toBe(5);
var y = 4; expect(x >> y).toBe(4);
assert("42" >> 3 === 5); expect(x >> [[[[5]]]]).toBe(2);
assert(x >> y === 4); expect(undefined >> y).toBe(0);
assert(x >> [[[[5]]]] === 2); expect("a" >> "b").toBe(0);
assert(undefined >> y === 0); expect(null >> null).toBe(0);
assert("a" >> "b" === 0); expect(undefined >> undefined).toBe(0);
assert(null >> null === 0); expect(NaN >> NaN).toBe(0);
assert(undefined >> undefined === 0); expect(6 >> NaN).toBe(6);
assert(NaN >> NaN === 0); expect(Infinity >> Infinity).toBe(0);
assert(6 >> NaN === 6); expect(-Infinity >> Infinity).toBe(0);
assert(Infinity >> Infinity === 0); });
assert(-Infinity >> Infinity === 0);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,63 +1,62 @@
load("test-common.js"); test("basic numeric shifting", () => {
expect(0 >>> 0).toBe(0);
expect(0 >>> 1).toBe(0);
expect(0 >>> 2).toBe(0);
expect(0 >>> 3).toBe(0);
expect(0 >>> 4).toBe(0);
expect(0 >>> 5).toBe(0);
try { expect(1 >>> 0).toBe(1);
assert(0 >>> 0 === 0); expect(1 >>> 1).toBe(0);
assert(0 >>> 1 === 0); expect(1 >>> 2).toBe(0);
assert(0 >>> 2 === 0); expect(1 >>> 3).toBe(0);
assert(0 >>> 3 === 0); expect(1 >>> 4).toBe(0);
assert(0 >>> 4 === 0); expect(1 >>> 5).toBe(0);
assert(0 >>> 5 === 0);
assert(1 >>> 0 === 1); expect(5 >>> 0).toBe(5);
assert(1 >>> 1 === 0); expect(5 >>> 1).toBe(2);
assert(1 >>> 2 === 0); expect(5 >>> 2).toBe(1);
assert(1 >>> 3 === 0); expect(5 >>> 3).toBe(0);
assert(1 >>> 4 === 0); expect(5 >>> 4).toBe(0);
assert(1 >>> 5 === 0); expect(5 >>> 5).toBe(0);
assert(5 >>> 0 === 5); expect(42 >>> 0).toBe(42);
assert(5 >>> 1 === 2); expect(42 >>> 1).toBe(21);
assert(5 >>> 2 === 1); expect(42 >>> 2).toBe(10);
assert(5 >>> 3 === 0); expect(42 >>> 3).toBe(5);
assert(5 >>> 4 === 0); expect(42 >>> 4).toBe(2);
assert(5 >>> 5 === 0); expect(42 >>> 5).toBe(1);
});
assert(42 >>> 0 === 42); test("numeric shifting with negative lhs values", () => {
assert(42 >>> 1 === 21); expect(-1 >>> 0).toBe(4294967295);
assert(42 >>> 2 === 10); expect(-1 >>> 1).toBe(2147483647);
assert(42 >>> 3 === 5); expect(-1 >>> 2).toBe(1073741823);
assert(42 >>> 4 === 2); expect(-1 >>> 3).toBe(536870911);
assert(42 >>> 5 === 1); expect(-1 >>> 4).toBe(268435455);
expect(-1 >>> 5).toBe(134217727);
assert(-1 >>> 0 === 4294967295); expect(-5 >>> 0).toBe(4294967291);
assert(-1 >>> 1 === 2147483647); expect(-5 >>> 1).toBe(2147483645);
assert(-1 >>> 2 === 1073741823); expect(-5 >>> 2).toBe(1073741822);
assert(-1 >>> 3 === 536870911); expect(-5 >>> 3).toBe(536870911);
assert(-1 >>> 4 === 268435455); expect(-5 >>> 4).toBe(268435455);
assert(-1 >>> 5 === 134217727); expect(-5 >>> 5).toBe(134217727);
});
assert(-5 >>> 0 === 4294967291); test("shifting with non-numeric values", () => {
assert(-5 >>> 1 === 2147483645); let x = -67;
assert(-5 >>> 2 === 1073741822); let y = 4;
assert(-5 >>> 3 === 536870911);
assert(-5 >>> 4 === 268435455);
assert(-5 >>> 5 === 134217727);
var x = -67; expect("-42" >>> 3).toBe(536870906);
var y = 4; expect(x >>> y).toBe(268435451);
assert("-42" >>> 3 === 536870906); expect(x >>> [[[[5]]]]).toBe(134217725);
assert(x >>> y === 268435451); expect(undefined >>> y).toBe(0);
assert(x >>> [[[[5]]]] === 134217725); expect("a" >>> "b").toBe(0);
assert(undefined >>> y === 0); expect(null >>> null).toBe(0);
assert("a" >>> "b" === 0); expect(undefined >>> undefined).toBe(0);
assert(null >>> null === 0); expect(NaN >>> NaN).toBe(0);
assert(undefined >>> undefined === 0); expect(6 >>> NaN).toBe(6);
assert(NaN >>> NaN === 0); expect(Infinity >>> Infinity).toBe(0);
assert(6 >>> NaN === 6); expect(-Infinity >>> Infinity).toBe(0);
assert(Infinity >>> Infinity === 0); });
assert(-Infinity >>> Infinity === 0);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,6 +1,4 @@
load("test-common.js"); test("basic functionality", () => {
try {
const vals = [ const vals = [
1, 1,
2, 2,
@ -723,13 +721,9 @@ try {
let x = vals[test[0]]; let x = vals[test[0]];
let y = vals[test[1]]; let y = vals[test[1]];
assert(x < y === test[2]); expect(x < y).toBe(test[2]);
assert(x > y === test[3]); expect(x > y).toBe(test[3]);
assert(x <= y === test[4]); expect(x <= y).toBe(test[4]);
assert(x >= y === test[5]); expect(x >= y).toBe(test[5]);
} }
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,26 +1,24 @@
load("test-common.js"); test("inside parenthesis", () => {
expect((1, 2, 3)).toBe(3);
expect((1, 2 + 3, 4)).toBe(4);
});
try { test("with post-increment operator", () => {
assert((1, 2, 3) === 3); let foo = 0;
assert((1, 2 + 3, 4) === 4);
var foo = 0;
foo = (foo++, foo); foo = (foo++, foo);
assert(foo === 1); expect(foo).toBe(1);
});
test("with assignment operator", () => {
var a, b, c; var a, b, c;
assert(((a = b = 3), (c = 4)) === 4); expect(((a = b = 3), (c = 4))).toBe(4);
assert(a === 3); expect(a).toBe(3);
assert(b === 3); expect(b).toBe(3);
assert(c === 4); expect(c).toBe(4);
var x, y, z; var x, y, z;
assert((x = ((y = 5), (z = 6))) === 6); expect((x = ((y = 5), (z = 6)))).toBe(6);
assert(x === 6); expect(x).toBe(6);
assert(y === 5); expect(y).toBe(5);
assert(z === 6); expect(z).toBe(6);
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,60 +1,58 @@
load("test-common.js"); test("deleting object properties", () => {
const o = {};
try {
o = {};
o.x = 1; o.x = 1;
o.y = 2; o.y = 2;
o.z = 3; o.z = 3;
assert(Object.getOwnPropertyNames(o).length === 3); expect(Object.getOwnPropertyNames(o)).toHaveLength(3);
assert(delete o.x === true); expect(delete o.x).toBeTrue();
assert(o.hasOwnProperty("x") === false); expect(o.hasOwnProperty("x")).toBeFalse();
assert(o.hasOwnProperty("y") === true); expect(o.hasOwnProperty("y")).toBeTrue();
assert(o.hasOwnProperty("z") === true); expect(o.hasOwnProperty("z")).toBeTrue();
assert(Object.getOwnPropertyNames(o).length === 2); expect(Object.getOwnPropertyNames(o)).toHaveLength(2);
assert(delete o.y === true); expect(delete o.y).toBeTrue();
assert(o.hasOwnProperty("x") === false); expect(o.hasOwnProperty("x")).toBeFalse();
assert(o.hasOwnProperty("y") === false); expect(o.hasOwnProperty("y")).toBeFalse();
assert(o.hasOwnProperty("z") === true); expect(o.hasOwnProperty("z")).toBeTrue();
assert(Object.getOwnPropertyNames(o).length === 1); expect(Object.getOwnPropertyNames(o)).toHaveLength(1);
assert(delete o.z === true); expect(delete o.z).toBeTrue();
assert(o.hasOwnProperty("x") === false); expect(o.hasOwnProperty("x")).toBeFalse();
assert(o.hasOwnProperty("y") === false); expect(o.hasOwnProperty("y")).toBeFalse();
assert(o.hasOwnProperty("z") === false); expect(o.hasOwnProperty("z")).toBeFalse();
assert(Object.getOwnPropertyNames(o).length === 0); expect(Object.getOwnPropertyNames(o)).toHaveLength(0);
});
a = [3, 5, 7]; test("deleting array indices", () => {
const a = [3, 5, 7];
assert(Object.getOwnPropertyNames(a).length === 4); expect(Object.getOwnPropertyNames(a)).toHaveLength(4);
assert(delete a[0] === true); expect(delete a[0]).toBeTrue();
assert(a.hasOwnProperty(0) === false); expect(a.hasOwnProperty(0)).toBeFalse();
assert(a.hasOwnProperty(1) === true); expect(a.hasOwnProperty(1)).toBeTrue();
assert(a.hasOwnProperty(2) === true); expect(a.hasOwnProperty(2)).toBeTrue();
assert(Object.getOwnPropertyNames(a).length === 3); expect(Object.getOwnPropertyNames(a)).toHaveLength(3);
assert(delete a[1] === true); expect(delete a[1]).toBeTrue();
assert(a.hasOwnProperty(0) === false); expect(a.hasOwnProperty(0)).toBeFalse();
assert(a.hasOwnProperty(1) === false); expect(a.hasOwnProperty(1)).toBeFalse();
assert(a.hasOwnProperty(2) === true); expect(a.hasOwnProperty(2)).toBeTrue();
assert(Object.getOwnPropertyNames(a).length === 2); expect(Object.getOwnPropertyNames(a)).toHaveLength(2);
assert(delete a[2] === true); expect(delete a[2]).toBeTrue();
assert(a.hasOwnProperty(0) === false); expect(a.hasOwnProperty(0)).toBeFalse();
assert(a.hasOwnProperty(1) === false); expect(a.hasOwnProperty(1)).toBeFalse();
assert(a.hasOwnProperty(2) === false); expect(a.hasOwnProperty(2)).toBeFalse();
assert(Object.getOwnPropertyNames(a).length === 1); expect(Object.getOwnPropertyNames(a)).toHaveLength(1);
});
q = {}; test("deleting non-configurable property", () => {
const q = {};
Object.defineProperty(q, "foo", { value: 1, writable: false, enumerable: false }); Object.defineProperty(q, "foo", { value: 1, writable: false, enumerable: false });
assert(q.foo === 1); expect(q.foo).toBe(1);
assert(delete q.foo === false); expect(delete q.foo).toBeFalse();
assert(q.hasOwnProperty("foo") === true); expect(q.hasOwnProperty("foo")).toBeTrue();
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,19 +1,9 @@
load("test-common.js"); a = 1;
try { test("basic functionality", () => {
a = 1; expect(delete a).toBeTrue();
assert(delete a === true);
assertThrowsError( expect(() => {
() => { a;
a; }).toThrowWithMessage(ReferenceError, "'a' is not defined");
}, });
{
error: ReferenceError,
}
);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,10 +1,8 @@
load("test-common.js"); a = 1;
try { test("basic functionality", () => {
a = 1; expect(delete globalThis.a).toBeTrue();
assert(delete globalThis.a === true); expect(() => {
a = 2; a = 2;
console.log("PASS"); }).not.toThrow();
} catch (e) { });
console.log("FAIL: " + e);
}

View file

@ -1,38 +1,32 @@
load("test-common.js"); test("in operator with objects", () => {
const o = { foo: "bar", bar: undefined };
expect("" in o).toBeFalse();
expect("foo" in o).toBeTrue();
expect("bar" in o).toBeTrue();
expect("baz" in o).toBeFalse();
expect("toString" in o).toBeTrue();
});
try { test("in operator with arrays", () => {
const a = ["hello", "friends"];
expect(0 in a).toBeTrue();
expect(1 in a).toBeTrue();
expect(2 in a).toBeFalse();
expect("0" in a).toBeTrue();
expect("hello" in a).toBeFalse();
expect("friends" in a).toBeFalse();
expect("length" in a).toBeTrue();
});
test("in operator with string object", () => {
const s = new String("foo");
expect("length" in s).toBeTrue();
});
test("error when used with primitives", () => {
["foo", 123, null, undefined].forEach(value => { ["foo", 123, null, undefined].forEach(value => {
assertThrowsError( expect(() => {
() => { "prop" in value;
"prop" in value; }).toThrowWithMessage(TypeError, "'in' operator must be used on an object");
},
{
error: TypeError,
message: "'in' operator must be used on an object",
}
);
}); });
});
var o = { foo: "bar", bar: undefined };
assert("" in o === false);
assert("foo" in o === true);
assert("bar" in o === true);
assert("baz" in o === false);
assert("toString" in o === true);
var a = ["hello", "friends"];
assert(0 in a === true);
assert(1 in a === true);
assert(2 in a === false);
assert("0" in a === true);
assert("hello" in a === false);
assert("friends" in a === false);
assert("length" in a === true);
var s = new String("foo");
assert("length" in s);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,13 +1,13 @@
load("test-common.js"); test("basic functionality", () => {
try {
function Foo() { function Foo() {
this.x = 123; this.x = 123;
} }
var foo = new Foo(); const foo = new Foo();
assert(foo instanceof Foo); expect(foo instanceof Foo).toBeTrue();
});
test("derived ES5 classes", () => {
function Base() { function Base() {
this.is_base = true; this.is_base = true;
} }
@ -18,11 +18,7 @@ try {
Object.setPrototypeOf(Derived.prototype, Base.prototype); Object.setPrototypeOf(Derived.prototype, Base.prototype);
var d = new Derived(); const d = new Derived();
assert(d instanceof Derived); expect(d instanceof Derived).toBeTrue();
assert(d instanceof Base); expect(d instanceof Base).toBeTrue();
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -0,0 +1,50 @@
test("booleans", () => {
expect(true && true).toBeTrue();
expect(false && false).toBeFalse();
expect(true && false).toBeFalse();
expect(false && true).toBeFalse();
});
test("strings", () => {
expect("" && "").toBe("");
expect("" && false).toBe("");
expect("" && true).toBe("");
expect(false && "").toBeFalse();
expect(true && "").toBe("");
expect("foo" && "bar").toBe("bar");
expect("foo" && false).toBeFalse();
expect("foo" && true).toBeTrue();
expect(false && "bar").toBeFalse();
expect(true && "bar").toBe("bar");
});
test("numbers", () => {
expect(false && 1 === 2).toBeFalse();
expect(true && 1 === 2).toBeFalse();
expect(0 && false).toBe(0);
expect(0 && true).toBe(0);
expect(42 && false).toBeFalse();
expect(42 && true).toBeTrue();
expect(false && 0).toBeFalse();
expect(true && 0).toBe(0);
expect(false && 42).toBeFalse();
expect(true && 42).toBe(42);
});
test("objects", () => {
expect([] && false).toBeFalse();
expect([] && true).toBeTrue();
expect(false && []).toBeFalse();
expect(true && []).toHaveLength(0);
});
test("null & undefined", () => {
expect(null && false).toBeNull();
expect(null && true).toBeNull();
expect(false && null).toBeFalse();
expect(true && null).toBeNull();
expect(undefined && false).toBeUndefined();
expect(undefined && true).toBeUndefined();
expect(false && undefined).toBeFalse();
expect(true && undefined).toBeUndefined();
});

View file

@ -1,118 +0,0 @@
load("test-common.js");
try {
assert((true && true) === true);
assert((false && false) === false);
assert((true && false) === false);
assert((false && true) === false);
assert((false && 1 === 2) === false);
assert((true && 1 === 2) === false);
assert(("" && "") === "");
assert(("" && false) === "");
assert(("" && true) === "");
assert((false && "") === false);
assert((true && "") === "");
assert(("foo" && "bar") === "bar");
assert(("foo" && false) === false);
assert(("foo" && true) === true);
assert((false && "bar") === false);
assert((true && "bar") === "bar");
assert((0 && false) === 0);
assert((0 && true) === 0);
assert((42 && false) === false);
assert((42 && true) === true);
assert((false && 0) === false);
assert((true && 0) === 0);
assert((false && 42) === false);
assert((true && 42) === 42);
assert(([] && false) === false);
assert(([] && true) === true);
assert((false && []) === false);
assert((true && []).length === 0);
assert((null && false) === null);
assert((null && true) === null);
assert((false && null) === false);
assert((true && null) === null);
assert((undefined && false) === undefined);
assert((undefined && true) === undefined);
assert((false && undefined) === false);
assert((true && undefined) === undefined);
assert((true || true) === true);
assert((false || false) === false);
assert((true || false) === true);
assert((false || true) === true);
assert((false || 1 === 2) === false);
assert((true || 1 === 2) === true);
assert(("" || "") === "");
assert(("" || false) === false);
assert(("" || true) === true);
assert((false || "") === "");
assert((true || "") === true);
assert(("foo" || "bar") === "foo");
assert(("foo" || false) === "foo");
assert(("foo" || true) === "foo");
assert((false || "bar") === "bar");
assert((true || "bar") === true);
assert((0 || false) === false);
assert((0 || true) === true);
assert((42 || false) === 42);
assert((42 || true) === 42);
assert((false || 0) === 0);
assert((true || 0) === true);
assert((false || 42) === 42);
assert((true || 42) === true);
assert(([] || false).length === 0);
assert(([] || true).length === 0);
assert((false || []).length === 0);
assert((true || []) === true);
assert((null || false) === false);
assert((null || true) === true);
assert((false || null) === null);
assert((true || null) === true);
assert((undefined || false) === false);
assert((undefined || true) === true);
assert((false || undefined) === undefined);
assert((true || undefined) === true);
assert((true ?? true) === true);
assert((false ?? false) === false);
assert((true ?? false) === true);
assert((false ?? true) === false);
assert((false ?? 1 === 2) === false);
assert((true ?? 1 === 2) === true);
assert(("" ?? "") === "");
assert(("" ?? false) === "");
assert(("" ?? true) === "");
assert((false ?? "") === false);
assert((true ?? "") === true);
assert(("foo" ?? "bar") === "foo");
assert(("foo" ?? false) === "foo");
assert(("foo" ?? true) === "foo");
assert((false ?? "bar") === false);
assert((true ?? "bar") === true);
assert((0 ?? false) === 0);
assert((0 ?? true) === 0);
assert((42 ?? false) === 42);
assert((42 ?? true) === 42);
assert((false ?? 0) === false);
assert((true ?? 0) === true);
assert((false ?? 42) === false);
assert((true ?? 42) === true);
assert(([] ?? false).length === 0);
assert(([] ?? true).length === 0);
assert((false ?? []) === false);
assert((true ?? []) === true);
assert((null ?? false) === false);
assert((null ?? true) === true);
assert((false ?? null) === false);
assert((true ?? null) === true);
assert((undefined ?? false) === false);
assert((undefined ?? true) === true);
assert((false ?? undefined) === false);
assert((true ?? undefined) === true);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,15 +1,13 @@
load("test-common.js"); test("basic functionality", () => {
try {
let foo = 1; let foo = 1;
false && (foo = 2); false && (foo = 2);
assert(foo === 1); expect(foo).toBe(1);
foo = 1; foo = 1;
true || (foo = 2); true || (foo = 2);
assert(foo === 1); expect(foo).toBe(1);
console.log("PASS"); foo = 1;
} catch (e) { true ?? (foo = 2);
console.log("FAIL: " + e); expect(foo).toBe(1);
} });

View file

@ -0,0 +1,50 @@
test("booleans", () => {
expect(true ?? true).toBeTrue();
expect(false ?? false).toBeFalse();
expect(true ?? false).toBeTrue();
expect(false ?? true).toBeFalse();
});
test("strings", () => {
expect("" ?? "").toBe("");
expect("" ?? false).toBe("");
expect("" ?? true).toBe("");
expect(false ?? "").toBeFalse();
expect(true ?? "").toBeTrue();
expect("foo" ?? "bar").toBe("foo");
expect("foo" ?? false).toBe("foo");
expect("foo" ?? true).toBe("foo");
expect(false ?? "bar").toBeFalse();
expect(true ?? "bar").toBeTrue();
});
test("numbers", () => {
expect(false ?? 1 === 2).toBeFalse();
expect(true ?? 1 === 2).toBeTrue();
expect(0 ?? false).toBe(0);
expect(0 ?? true).toBe(0);
expect(42 ?? false).toBe(42);
expect(42 ?? true).toBe(42);
expect(false ?? 0).toBeFalse();
expect(true ?? 0).toBeTrue();
expect(false ?? 42).toBeFalse();
expect(true ?? 42).toBeTrue();
});
test("objects", () => {
expect([] ?? false).toHaveLength(0);
expect([] ?? true).toHaveLength(0);
expect(false ?? []).toBeFalse();
expect(true ?? []).toBeTrue();
});
test("null & undefined", () => {
expect(null ?? false).toBeFalse();
expect(null ?? true).toBeTrue();
expect(false ?? null).toBeFalse();
expect(true ?? null).toBeTrue();
expect(undefined ?? false).toBeFalse();
expect(undefined ?? true).toBeTrue();
expect(false ?? undefined).toBeFalse();
expect(true ?? undefined).toBeTrue();
});

View file

@ -0,0 +1,50 @@
test("booleans", () => {
expect(true || true).toBeTrue();
expect(false || false).toBeFalse();
expect(true || false).toBeTrue();
expect(false || true).toBeTrue();
});
test("strings", () => {
expect("" || "").toBe("");
expect("" || false).toBeFalse();
expect("" || true).toBeTrue();
expect(false || "").toBe("");
expect(true || "").toBeTrue();
expect("foo" || "bar").toBe("foo");
expect("foo" || false).toBe("foo");
expect("foo" || true).toBe("foo");
expect(false || "bar").toBe("bar");
expect(true || "bar").toBeTrue();
});
test("numbers", () => {
expect(false || 1 === 2).toBeFalse();
expect(true || 1 === 2).toBeTrue();
expect(0 || false).toBeFalse();
expect(0 || true).toBeTrue();
expect(42 || false).toBe(42);
expect(42 || true).toBe(42);
expect(false || 0).toBe(0);
expect(true || 0).toBeTrue();
expect(false || 42).toBe(42);
expect(true || 42).toBeTrue();
});
test("objects", () => {
expect([] || false).toHaveLength(0);
expect([] || true).toHaveLength(0);
expect(false || []).toHaveLength(0);
expect(true || []).toBeTrue();
});
test("null & undefined", () => {
expect(null || false).toBeFalse();
expect(null || true).toBeTrue();
expect(false || null).toBeNull();
expect(true || null).toBeTrue();
expect(undefined || false).toBeFalse();
expect(undefined || true).toBeTrue();
expect(false || undefined).toBeUndefined();
expect(true || undefined).toBeTrue();
});

View file

@ -1,22 +1,16 @@
load("test-common.js"); test("basic functionality", () => {
expect(10 % 3).toBe(1);
try { expect(10.5 % 2.5).toBe(0.5);
assert(10 % 3 === 1); expect(-0.99 % 0.99).toBe(-0);
assert(10.5 % 2.5 === 0.5);
assert(-0.99 % 0.99 === -0);
// Examples from MDN: // Examples from MDN:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators
assert(12 % 5 === 2); expect(12 % 5).toBe(2);
assert(-1 % 2 === -1); expect(-1 % 2).toBe(-1);
assert(1 % -2 === 1); expect(1 % -2).toBe(1);
assert(isNaN(NaN % 2)); expect(1 % 2).toBe(1);
assert(1 % 2 === 1); expect(2 % 3).toBe(2);
assert(2 % 3 === 2); expect(-4 % 2).toBe(-0);
assert(-4 % 2 === -0); expect(5.5 % 2).toBe(1.5);
assert(5.5 % 2 === 1.5); expect(NaN % 2).toBeNaN();
});
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,21 +1,16 @@
load("test-common.js"); test("basic functionality", () => {
const x = 1;
try { expect(x === 1 ? true : false).toBeTrue();
var x = 1; expect(x ? x : 0).toBe(x);
expect(1 < 2 ? true : false).toBeTrue();
expect(0 ? 1 : 1 ? 10 : 20).toBe(10);
expect(0 ? (1 ? 1 : 10) : 20).toBe(20);
});
assert(x === 1 ? true : false); test("object values", () => {
assert((x ? x : 0) === x); const o = {};
assert(1 < 2 ? true : false);
assert((0 ? 1 : 1 ? 10 : 20) === 10);
assert((0 ? (1 ? 1 : 10) : 20) === 20);
var o = {};
o.f = true; o.f = true;
assert(o.f ? true : false); expect(o.f ? true : false).toBeTrue();
expect(1 ? o.f : null).toBeTrue();
assert(1 ? o.f : null); });
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -1,27 +1,27 @@
load("test-common.js"); test("basic functionality", () => {
expect(typeof "foo").toBe("string");
try { expect(typeof (1 + 2)).toBe("number");
assert(typeof "foo" === "string"); expect(typeof {}).toBe("object");
assert(!(typeof "foo" !== "string")); expect(typeof null).toBe("object");
assert(typeof (1 + 2) === "number"); expect(typeof undefined).toBe("undefined");
assert(typeof {} === "object"); expect(typeof 1n).toBe("bigint");
assert(typeof null === "object"); expect(typeof Symbol()).toBe("symbol");
assert(typeof undefined === "undefined"); expect(typeof function () {}).toBe("function");
var iExist = 1; var iExist = 1;
assert(typeof iExist === "number"); expect(typeof iExist).toBe("number");
assert(typeof iDontExist === "undefined"); expect(typeof iDontExist).toBe("undefined");
});
test("typeof calls property getter", () => {
var calls = 0; var calls = 0;
Object.defineProperty(globalThis, "foo", { Object.defineProperty(globalThis, "foo", {
get() { get() {
calls++; calls++;
return 10;
}, },
}); });
assert(typeof foo === "undefined");
assert(calls === 1);
console.log("PASS"); expect(typeof foo).toBe("number");
} catch (e) { expect(calls).toBe(1);
console.log("FAIL: " + e); });
}

View file

@ -1,20 +1,14 @@
load("test-common.js"); test("basic functionality", () => {
expect(void "").toBeUndefined();
try { expect(void "foo").toBeUndefined();
assert(void "" === undefined); expect(void 1).toBeUndefined();
assert(void "foo" === undefined); expect(void 42).toBeUndefined();
assert(void 1 === undefined); expect(void true).toBeUndefined();
assert(void 42 === undefined); expect(void false).toBeUndefined();
assert(void true === undefined); expect(void null).toBeUndefined();
assert(void false === undefined); expect(void undefined).toBeUndefined();
assert(void null === undefined); expect(void function () {}).toBeUndefined();
assert(void undefined === undefined); expect(void (() => {})).toBeUndefined();
assert(void function () {} === undefined); expect(void (() => "hello friends")()).toBeUndefined();
assert(void (() => {}) === undefined); expect((() => void "hello friends")()).toBeUndefined();
assert(void (() => "hello friends")() === undefined); });
assert((() => void "hello friends")() === undefined);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -43,6 +43,12 @@
// FIXME: Will eventually not be necessary when all tests are converted // FIXME: Will eventually not be necessary when all tests are converted
Vector<String> tests_to_run = { Vector<String> tests_to_run = {
"builtins/BigInt/BigInt.js",
"builtins/BigInt/bigint-basic.js",
"builtins/BigInt/bigint-number-mix-errors.js",
"builtins/BigInt/BigInt.prototype.toLocaleString.js",
"builtins/BigInt/BigInt.prototype.toString.js",
"builtins/BigInt/BigInt.prototype.valueOf.js",
"builtins/Boolean/Boolean.js", "builtins/Boolean/Boolean.js",
"builtins/Boolean/Boolean.prototype.js", "builtins/Boolean/Boolean.prototype.js",
"builtins/Boolean/Boolean.prototype.toString.js", "builtins/Boolean/Boolean.prototype.toString.js",
@ -169,6 +175,65 @@ Vector<String> tests_to_run = {
"builtins/String/String.prototype.trim.js", "builtins/String/String.prototype.trim.js",
"builtins/String/String.prototype.valueOf.js", "builtins/String/String.prototype.valueOf.js",
"builtins/String/String.raw.js", "builtins/String/String.raw.js",
"builtins/Symbol/Symbol.js",
"builtins/Symbol/Symbol.for.js",
"builtins/Symbol/Symbol.keyFor.js",
"builtins/Symbol/Symbol.prototype.toString.js",
"builtins/Symbol/Symbol.prototype.valueOf.js",
"classes/class-advanced-extends.js",
"classes/class-basic.js",
"classes/class-constructor.js",
"classes/class-errors.js",
"classes/class-expressions.js",
"classes/class-getters.js",
"classes/class-inheritance.js",
"classes/class-methods.js",
"classes/class-setters.js",
"classes/class-static.js",
"classes/class-static-getters.js",
"classes/class-static-setters.js",
"classes/class-strict-mode.js",
"functions/arrow-functions.js",
"functions/constructor-basic.js",
"functions/function-default-parameters.js",
"functions/function-hoisting.js",
"functions/function-length.js",
"functions/function-missing-arg.js",
"functions/function-name.js",
"functions/function-rest-params.js",
"functions/function-spread.js",
"functions/function-strict-mode.js",
"functions/function-this-in-arguments.js",
"functions/function-TypeError.js",
"loops/continue-basic.js",
"loops/do-while-basic.js",
"loops/for-basic.js",
"loops/for-head-errors.js",
"loops/for-in-basic.js",
"loops/for-no-curlies.js",
"loops/for-of-basic.js",
"loops/for-scopes.js",
"loops/while-basic.js",
"operators/assignment-operators.js",
"operators/binary-bitwise-left-shift.js",
"operators/binary-bitwise-or.js",
"operators/binary-bitwise-right-shift.js",
"operators/binary-bitwise-unsigned-right-shift.js",
"operators/binary-relational.js",
"operators/comma-operator.js",
"operators/delete-basic.js",
"operators/delete-global-variable.js",
"operators/delete-globalThis-property-crash.js",
"operators/in-operator-basic.js",
"operators/instanceof-basic.js",
"operators/logical-and.js",
"operators/logical-expressions-short-circuit.js",
"operators/logical-nullish-coalescing.js",
"operators/logical-or.js",
"operators/modulo-basic.js",
"operators/ternary-basic.js",
"operators/typeof-basic.js",
"operators/void-basic.js",
"add-values-to-primitive.js", "add-values-to-primitive.js",
"automatic-semicolon-insertion.js", "automatic-semicolon-insertion.js",
"comments-basic.js", "comments-basic.js",