blob: b4bcaf945916616648954718f86407f3413127aa [file] [log] [blame]
// 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);