1032 lines
38 KiB
JavaScript
1032 lines
38 KiB
JavaScript
// isWhiteSpace() and stripSpaces() are borrowed from
|
|
// kde/script-tests/inbuilt_function_tostring.js and modified.
|
|
|
|
let section;
|
|
let failures = "";
|
|
let failureCount = 0;
|
|
|
|
let nonSymbolValues = [ "foo", "", undefined, null, true, false, 0, 10, 1234.567 ];
|
|
let symbolValues = [
|
|
{ v: Symbol("foo"), name: "[foo]" },
|
|
{ v: Symbol(""), name: "[]" },
|
|
{ v: Symbol(), name: "" },
|
|
];
|
|
|
|
function isWhiteSpace(string) {
|
|
let cc = string.charCodeAt(0);
|
|
switch (cc) {
|
|
case (0x0009):
|
|
case (0x000B):
|
|
case (0x000C):
|
|
case (0x0020):
|
|
case (0x000A):
|
|
case (0x000D):
|
|
case (59): // let's strip out semicolons, too
|
|
return true;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function minimizeSpaces(s) {
|
|
let currentChar;
|
|
let strippedString;
|
|
let previousCharIsWhiteSpace = false;
|
|
for (currentChar = 0, strippedString = ""; currentChar < s.length; currentChar++) {
|
|
let ch = s.charAt(currentChar);
|
|
if (!isWhiteSpace(ch)) {
|
|
if (previousCharIsWhiteSpace &&
|
|
(ch == '(' || ch == ')' || ch == '{' || ch == '}' || ch == '[' || ch == ']'))
|
|
strippedString = strippedString.slice(0, strippedString.length - 1);
|
|
strippedString += ch;
|
|
previousCharIsWhiteSpace = false;
|
|
} else if (!previousCharIsWhiteSpace) {
|
|
strippedString += ' ';
|
|
previousCharIsWhiteSpace = true;
|
|
}
|
|
}
|
|
return strippedString;
|
|
}
|
|
|
|
function shouldBe(desc, funcName, actual, expected) {
|
|
if (typeof(actual) !== typeof(expected) || actual !== expected) {
|
|
failures += (" " + section + ": " + desc + "'" + funcName + "': typeof expected: " + typeof(expected) + ", typeof actual: " + typeof(actual) + "\n");
|
|
failures += (" expected: '" + expected + "', actual: '" + actual + "'\n");
|
|
failureCount++;
|
|
}
|
|
}
|
|
|
|
function toString(x) {
|
|
if (typeof x === "symbol")
|
|
return x.toString();
|
|
return "" + x;
|
|
}
|
|
|
|
function test(func, expectedName, expectedToString) {
|
|
shouldBe("Function.name on ", expectedName, func.name, expectedName);
|
|
|
|
let str = func.toString();
|
|
shouldBe("Function#toString on ", expectedName, minimizeSpaces(str), minimizeSpaces(expectedToString));
|
|
|
|
let origDesc = Object.getOwnPropertyDescriptor(func, "name");
|
|
shouldBe("Function.name configurability of ", expectedName, origDesc.configurable, true);
|
|
shouldBe("Function.name writability of ", expectedName, origDesc.writable, false);
|
|
shouldBe("Function.name enumerability of ", expectedName, origDesc.enumerable, false);
|
|
|
|
// We should not be able to change Function.name while it is not writable.
|
|
let origFuncName = func.name;
|
|
let modifiedFuncName = "modified_" + toString(origFuncName);
|
|
func.name = modifiedFuncName;
|
|
shouldBe("Function.name (after attempted write) on ", expectedName, func.name, expectedName);
|
|
|
|
// We should be able to change Function.name after making it writable.
|
|
Object.defineProperty(func, "name", { writable: true });
|
|
let modifiedDesc = Object.getOwnPropertyDescriptor(func, "name");
|
|
shouldBe("Function.name writability (after made writable) of ", expectedName, modifiedDesc.writable, true);
|
|
|
|
func.name = modifiedFuncName;
|
|
shouldBe("Function.name (after attempted write again) on ", expectedName, func.name, modifiedFuncName);
|
|
|
|
// But the toString name should not have changed.
|
|
str = func.toString();
|
|
shouldBe("Function#toString (after attempted write) on ", expectedName, minimizeSpaces(str), minimizeSpaces(expectedToString));
|
|
|
|
// Put things back to the original state.
|
|
Object.defineProperty(func, "name", origDesc);
|
|
}
|
|
|
|
section = "builtin function";
|
|
{
|
|
test(Array.prototype.every, "every", "function every() { [native code] }");
|
|
test(Array.prototype.forEach, "forEach", "function forEach() { [native code] }");
|
|
test(Array.prototype.some, "some", "function some() { [native code] }");
|
|
|
|
section = "bound builtin function";
|
|
{
|
|
let o = {}
|
|
let boundEvery = Array.prototype.every.bind(o);
|
|
test(boundEvery, "bound every", "function every() { [native code] }");
|
|
let boundForEach = Array.prototype.forEach.bind(o);
|
|
test(boundForEach, "bound forEach", "function forEach() { [native code] }");
|
|
}
|
|
}
|
|
|
|
section = "native function";
|
|
{
|
|
test(Array.prototype.splice, "splice", "function splice() { [native code] }");
|
|
test(Array.prototype.unshift, "unshift", "function unshift() { [native code] }");
|
|
test(Array.prototype.indexOf, "indexOf", "function indexOf() { [native code] }");
|
|
|
|
section = "bound native function";
|
|
{
|
|
let o = {}
|
|
let boundSplice = Array.prototype.splice.bind(o);
|
|
test(boundSplice, "bound splice", "function splice() { [native code] }");
|
|
let boundUnshift = Array.prototype.unshift.bind(o);
|
|
test(boundUnshift, "bound unshift", "function unshift() { [native code] }");
|
|
}
|
|
}
|
|
|
|
section = "InternalFunction";
|
|
{
|
|
test(Array, "Array", "function Array() { [native code] }");
|
|
test(Boolean, "Boolean", "function Boolean() { [native code] }");
|
|
|
|
section = "bound InternalFunction";
|
|
{
|
|
let o = {}
|
|
let boundArray = Array.bind(o);
|
|
test(boundArray, "bound Array", "function Array() { [native code] }");
|
|
let boundBoolean = Boolean.bind(o);
|
|
test(boundBoolean, "bound Boolean", "function Boolean() { [native code] }");
|
|
}
|
|
}
|
|
|
|
section = "JS function";
|
|
{
|
|
function foo1() {}
|
|
test(foo1, "foo1", "function foo1() {}");
|
|
|
|
let foo2 = function() {}
|
|
test(foo2, "foo2", "function() {}");
|
|
|
|
let foo3 = (function() {
|
|
function goo3() {}
|
|
return goo3;
|
|
}) ();
|
|
test(foo3, "goo3", "function goo3() {}");
|
|
|
|
let foo4 = (function() {
|
|
return (function() {});
|
|
}) ();
|
|
test(foo4, "", "function() {}");
|
|
|
|
section = "bound JS function";
|
|
{
|
|
let o = {}
|
|
let boundFoo1 = foo1.bind(o);
|
|
test(boundFoo1, "bound foo1", "function foo1() { [native code] }");
|
|
let boundFoo2 = foo2.bind(o);
|
|
test(boundFoo2, "bound foo2", "function foo2() { [native code] }");
|
|
let boundFoo3 = foo3.bind(o);
|
|
test(boundFoo3, "bound goo3", "function goo3() { [native code] }");
|
|
let boundFoo4 = foo4.bind(o);
|
|
test(boundFoo4, "bound ", "function () { [native code] }");
|
|
|
|
test((function(){}).bind({}), "bound ", "function () { [native code] }");
|
|
}
|
|
}
|
|
|
|
section = "Object property";
|
|
{
|
|
let o = {
|
|
prop1: function() {},
|
|
prop2: function namedProp2() {}
|
|
};
|
|
o.prop3 = function() { };
|
|
o.prop4 = function namedProp4() {};
|
|
test(o.prop1, "prop1", "function() {}");
|
|
test(o.prop2, "namedProp2", "function namedProp2() {}");
|
|
test(o.prop3, "", "function() {}");
|
|
test(o.prop4, "namedProp4", "function namedProp4() {}");
|
|
|
|
section = "bound Object property";
|
|
{
|
|
let boundProp1 = o.prop1.bind({});
|
|
test(boundProp1, "bound prop1", "function prop1() { [native code] }");
|
|
let boundFoo2 = o.prop2.bind({});
|
|
test(boundFoo2, "bound namedProp2", "function namedProp2() { [native code] }");
|
|
let boundFoo3 = o.prop3.bind({});
|
|
test(boundFoo3, "bound ", "function() { [native code] }");
|
|
let boundFoo4 = o.prop4.bind({});
|
|
test(boundFoo4, "bound namedProp4", "function namedProp4() { [native code] }");
|
|
}
|
|
}
|
|
|
|
section = "object shorthand method";
|
|
{
|
|
let o = {
|
|
prop1() {},
|
|
prop2(x) {}
|
|
};
|
|
test(o.prop1, "prop1", "function prop1() {}");
|
|
test(o.prop2, "prop2", "function prop2(x) {}");
|
|
|
|
section = "bound object shorthand method";
|
|
{
|
|
let boundProp1 = o.prop1.bind(o);
|
|
test(boundProp1, "bound prop1", "function prop1() { [native code] }");
|
|
let boundProp2 = o.prop2.bind(o);
|
|
test(boundProp2, "bound prop2", "function prop2() { [native code] }");
|
|
}
|
|
}
|
|
|
|
section = "class from statement";
|
|
(function () {
|
|
class foo {}
|
|
class bar {}
|
|
class bax { static name() {} }
|
|
let baz = bar;
|
|
class goo extends foo {}
|
|
|
|
test(foo, "foo", "class foo {}");
|
|
test(bar, "bar", "class bar {}");
|
|
shouldBe("typeof bax.name of ", "bax", typeof bax.name, "function");
|
|
shouldBe("toString of ", "bax", bax.toString(), "class bax { static name() {} }");
|
|
test(baz, "bar", "class bar {}");
|
|
test(goo, "goo", "class goo extends foo {}");
|
|
|
|
section = "bound class from statement";
|
|
{
|
|
let bound1 = foo.bind({});
|
|
test(bound1, "bound foo", "function foo() { [native code] }");
|
|
let bound2 = bar.bind({});
|
|
test(bound2, "bound bar", "function bar() { [native code] }");
|
|
let bound3 = bax.bind({});
|
|
test(bound3, "bound ", "function() { [native code] }"); // bax.name is not a string.
|
|
let bound4 = baz.bind({});
|
|
test(bound4, "bound bar", "function bar() { [native code] }");
|
|
let bound5 = goo.bind({});
|
|
test(bound5, "bound goo", "function goo() { [native code] }");
|
|
}
|
|
})();
|
|
|
|
section = "class with constructor from statement";
|
|
(function () {
|
|
class foo { constructor(x) {} }
|
|
class bar { constructor() {} }
|
|
class bax { static name() {} constructor() {} }
|
|
let baz = bar;
|
|
class goo extends foo { constructor() { super(5); } }
|
|
|
|
test(foo, "foo", "class foo { constructor(x) {} }");
|
|
test(bar, "bar", "class bar { constructor() {} }");
|
|
shouldBe("typeof bax.name of ", "bax", typeof bax.name, "function");
|
|
shouldBe("toString of ", "bax", bax.toString(), "class bax { static name() {} constructor() {} }");
|
|
test(baz, "bar", "class bar { constructor() {} }");
|
|
test(goo, "goo", "class goo extends foo { constructor() { super(5); } }");
|
|
|
|
section = "bound class with constructor from statement";
|
|
{
|
|
let bound1 = foo.bind({});
|
|
test(bound1, "bound foo", "function foo() { [native code] }");
|
|
let bound2 = bar.bind({});
|
|
test(bound2, "bound bar", "function bar() { [native code] }");
|
|
let bound3 = bax.bind({});
|
|
test(bound3, "bound ", "function() { [native code] }"); // bax.name is not a string.
|
|
let bound4 = baz.bind({});
|
|
test(bound4, "bound bar", "function bar() { [native code] }");
|
|
let bound5 = goo.bind({});
|
|
test(bound5, "bound goo", "function goo() { [native code] }");
|
|
}
|
|
})();
|
|
|
|
section = "class from expression";
|
|
(function () {
|
|
let foo = class namedFoo {}
|
|
let bar = class {}
|
|
let bax = class { static name() {} }
|
|
let baz = bar;
|
|
let goo = class extends foo {}
|
|
|
|
test(foo, "namedFoo", "class namedFoo {}");
|
|
test(bar, "bar", "class {}");
|
|
shouldBe("typeof bax.name of ", "bax", typeof bax.name, "function");
|
|
shouldBe("toString of ", "bax", bax.toString(), "class { static name() {} }");
|
|
test(baz, "bar", "class {}");
|
|
test(goo, "goo", "class extends foo {}");
|
|
|
|
section = "bound class from expression";
|
|
{
|
|
let bound1 = foo.bind({});
|
|
test(bound1, "bound namedFoo", "function namedFoo() { [native code] }");
|
|
let bound2 = bar.bind({});
|
|
test(bound2, "bound bar", "function bar() { [native code] }");
|
|
let bound3 = bax.bind({});
|
|
test(bound3, "bound ", "function() { [native code] }"); // bax.name is not a string.
|
|
let bound4 = baz.bind({});
|
|
test(bound4, "bound bar", "function bar() { [native code] }");
|
|
let bound5 = goo.bind({});
|
|
test(bound5, "bound goo", "function goo() { [native code] }");
|
|
}
|
|
})();
|
|
|
|
section = "class with constructor from expression";
|
|
(function () {
|
|
let foo = class namedFoo { constructor(x) {} }
|
|
let bar = class { constructor() {} }
|
|
let bax = class { static name() {} constructor() {} }
|
|
let baz = bar;
|
|
let goo = class extends foo { constructor() { super(x) } }
|
|
|
|
test(foo, "namedFoo", "class namedFoo { constructor(x) {} }");
|
|
test(bar, "bar", "class { constructor() {} }");
|
|
shouldBe("typeof bax.name of ", "bax", typeof bax.name, "function");
|
|
shouldBe("toString of ", "bax", bax.toString(), "class { static name() {} constructor() {} }");
|
|
test(baz, "bar", "class { constructor() {} }");
|
|
test(goo, "goo", "class extends foo { constructor() { super(x) } }");
|
|
|
|
section = "bound class with constructor from expression";
|
|
{
|
|
let bound1 = foo.bind({});
|
|
test(bound1, "bound namedFoo", "function namedFoo() { [native code] }");
|
|
let bound2 = bar.bind({});
|
|
test(bound2, "bound bar", "function bar() { [native code] }");
|
|
let bound3 = bax.bind({});
|
|
test(bound3, "bound ", "function() { [native code] }"); // bax.name is not a string.
|
|
let bound4 = baz.bind({});
|
|
test(bound4, "bound bar", "function bar() { [native code] }");
|
|
let bound5 = goo.bind({});
|
|
test(bound5, "bound goo", "function goo() { [native code] }");
|
|
}
|
|
})();
|
|
|
|
section = "class in object property";
|
|
(function () {
|
|
class gooBase {}
|
|
let o = {
|
|
foo: class {},
|
|
bar: class {},
|
|
bax: class { static name() {} },
|
|
goo: class extends gooBase {},
|
|
};
|
|
o.bay = o.bar;
|
|
o.baz = class {};
|
|
|
|
test(o.foo, "foo", "class {}");
|
|
test(o.bar, "bar", "class {}");
|
|
shouldBe("typeof o.bax.name of ", "o.bax", typeof o.bax.name, "function");
|
|
shouldBe("toString of ", "o.bax", o.bax.toString(), "class { static name() {} }");
|
|
test(o.bay, "bar", "class {}");
|
|
test(o.baz, "", "class {}");
|
|
test(o.goo, "goo", "class extends gooBase {}");
|
|
|
|
section = "bound class in object property";
|
|
{
|
|
let bound1 = o.foo.bind({});
|
|
test(bound1, "bound foo", "function foo() { [native code] }");
|
|
let bound2 = o.bar.bind({});
|
|
test(bound2, "bound bar", "function bar() { [native code] }");
|
|
let bound3 = o.bax.bind({});
|
|
test(bound3, "bound ", "function() { [native code] }"); // bax.name is not a string.
|
|
let bound4 = o.bay.bind({});
|
|
test(bound4, "bound bar", "function bar() { [native code] }");
|
|
let bound5 = o.baz.bind({});
|
|
test(bound5, "bound ", "function() { [native code] }");
|
|
let bound6 = o.goo.bind({});
|
|
test(bound6, "bound goo", "function goo() { [native code] }");
|
|
}
|
|
})();
|
|
|
|
section = "class with constructor in object property";
|
|
(function () {
|
|
class gooBase { constructor(x) {} }
|
|
let o = {
|
|
foo: class { constructor(x) {} },
|
|
bar: class { constructor() {} },
|
|
bax: class { static name() {} constructor() {} },
|
|
goo: class extends gooBase { constructor() { super(5); } },
|
|
};
|
|
o.bay = o.bar;
|
|
o.baz = class { constructor() {} };
|
|
|
|
test(o.foo, "foo", "class { constructor(x) {} }");
|
|
test(o.bar, "bar", "class { constructor() {} }");
|
|
shouldBe("typeof o.bax.name of ", "o.bax", typeof o.bax.name, "function");
|
|
shouldBe("toString of ", "o.bax", o.bax.toString(), "class { static name() {} constructor() {} }");
|
|
test(o.bay, "bar", "class { constructor() {} }");
|
|
test(o.baz, "", "class { constructor() {} }");
|
|
test(o.goo, "goo", "class extends gooBase { constructor() { super(5); } }");
|
|
|
|
section = "bound class with constructor in object property";
|
|
{
|
|
let bound1 = o.foo.bind({});
|
|
test(bound1, "bound foo", "function foo() { [native code] }");
|
|
let bound2 = o.bar.bind({});
|
|
test(bound2, "bound bar", "function bar() { [native code] }");
|
|
let bound3 = o.bax.bind({});
|
|
test(bound3, "bound ", "function() { [native code] }"); // bax.name is not a string.
|
|
let bound4 = o.bay.bind({});
|
|
test(bound4, "bound bar", "function bar() { [native code] }");
|
|
let bound5 = o.baz.bind({});
|
|
test(bound5, "bound ", "function() { [native code] }");
|
|
let bound6 = o.goo.bind({});
|
|
test(bound6, "bound goo", "function goo() { [native code] }");
|
|
}
|
|
})();
|
|
|
|
section = "global class statement";
|
|
// Checking if there are CodeCache badness that can result from global class statements
|
|
// with identical bodies.
|
|
class globalCS1 { constructor(x) { return x; } stuff() { return 5; } }
|
|
// Identical class body as CS1.
|
|
class globalCS2 { constructor(x) { return x; } stuff() { return 5; } }
|
|
// Identical constructor as CS2 & CS1, but different otherwise.
|
|
class globalCS3 { constructor(x) { return x; } stuff3() { return 15; } }
|
|
|
|
test(globalCS1, "globalCS1", "class globalCS1 { constructor(x) { return x; } stuff() { return 5; } }");
|
|
test(globalCS2, "globalCS2", "class globalCS2 { constructor(x) { return x; } stuff() { return 5; } }");
|
|
test(globalCS3, "globalCS3", "class globalCS3 { constructor(x) { return x; } stuff3() { return 15; } }");
|
|
|
|
section = "global class expression";
|
|
// Checking if there are CodeCache badness that can result from global class expressions
|
|
// with identical bodies.
|
|
var globalCE1 = class { constructor(x) { return x; } stuff() { return 5; } }
|
|
// Identical class body as CSE1.
|
|
var globalCE2 = class { constructor(x) { return x; } stuff() { return 5; } }
|
|
// Identical constructor as CSE2 & CSE1, but different otherwise.
|
|
var globalCE3 = class { constructor(x) { return x; } stuff3() { return 15; } }
|
|
|
|
test(globalCE1, "globalCE1", "class { constructor(x) { return x; } stuff() { return 5; } }");
|
|
test(globalCE2, "globalCE2", "class { constructor(x) { return x; } stuff() { return 5; } }");
|
|
test(globalCE3, "globalCE3", "class { constructor(x) { return x; } stuff3() { return 15; } }");
|
|
|
|
section = "class statements in eval";
|
|
// Checking if there are CodeCache badness that can result from class statements in
|
|
// identical eval statements.
|
|
(function () {
|
|
let body1 = "class foo { constructor(x) { return x; } stuff() { return 5; } }; foo";
|
|
// Identical class body as body1.
|
|
let body2 = "class foo { constructor(x) { return x; } stuff() { return 5; } }; foo";
|
|
// Identical constructor as body1 & body2, but different otherwise.
|
|
let body3 = "class foo3 { constructor(x) { return x; } stuff3() { return 15; } }; foo3";
|
|
|
|
let bar1 = eval(body1);
|
|
let bar2 = eval(body2);
|
|
let bar3 = eval(body3);
|
|
let bar4 = eval(body1);
|
|
|
|
test(bar1, "foo", "class foo { constructor(x) { return x; } stuff() { return 5; } }");
|
|
test(bar2, "foo", "class foo { constructor(x) { return x; } stuff() { return 5; } }");
|
|
test(bar3, "foo3", "class foo3 { constructor(x) { return x; } stuff3() { return 15; } }");
|
|
test(bar4, "foo", "class foo { constructor(x) { return x; } stuff() { return 5; } }");
|
|
})();
|
|
|
|
section = "class expressions in eval";
|
|
// Checking if there are CodeCache badness that can result from class expressions in
|
|
// identical eval statements.
|
|
(function () {
|
|
let body1 = "var foo = class { constructor(x) { return x; } stuff() { return 5; } }; foo";
|
|
// Identical class body as body1.
|
|
let body2 = "var foo = class { constructor(x) { return x; } stuff() { return 5; } }; foo";
|
|
// Identical constructor as body1 & body2, but different otherwise.
|
|
let body3 = "var foo3 = class { constructor(x) { return x; } stuff3() { return 15; } }; foo3";
|
|
|
|
let bar1 = eval(body1);
|
|
let bar2 = eval(body2);
|
|
let bar3 = eval(body3);
|
|
let bar4 = eval(body1);
|
|
|
|
test(bar1, "foo", "class { constructor(x) { return x; } stuff() { return 5; } }");
|
|
test(bar2, "foo", "class { constructor(x) { return x; } stuff() { return 5; } }");
|
|
test(bar3, "foo3", "class { constructor(x) { return x; } stuff3() { return 15; } }");
|
|
test(bar4, "foo", "class { constructor(x) { return x; } stuff() { return 5; } }");
|
|
})();
|
|
|
|
section = "class statements in dynamically created Functions";
|
|
// Checking if there are CodeCache badness that can result from dynamically created
|
|
// Function objects with class statements in identical bodies.
|
|
(function () {
|
|
let body1 = "class foo { constructor(x) { return x; } stuff() { return 5; } } return foo;";
|
|
// Identical class body as body1.
|
|
let body2 = "class foo { constructor(x) { return x; } stuff() { return 5; } } return foo;";
|
|
// Identical constructor as body1 & body2, but different otherwise.
|
|
let body3 = "class foo3 { constructor(x) { return x; } stuff3() { return 15; } } return foo3;";
|
|
|
|
let bar1 = new Function(body1);
|
|
let bar2 = new Function(body2);
|
|
let bar3 = new Function(body3);
|
|
|
|
test(bar1(), "foo", "class foo { constructor(x) { return x; } stuff() { return 5; } }");
|
|
test(bar2(), "foo", "class foo { constructor(x) { return x; } stuff() { return 5; } }");
|
|
test(bar3(), "foo3", "class foo3 { constructor(x) { return x; } stuff3() { return 15; } }");
|
|
})();
|
|
|
|
section = "class expressions in dynamically created Functions";
|
|
// Checking if there are CodeCache badness that can result from dynamically created
|
|
// Function objects with class expressions in identical bodies.
|
|
(function () {
|
|
let body1 = "var foo = class { constructor(x) { return x; } stuff() { return 5; } }; return foo;";
|
|
// Identical class body as body1.
|
|
let body2 = "var foo = class { constructor(x) { return x; } stuff() { return 5; } }; return foo;";
|
|
// Identical constructor as body1 & body2, but different otherwise.
|
|
let body3 = "var foo3 = class { constructor(x) { return x; } stuff3() { return 15; } }; return foo3;";
|
|
|
|
let bar1 = new Function(body1);
|
|
let bar2 = new Function(body2);
|
|
let bar3 = new Function(body3);
|
|
|
|
test(bar1(), "foo", "class { constructor(x) { return x; } stuff() { return 5; } }");
|
|
test(bar2(), "foo", "class { constructor(x) { return x; } stuff() { return 5; } }");
|
|
test(bar3(), "foo3", "class { constructor(x) { return x; } stuff3() { return 15; } }");
|
|
})();
|
|
|
|
section = "Object computed non-symbol anonymous function property";
|
|
(function() {
|
|
let values = nonSymbolValues;
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]: function() {},
|
|
}
|
|
test(o[value], toString(value), "function() {}");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound " + toString(value), "function " + toString(value) + "() { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i]);
|
|
})();
|
|
|
|
section = "Object computed non-symbol named function property";
|
|
(function() {
|
|
let values = nonSymbolValues;
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]: function bar() {},
|
|
}
|
|
test(o[value], "bar", "function bar() {}");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound bar", "function bar() { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i]);
|
|
})();
|
|
|
|
section = "Object computed non-symbol property with shorthand function";
|
|
(function () {
|
|
let values = nonSymbolValues;
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]() {},
|
|
}
|
|
test(o[value], toString(value), "function() {}");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound " + toString(value), "function " + toString(value) + "() { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i]);
|
|
})();
|
|
|
|
section = "Object computed non-symbol property with get/set function";
|
|
(function () {
|
|
let values = nonSymbolValues;
|
|
function runTest(value) {
|
|
let o = {
|
|
get [value]() {},
|
|
set [value](x) {},
|
|
}
|
|
|
|
let desc = Object.getOwnPropertyDescriptor(o, value);
|
|
test(desc.get, "get " + value, "function() {}");
|
|
test(desc.set, "set " + value, "function(x) {}");
|
|
|
|
let bound = desc.get.bind({});
|
|
test(bound, "bound get " + toString(value), "function get " + toString(value) + "() { [native code] }");
|
|
bound = desc.set.bind({});
|
|
test(bound, "bound set " + toString(value), "function set " + toString(value) + "() { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i]);
|
|
})();
|
|
|
|
section = "Object computed symbol anonymous function property";
|
|
(function() {
|
|
let values = symbolValues;
|
|
function runTest(value, expectedName) {
|
|
let o = {
|
|
[value]: function() {},
|
|
}
|
|
test(o[value], expectedName, "function() {}");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound " + expectedName, "function " + expectedName + "() { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i].v, values[i].name);
|
|
})();
|
|
|
|
section = "Object computed symbol named function property";
|
|
(function() {
|
|
let values = symbolValues;
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]: function bar() {},
|
|
}
|
|
test(o[value], "bar", "function bar() {}");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound bar", "function bar() { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i].v);
|
|
})();
|
|
|
|
section = "Object computed symbol property with shorthand function";
|
|
(function() {
|
|
let values = symbolValues;
|
|
function runTest(value, expectedName) {
|
|
let o = {
|
|
[value]() {},
|
|
}
|
|
test(o[value], expectedName, "function() {}");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound " + expectedName, "function " + expectedName + "() { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i].v, values[i].name);
|
|
})();
|
|
|
|
section = "Object computed symbol property with get/set function";
|
|
(function () {
|
|
let values = symbolValues;
|
|
function runTest(value, expectedName) {
|
|
let o = {
|
|
get [value]() {},
|
|
set [value](x) {},
|
|
}
|
|
|
|
let desc = Object.getOwnPropertyDescriptor(o, value);
|
|
test(desc.get, "get " + expectedName, "function() {}");
|
|
test(desc.set, "set " + expectedName, "function(x) {}");
|
|
|
|
let bound = desc.get.bind({});
|
|
test(bound, "bound get " + expectedName, "function get " + expectedName + "() { [native code] }");
|
|
bound = desc.set.bind({});
|
|
test(bound, "bound set " + expectedName, "function set " + expectedName + "() { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i].v, values[i].name);
|
|
})();
|
|
|
|
// Test functions in destructuring assignments.
|
|
section = "destructuring assignment";
|
|
{
|
|
let prop1;
|
|
let prop2;
|
|
{ prop1 = function() {}, prop2 = function namedProp2() {} }
|
|
test(prop1, "prop1", "function() {}");
|
|
test(prop2, "namedProp2", "function namedProp2() {}");
|
|
|
|
section = "bound destructuring assignment";
|
|
{
|
|
let o = {}
|
|
let bound1 = prop1.bind(o);
|
|
test(bound1, "bound prop1", "function prop1() { [native code] }");
|
|
|
|
let bound2 = prop2.bind(o);
|
|
test(bound2, "bound namedProp2", "function namedProp2() { [native code] }");
|
|
}
|
|
}
|
|
|
|
section = "dynamically created function";
|
|
{
|
|
let dynamic1 = new Function("");
|
|
test(dynamic1, "anonymous", "function anonymous() {}");
|
|
|
|
let dynamic2 = new Function("");
|
|
dynamic2.name = "Goo2";
|
|
test(dynamic2, "anonymous", "function anonymous() {}");
|
|
|
|
section = "bound dynamically created function";
|
|
{
|
|
let o = {}
|
|
let bound1 = dynamic1.bind(o);
|
|
test(bound1, "bound anonymous", "function anonymous() { [native code] }");
|
|
|
|
let bound2 = dynamic2.bind(o);
|
|
test(bound2, "bound anonymous", "function anonymous() { [native code] }");
|
|
}
|
|
}
|
|
|
|
section = "JSBoundSlotBaseFunction";
|
|
{
|
|
if (typeof document !== "undefined") {
|
|
let desc = Object.getOwnPropertyDescriptor(document, "location");
|
|
test(desc.get, "get location", "function location() { [native code] }");
|
|
test(desc.set, "set location", "function location() { [native code] }");
|
|
|
|
section = "bound JSBoundSlotBaseFunction";
|
|
{
|
|
let o = {}
|
|
let bound1 = desc.get.bind(o);
|
|
test(bound1, "bound get location", "function get location() { [native code] }");
|
|
|
|
let bound2 = desc.set.bind(o);
|
|
test(bound2, "bound set location", "function set location() { [native code] }");
|
|
}
|
|
}
|
|
}
|
|
|
|
section = "get/set function";
|
|
{
|
|
let o = { get foo() {}, set foo(x){} };
|
|
let desc = Object.getOwnPropertyDescriptor(o, "foo");
|
|
test(desc.get, "get foo", "function() {}");
|
|
test(desc.set, "set foo", "function(x) {}");
|
|
|
|
let o1 = { get "bar"() {}, set "bar"(x){} };
|
|
let desc1 = Object.getOwnPropertyDescriptor(o1, "bar");
|
|
test(desc1.get, "get bar", "function() {}");
|
|
test(desc1.set, "set bar", "function(x) {}");
|
|
|
|
let o2 = { get 100() {}, set 100(x){} };
|
|
let desc2 = Object.getOwnPropertyDescriptor(o2, 100);
|
|
test(desc2.get, "get ", "function() {}");
|
|
test(desc2.set, "set ", "function(x) {}");
|
|
|
|
let o3 = { get [100]() {}, set [100](x){} };
|
|
let desc3 = Object.getOwnPropertyDescriptor(o3, 100);
|
|
test(desc3.get, "get 100", "function() {}");
|
|
test(desc3.set, "set 100", "function(x) {}");
|
|
|
|
section = "bound get/set function";
|
|
{
|
|
let bound1;
|
|
let bound2;
|
|
|
|
bound1 = desc.get.bind(o);
|
|
test(bound1, "bound get foo", "function get foo() { [native code] }");
|
|
bound2 = desc.set.bind(o);
|
|
test(bound2, "bound set foo", "function set foo() { [native code] }");
|
|
|
|
bound1 = desc1.get.bind(o);
|
|
test(bound1, "bound get bar", "function get bar() { [native code] }");
|
|
bound2 = desc1.set.bind(o);
|
|
test(bound2, "bound set bar", "function set bar() { [native code] }");
|
|
|
|
bound1 = desc2.get.bind(o);
|
|
test(bound1, "bound get ", "function get () { [native code] }");
|
|
bound2 = desc2.set.bind(o);
|
|
test(bound2, "bound set ", "function set () { [native code] }");
|
|
|
|
bound1 = desc3.get.bind(o);
|
|
test(bound1, "bound get 100", "function get 100() { [native code] }");
|
|
bound2 = desc3.set.bind(o);
|
|
test(bound2, "bound set 100", "function set 100() { [native code] }");
|
|
}
|
|
}
|
|
|
|
// https://tc39.github.io/ecma262/#sec-function.prototype.bind
|
|
// 9. Let targetName be ? Get(Target, "name").
|
|
// 10. If Type(targetName) is not String, let targetName be the empty string.
|
|
// 11. Perform SetFunctionName(F, targetName, "bound").
|
|
section = "bound functions with non-string names";
|
|
{
|
|
let foo = function() {};
|
|
let bound;
|
|
|
|
function setName(func, newName) {
|
|
Object.defineProperty(func, "name", { writable:true });
|
|
func.name = newName;
|
|
Object.defineProperty(func, "name", { writable:false });
|
|
}
|
|
|
|
setName(foo, undefined);
|
|
test(foo, undefined, "function() {}");
|
|
bound = foo.bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
|
|
setName(foo, null);
|
|
test(foo, null, "function() {}");
|
|
bound = foo.bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
|
|
setName(foo, true);
|
|
test(foo, true, "function() {}");
|
|
bound = foo.bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
|
|
setName(foo, false);
|
|
test(foo, false, "function() {}");
|
|
bound = foo.bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
|
|
setName(foo, 1234.567);
|
|
test(foo, 1234.567, "function() {}");
|
|
bound = foo.bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
|
|
let anonSym = Symbol();
|
|
setName(foo, anonSym);
|
|
test(foo, anonSym, "function() {}");
|
|
bound = foo.bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
|
|
let sym = Symbol("baz");
|
|
setName(foo, sym);
|
|
test(foo, sym, "function() {}");
|
|
bound = foo.bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
}
|
|
|
|
section = "Object computed non-symbol anonymous class property";
|
|
(function() {
|
|
let values = nonSymbolValues;
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]: class {},
|
|
}
|
|
test(o[value], toString(value), "class {}");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound " + toString(value), "function " + toString(value) + "() { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i]);
|
|
})();
|
|
|
|
section = "Object computed non-symbol named class property";
|
|
(function() {
|
|
let values = nonSymbolValues;
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]: class bar {},
|
|
}
|
|
test(o[value], "bar", "class bar {}");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound bar", "function bar() { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i]);
|
|
})();
|
|
|
|
section = "Object computed symbol anonymous class property";
|
|
(function() {
|
|
let values = symbolValues;
|
|
function runTest(value, expectedName) {
|
|
let o = {
|
|
[value]: class {},
|
|
}
|
|
test(o[value], expectedName, "class {}");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound " + expectedName, "function " + expectedName + "() { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i].v, values[i].name);
|
|
})();
|
|
|
|
section = "Object computed symbol named class property";
|
|
(function() {
|
|
let values = symbolValues;
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]: class bar {},
|
|
}
|
|
test(o[value], "bar", "class bar {}");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound bar", "function bar() { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i].v);
|
|
})();
|
|
|
|
section = "Object computed non-symbol anonymous class (with name method) property";
|
|
(function() {
|
|
let values = nonSymbolValues;
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]: class { static name(){} },
|
|
}
|
|
shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
|
|
shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class { static name(){} }");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i]);
|
|
})();
|
|
|
|
section = "Object computed non-symbol named class (with name method) property";
|
|
(function() {
|
|
let values = nonSymbolValues;
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]: class bar { static name(){} },
|
|
}
|
|
shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
|
|
shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class bar { static name(){} }");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i]);
|
|
})();
|
|
|
|
section = "Object computed symbol anonymous class (with name method) property";
|
|
(function() {
|
|
let values = symbolValues;
|
|
function runTest(value, expectedName) {
|
|
let o = {
|
|
[value]: class { static name(){} },
|
|
}
|
|
shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
|
|
shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class { static name(){} }");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i].v, values[i].name);
|
|
})();
|
|
|
|
section = "Object computed symbol named class (with name method) property";
|
|
(function() {
|
|
let values = symbolValues;
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]: class bar { static name(){} },
|
|
}
|
|
shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
|
|
shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class bar { static name(){} }");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i].v);
|
|
})();
|
|
|
|
section = "Object computed non-symbol anonymous class (with computed name method) property";
|
|
(function() {
|
|
let values = nonSymbolValues;
|
|
let nameStr = "name";
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]: class { static [nameStr](){} },
|
|
}
|
|
shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
|
|
shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class { static [nameStr](){} }");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i]);
|
|
})();
|
|
|
|
section = "Object computed non-symbol named class (with computed name method) property";
|
|
(function() {
|
|
let values = nonSymbolValues;
|
|
let nameStr = "name";
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]: class bar { static [nameStr](){} },
|
|
}
|
|
shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
|
|
shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class bar { static [nameStr](){} }");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i]);
|
|
})();
|
|
|
|
section = "Object computed symbol anonymous class (with computed name method) property";
|
|
(function() {
|
|
let values = symbolValues;
|
|
let nameStr = "name";
|
|
function runTest(value, expectedName) {
|
|
let o = {
|
|
[value]: class { static [nameStr](){} },
|
|
}
|
|
shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
|
|
shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class { static [nameStr](){} }");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i].v, values[i].name);
|
|
})();
|
|
|
|
section = "Object computed symbol named class (with computed name method) property";
|
|
(function() {
|
|
let values = symbolValues;
|
|
let nameStr = "name";
|
|
function runTest(value) {
|
|
let o = {
|
|
[value]: class bar { static [nameStr](){} },
|
|
}
|
|
shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
|
|
shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class bar { static [nameStr](){} }");
|
|
|
|
let bound = o[value].bind({});
|
|
test(bound, "bound ", "function () { [native code] }");
|
|
}
|
|
for (var i = 0; i < values.length; i++)
|
|
runTest(values[i].v);
|
|
})();
|
|
|
|
if (failureCount)
|
|
throw Error("Found " + failureCount + " failures:\n" + failures);
|