// |reftest| skip-if(!Object.prototype.toSource)
var BUGNUMBER = 1317400;
var summary = "Function string representation in Object.prototype.toSource" ;
print(BUGNUMBER + ": " + summary);
// Methods.
assertEq(({ foo(){} }).toSource(),
"({foo(){}})" );
assertEq(({ *foo(){} }).toSource(),
"({*foo(){}})" );
assertEq(({ async foo(){} }).toSource(),
"({async foo(){}})" );
assertEq(({ 1(){} }).toSource(),
"({1(){}})" );
// Methods with more spacing.
// Spacing is kept.
assertEq(({ foo (){} }).toSource(),
"({foo (){}})" );
assertEq(({ foo () {} }).toSource(),
"({foo () {}})" );
// Methods with computed name.
// Method syntax is composed.
let name = "foo" ;
assertEq(({ [name](){} }).toSource(),
"({foo(){}})" );
assertEq(({ *[name](){} }).toSource(),
"({*foo(){}})" );
assertEq(({ async [name](){} }).toSource(),
"({async foo(){}})" );
assertEq(({ [ Symbol.iterator ](){} }).toSource(),
"({[Symbol.iterator](){}})" );
// Accessors.
assertEq(({ get foo(){} }).toSource(),
"({get foo(){}})" );
assertEq(({ set foo(v){} }).toSource(),
"({set foo(v){}})" );
// Accessors with computed name.
// Method syntax is composed.
assertEq(({ get [name](){} }).toSource(),
"({get foo(){}})" );
assertEq(({ set [name](v){} }).toSource(),
"({set foo(v){}})" );
assertEq(({ get [ Symbol.iterator ](){} }).toSource(),
"({get [Symbol.iterator](){}})" );
assertEq(({ set [ Symbol.iterator ](v){} }).toSource(),
"({set [Symbol.iterator](v){}})" );
// Getter and setter with same name.
// Getter always comes before setter.
assertEq(({ get foo(){}, set foo(v){} }).toSource(),
"({get foo(){}, set foo(v){}})" );
assertEq(({ set foo(v){}, get foo(){} }).toSource(),
"({get foo(){}, set foo(v){}})" );
// Normal properties.
assertEq(({ foo: function (){} }).toSource(),
"({foo:(function(){})})" );
assertEq(({ foo: function bar(){} }).toSource(),
"({foo:(function bar(){})})" );
assertEq(({ foo: function *(){} }).toSource(),
"({foo:(function*(){})})" );
assertEq(({ foo: async function (){} }).toSource(),
"({foo:(async function(){})})" );
// Normal properties with computed name.
assertEq(({ [ Symbol.iterator ]: function (){} }).toSource(),
"({[Symbol.iterator]:(function(){})})" );
// Dynamically defined properties with function expression.
// Never become a method syntax.
let obj = {};
obj.foo = function () {};
assertEq(obj.toSource(),
"({foo:(function() {})})" );
obj = {};
Object.defineProperty(obj, "foo" , {value: function () {}});
assertEq(obj.toSource(),
"({})" );
obj = {};
Object.defineProperty(obj, "foo" , {value: function () {}, enumerable: true });
assertEq(obj.toSource(),
"({foo:(function() {})})" );
obj = {};
Object.defineProperty(obj, "foo" , {value: function bar() {}, enumerable: true });
assertEq(obj.toSource(),
"({foo:(function bar() {})})" );
obj = {};
Object.defineProperty(obj, Symbol.iterator, {value: function () {}, enumerable: true });
assertEq(obj.toSource(),
"({[Symbol.iterator]:(function() {})})" );
// Dynamically defined property with other object's method.
// Method syntax is composed.
let method = ({foo() {}}).foo;
obj = {};
Object.defineProperty(obj, "foo" , {value: method, enumerable: true });
assertEq(obj.toSource(),
"({foo() {}})" );
obj = {};
Object.defineProperty(obj, "bar" , {value: method, enumerable: true });
assertEq(obj.toSource(),
"({bar() {}})" );
method = ({*foo() {}}).foo;
obj = {};
Object.defineProperty(obj, "bar" , {value: method, enumerable: true });
assertEq(obj.toSource(),
"({*bar() {}})" );
method = ({async foo() {}}).foo;
obj = {};
Object.defineProperty(obj, "bar" , {value: method, enumerable: true });
assertEq(obj.toSource(),
"({async bar() {}})" );
// Dynamically defined accessors.
// Accessor syntax is composed.
obj = {};
Object.defineProperty(obj, "foo" , {get: function () {}, enumerable: true });
assertEq(obj.toSource(),
"({get foo() {}})" );
obj = {};
Object.defineProperty(obj, "foo" , {set: function () {}, enumerable: true });
assertEq(obj.toSource(),
"({set foo() {}})" );
obj = {};
Object.defineProperty(obj, Symbol.iterator, {get: function () {}, enumerable: true });
assertEq(obj.toSource(),
"({get [Symbol.iterator]() {}})" );
obj = {};
Object.defineProperty(obj, Symbol.iterator, {set: function () {}, enumerable: true });
assertEq(obj.toSource(),
"({set [Symbol.iterator]() {}})" );
// Dynamically defined accessors with other object's accessors.
// Accessor syntax is composed.
let accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo" ).get;
obj = {};
Object.defineProperty(obj, "foo" , {get: accessor, enumerable: true });
assertEq(obj.toSource(),
"({get foo() {}})" );
accessor = Object.getOwnPropertyDescriptor({ get bar() {} }, "bar" ).get;
obj = {};
Object.defineProperty(obj, "foo" , {get: accessor, enumerable: true });
assertEq(obj.toSource(),
"({get foo() {}})" );
accessor = Object.getOwnPropertyDescriptor({ set foo(v) {} }, "foo" ).set;
obj = {};
Object.defineProperty(obj, "foo" , {get: accessor, enumerable: true });
assertEq(obj.toSource(),
"({get foo(v) {}})" );
accessor = Object.getOwnPropertyDescriptor({ set bar(v) {} }, "bar" ).set;
obj = {};
Object.defineProperty(obj, "foo" , {get: accessor, enumerable: true });
assertEq(obj.toSource(),
"({get foo(v) {}})" );
accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo" ).get;
obj = {};
Object.defineProperty(obj, "foo" , {set: accessor, enumerable: true });
assertEq(obj.toSource(),
"({set foo() {}})" );
accessor = Object.getOwnPropertyDescriptor({ get bar() {} }, "bar" ).get;
obj = {};
Object.defineProperty(obj, "foo" , {set: accessor, enumerable: true });
assertEq(obj.toSource(),
"({set foo() {}})" );
accessor = Object.getOwnPropertyDescriptor({ set foo(v) {} }, "foo" ).set;
obj = {};
Object.defineProperty(obj, "foo" , {set: accessor, enumerable: true });
assertEq(obj.toSource(),
"({set foo(v) {}})" );
accessor = Object.getOwnPropertyDescriptor({ set bar(v) {} }, "bar" ).set;
obj = {};
Object.defineProperty(obj, "foo" , {set: accessor, enumerable: true });
assertEq(obj.toSource(),
"({set foo(v) {}})" );
// Methods with proxy.
// Treated as normal property.
method = ({foo() {}}).foo;
let handler = {
get(that, name) {
if (name == "toSource" ) {
return function () {
return that.toSource();
};
}
return that[name];
}
};
let proxy = new Proxy(method, handler);
obj = {};
Object.defineProperty(obj, "foo" , {value: proxy, enumerable: true });
assertEq(obj.toSource(),
"({foo:foo() {}})" );
// Accessors with proxy.
// Accessor syntax is composed.
accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo" ).get;
proxy = new Proxy(accessor, handler);
obj = {};
Object.defineProperty(obj, "foo" , {get: proxy, enumerable: true });
assertEq(obj.toSource(),
"({get foo() {}})" );
obj = {};
Object.defineProperty(obj, "foo" , {set: proxy, enumerable: true });
assertEq(obj.toSource(),
"({set foo() {}})" );
// Methods from other global.
// Treated as normal property in the cross-compartment case.
let g = newGlobal();
method = g.eval("({ foo() {} }).foo" );
obj = {};
Object.defineProperty(obj, "foo" , {value: method, enumerable: true });
assertEq((obj.toSource() === "({foo:foo() {}})" ||
obj.toSource() === "({foo() {}})" ),
true );
// Accessors from other global.
// Accessor syntax is composed.
accessor = g.eval("Object.getOwnPropertyDescriptor({ get foo() {} }, 'foo').get" );
obj = {};
Object.defineProperty(obj, "foo" , {get: accessor, enumerable: true });
assertEq(obj.toSource(),
"({get foo() {}})" );
accessor = g.eval("Object.getOwnPropertyDescriptor({ get bar() {} }, 'bar').get" );
obj = {};
Object.defineProperty(obj, "foo" , {get: accessor, enumerable: true });
assertEq(obj.toSource(),
"({get foo() {}})" );
accessor = g.eval("Object.getOwnPropertyDescriptor({ set foo(v) {} }, 'foo').set" );
obj = {};
Object.defineProperty(obj, "foo" , {get: accessor, enumerable: true });
assertEq(obj.toSource(),
"({get foo(v) {}})" );
accessor = g.eval("Object.getOwnPropertyDescriptor({ set bar(v) {} }, 'bar').set" );
obj = {};
Object.defineProperty(obj, "foo" , {get: accessor, enumerable: true });
assertEq(obj.toSource(),
"({get foo(v) {}})" );
accessor = g.eval("Object.getOwnPropertyDescriptor({ get foo() {} }, 'foo').get" );
obj = {};
Object.defineProperty(obj, "foo" , {set: accessor, enumerable: true });
assertEq(obj.toSource(),
"({set foo() {}})" );
accessor = g.eval("Object.getOwnPropertyDescriptor({ get bar() {} }, 'bar').get" );
obj = {};
Object.defineProperty(obj, "foo" , {set: accessor, enumerable: true });
assertEq(obj.toSource(),
"({set foo() {}})" );
accessor = g.eval("Object.getOwnPropertyDescriptor({ set foo(v) {} }, 'foo').set" );
obj = {};
Object.defineProperty(obj, "foo" , {set: accessor, enumerable: true });
assertEq(obj.toSource(),
"({set foo(v) {}})" );
accessor = g.eval("Object.getOwnPropertyDescriptor({ set bar(v) {} }, 'bar').set" );
obj = {};
Object.defineProperty(obj, "foo" , {set: accessor, enumerable: true });
assertEq(obj.toSource(),
"({set foo(v) {}})" );
// **** Some weird cases ****
// Accessors with generator or async.
obj = {};
Object.defineProperty(obj, "foo" , {get: function *() {}, enumerable: true });
assertEq(obj.toSource(),
"({get foo() {}})" );
obj = {};
Object.defineProperty(obj, "foo" , {set: async function () {}, enumerable: true });
assertEq(obj.toSource(),
"({set foo() {}})" );
// Modified toSource.
obj = { foo() {} };
obj.foo.toSource = () => "hello" ;
assertEq(obj.toSource(),
"({hello})" );
obj = { foo() {} };
obj.foo.toSource = () => "bar() {}" ;
assertEq(obj.toSource(),
"({bar() {}})" );
// Modified toSource with different method name.
obj = {};
Object.defineProperty(obj, "foo" , {value: function bar() {}, enumerable: true });
obj.foo.toSource = () => "hello" ;
assertEq(obj.toSource(),
"({foo:hello})" );
obj = {};
Object.defineProperty(obj, "foo" , {value: function * bar() {}, enumerable: true });
obj.foo.toSource = () => "hello" ;
assertEq(obj.toSource(),
"({foo:hello})" );
obj = {};
Object.defineProperty(obj, "foo" , {value: async function bar() {}, enumerable: true });
obj.foo.toSource = () => "hello" ;
assertEq(obj.toSource(),
"({foo:hello})" );
if (typeof reportCompare === "function" )
reportCompare(true , true );
Messung V0.5 C=90 H=99 G=94
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland