640 lines
16 KiB
Go
640 lines
16 KiB
Go
package otto
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestObject_(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
object := newObject(nil, "")
|
|
is(object != nil, true)
|
|
|
|
object.put("xyzzy", toValue("Nothing happens."), true)
|
|
is(object.get("xyzzy"), "Nothing happens.")
|
|
|
|
test(`
|
|
var abc = Object.getOwnPropertyDescriptor(Object, "prototype");
|
|
[ [ typeof Object.prototype, abc.writable, abc.enumerable, abc.configurable ],
|
|
];
|
|
`, "object,false,false,false")
|
|
})
|
|
}
|
|
|
|
func TestStringObject(t *testing.T) {
|
|
tt(t, func() {
|
|
object := New().runtime.newStringObject(toValue("xyzzy"))
|
|
is(object.get("1"), "y")
|
|
is(object.get("10"), "undefined")
|
|
is(object.get("2"), "z")
|
|
})
|
|
}
|
|
|
|
func TestObject_getPrototypeOf(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`
|
|
abc = {};
|
|
def = Object.getPrototypeOf(abc);
|
|
ghi = Object.getPrototypeOf(def);
|
|
[abc,def,ghi,ghi+""];
|
|
`, "[object Object],[object Object],,null")
|
|
|
|
test(`
|
|
abc = Object.getOwnPropertyDescriptor(Object, "getPrototypeOf");
|
|
[ abc.value === Object.getPrototypeOf, abc.writable, abc.enumerable, abc.configurable ];
|
|
`, "true,true,false,true")
|
|
})
|
|
}
|
|
|
|
func TestObject_new(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`
|
|
[ new Object("abc"), new Object(2+2) ];
|
|
`, "abc,4")
|
|
})
|
|
}
|
|
|
|
func TestObject_create(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`raise: Object.create()`, "TypeError")
|
|
|
|
test(`
|
|
var abc = Object.create(null)
|
|
var def = Object.create({x: 10, y: 20})
|
|
var ghi = Object.create(Object.prototype)
|
|
|
|
var jkl = Object.create({x: 10, y: 20}, {
|
|
z: {
|
|
value: 30,
|
|
writable: true
|
|
},
|
|
// sum: {
|
|
// get: function() {
|
|
// return this.x + this.y + this.z
|
|
// }
|
|
// }
|
|
});
|
|
[ abc.prototype, def.x, def.y, ghi, jkl.x, jkl.y, jkl.z ]
|
|
`, ",10,20,[object Object],10,20,30")
|
|
|
|
test(`
|
|
var properties = {};
|
|
Object.defineProperty(properties, "abc", {
|
|
value: {},
|
|
enumerable: false
|
|
});
|
|
var mno = Object.create({}, properties);
|
|
mno.hasOwnProperty("abc");
|
|
`, false)
|
|
})
|
|
}
|
|
|
|
func TestObject_toLocaleString(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`
|
|
({}).toLocaleString();
|
|
`, "[object Object]")
|
|
|
|
test(`
|
|
object = {
|
|
toString: function() {
|
|
return "Nothing happens.";
|
|
}
|
|
};
|
|
object.toLocaleString();
|
|
`, "Nothing happens.")
|
|
})
|
|
}
|
|
|
|
func TestObject_isExtensible(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`raise:
|
|
Object.isExtensible();
|
|
`, "TypeError")
|
|
|
|
// FIXME terst, Why raise?
|
|
test(`raise:
|
|
Object.isExtensible({});
|
|
`, true)
|
|
|
|
test(`Object.isExtensible.length`, 1)
|
|
test(`Object.isExtensible.prototype`, "undefined")
|
|
})
|
|
}
|
|
|
|
func TestObject_preventExtensions(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`raise:
|
|
Object.preventExtensions()
|
|
`, "TypeError")
|
|
|
|
test(`raise:
|
|
var abc = { def: true };
|
|
var ghi = Object.preventExtensions(abc);
|
|
[ ghi.def === true, Object.isExtensible(abc), Object.isExtensible(ghi) ];
|
|
`, "true,false,false")
|
|
|
|
test(`
|
|
var abc = new String();
|
|
var def = Object.isExtensible(abc);
|
|
Object.preventExtensions(abc);
|
|
var ghi = false;
|
|
try {
|
|
Object.defineProperty(abc, "0", { value: "~" });
|
|
} catch (err) {
|
|
ghi = err instanceof TypeError;
|
|
}
|
|
[ def, ghi, abc.hasOwnProperty("0"), typeof abc[0] ];
|
|
`, "true,true,false,undefined")
|
|
|
|
test(`Object.preventExtensions.length`, 1)
|
|
test(`Object.preventExtensions.prototype`, "undefined")
|
|
})
|
|
}
|
|
|
|
func TestObject_isSealed(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`Object.isSealed.length`, 1)
|
|
test(`Object.isSealed.prototype`, "undefined")
|
|
})
|
|
}
|
|
|
|
func TestObject_seal(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`raise: Object.seal()`, "TypeError")
|
|
|
|
test(`
|
|
var abc = {a:1,b:1,c:3};
|
|
var sealed = Object.isSealed(abc);
|
|
Object.seal(abc);
|
|
[sealed, Object.isSealed(abc)];
|
|
`, "false,true")
|
|
|
|
test(`
|
|
var abc = {a:1,b:1,c:3};
|
|
var sealed = Object.isSealed(abc);
|
|
var caught = false;
|
|
Object.seal(abc);
|
|
abc.b = 5;
|
|
Object.defineProperty(abc, "a", {value:4});
|
|
try {
|
|
Object.defineProperty(abc, "a", {value:42,enumerable:false});
|
|
} catch (e) {
|
|
caught = e instanceof TypeError;
|
|
}
|
|
[sealed, Object.isSealed(abc), caught, abc.a, abc.b];
|
|
`, "false,true,true,4,5")
|
|
|
|
test(`Object.seal.length`, 1)
|
|
test(`Object.seal.prototype`, "undefined")
|
|
})
|
|
}
|
|
|
|
func TestObject_isFrozen(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`raise: Object.isFrozen()`, "TypeError")
|
|
test(`Object.isFrozen(Object.preventExtensions({a:1}))`, false)
|
|
test(`Object.isFrozen({})`, false)
|
|
|
|
test(`
|
|
var abc = {};
|
|
Object.defineProperty(abc, "def", {
|
|
value: "def",
|
|
writable: true,
|
|
configurable: false
|
|
});
|
|
Object.preventExtensions(abc);
|
|
!Object.isFrozen(abc);
|
|
`, true)
|
|
|
|
test(`Object.isFrozen.length`, 1)
|
|
test(`Object.isFrozen.prototype`, "undefined")
|
|
})
|
|
}
|
|
|
|
func TestObject_freeze(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`raise: Object.freeze()`, "TypeError")
|
|
|
|
test(`
|
|
var abc = {a:1,b:2,c:3};
|
|
var frozen = Object.isFrozen(abc);
|
|
Object.freeze(abc);
|
|
abc.b = 5;
|
|
[frozen, Object.isFrozen(abc), abc.b];
|
|
`, "false,true,2")
|
|
|
|
test(`
|
|
var abc = {a:1,b:2,c:3};
|
|
var frozen = Object.isFrozen(abc);
|
|
var caught = false;
|
|
Object.freeze(abc);
|
|
abc.b = 5;
|
|
try {
|
|
Object.defineProperty(abc, "a", {value:4});
|
|
} catch (e) {
|
|
caught = e instanceof TypeError;
|
|
}
|
|
[frozen, Object.isFrozen(abc), caught, abc.a, abc.b];
|
|
`, "false,true,true,1,2")
|
|
|
|
test(`Object.freeze.length`, 1)
|
|
test(`Object.freeze.prototype`, "undefined")
|
|
})
|
|
}
|
|
|
|
func TestObject_defineProperty(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`
|
|
(function(abc, def, ghi){
|
|
Object.defineProperty(arguments, "0", {
|
|
enumerable: false
|
|
});
|
|
return true;
|
|
})(0, 1, 2);
|
|
`, true)
|
|
|
|
test(`
|
|
var abc = {};
|
|
abc.def = 3.14; // Default: writable: true, enumerable: true, configurable: true
|
|
|
|
Object.defineProperty(abc, "def", {
|
|
value: 42
|
|
});
|
|
|
|
var ghi = Object.getOwnPropertyDescriptor(abc, "def");
|
|
[ ghi.value, ghi.writable, ghi.enumerable, ghi.configurable ];
|
|
`, "42,true,true,true")
|
|
|
|
// Test that we handle the case of DefineOwnProperty
|
|
// where [[Writable]] is something but [[Value]] is not
|
|
test(`
|
|
var abc = [];
|
|
Object.defineProperty(abc, "0", { writable: false });
|
|
0 in abc;
|
|
`, true)
|
|
|
|
// Test that we handle the case of DefineOwnProperty
|
|
// where [[Writable]] is something but [[Value]] is not
|
|
// (and the property originally had something for [[Value]]
|
|
test(`
|
|
abc = {
|
|
def: 42
|
|
};
|
|
Object.defineProperty(abc, "def", { writable: false });
|
|
abc.def;
|
|
`, 42)
|
|
})
|
|
}
|
|
|
|
func TestObject_keys(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`Object.keys({ abc:undefined, def:undefined })`, "abc,def")
|
|
|
|
test(`
|
|
function abc() {
|
|
this.abc = undefined;
|
|
this.def = undefined;
|
|
}
|
|
Object.keys(new abc())
|
|
`, "abc,def")
|
|
|
|
test(`
|
|
function def() {
|
|
this.ghi = undefined;
|
|
}
|
|
def.prototype = new abc();
|
|
Object.keys(new def());
|
|
`, "ghi")
|
|
|
|
test(`
|
|
var ghi = Object.create(
|
|
{
|
|
abc: undefined,
|
|
def: undefined
|
|
},
|
|
{
|
|
ghi: { value: undefined, enumerable: true },
|
|
jkl: { value: undefined, enumerable: false }
|
|
}
|
|
);
|
|
Object.keys(ghi);
|
|
`, "ghi")
|
|
|
|
test(`
|
|
(function(abc, def, ghi){
|
|
return Object.keys(arguments)
|
|
})(undefined, undefined);
|
|
`, "0,1")
|
|
|
|
test(`
|
|
(function(abc, def, ghi){
|
|
return Object.keys(arguments)
|
|
})(undefined, undefined, undefined, undefined);
|
|
`, "0,1,2,3")
|
|
})
|
|
}
|
|
|
|
func TestObject_getOwnPropertyNames(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`Object.getOwnPropertyNames({ abc:undefined, def:undefined })`, "abc,def")
|
|
|
|
test(`
|
|
var ghi = Object.create(
|
|
{
|
|
abc: undefined,
|
|
def: undefined
|
|
},
|
|
{
|
|
ghi: { value: undefined, enumerable: true },
|
|
jkl: { value: undefined, enumerable: false }
|
|
}
|
|
);
|
|
Object.getOwnPropertyNames(ghi)
|
|
`, "ghi,jkl")
|
|
})
|
|
}
|
|
|
|
func TestObjectGetterSetter(t *testing.T) {
|
|
tt(t, func() {
|
|
test, _ := test()
|
|
|
|
test(`raise:
|
|
Object.create({}, {
|
|
abc: {
|
|
get: function(){
|
|
return "true";
|
|
},
|
|
writable: true
|
|
}
|
|
}).abc;
|
|
`, "TypeError")
|
|
|
|
test(`raise:
|
|
Object.create({}, {
|
|
abc: {
|
|
get: function(){
|
|
return "true";
|
|
},
|
|
writable: false
|
|
}
|
|
}).abc;
|
|
`, "TypeError")
|
|
|
|
test(`
|
|
Object.create({}, {
|
|
abc: {
|
|
get: function(){
|
|
return "true";
|
|
}
|
|
}
|
|
}).abc;
|
|
`, "true")
|
|
|
|
test(`
|
|
Object.create({xyz:true},{abc:{get:function(){return this.xyx}}}).abc;
|
|
Object.create({
|
|
xyz: true
|
|
}, {
|
|
abc: {
|
|
get: function(){
|
|
return this.xyz;
|
|
}
|
|
}
|
|
}).abc;
|
|
`, true)
|
|
|
|
test(`
|
|
var abc = false;
|
|
var def = Object.create({}, {
|
|
xyz: {
|
|
set: function(value) {
|
|
abc = value;
|
|
}
|
|
}
|
|
});
|
|
def.xyz = true;
|
|
[ abc ];
|
|
`, "true")
|
|
|
|
test(`
|
|
var abc = {};
|
|
Object.defineProperty(abc, "def", {
|
|
value: "xyzzy",
|
|
configurable: true
|
|
});
|
|
Object.preventExtensions(abc);
|
|
Object.defineProperty(abc, "def", {
|
|
get: function() {
|
|
return 5;
|
|
}
|
|
});
|
|
var def = Object.getOwnPropertyDescriptor(abc, "def");
|
|
[ abc.def, typeof def.get, typeof def.set, typeof def.value, def.configurable, def.enumerable, typeof def.writable ];
|
|
`, "5,function,undefined,undefined,true,false,undefined")
|
|
|
|
test(`
|
|
var abc = {};
|
|
Object.defineProperty(abc, "def", {
|
|
get: function() {
|
|
return 5;
|
|
}
|
|
configurable: true
|
|
});
|
|
Object.preventExtensions(abc);
|
|
Object.defineProperty(abc, "def", {
|
|
value: "xyzzy",
|
|
});
|
|
var def = Object.getOwnPropertyDescriptor(abc, "def");
|
|
[ abc.def, typeof def.get, typeof def.set, def.value, def.configurable, def.enumerable, def.writable ];
|
|
`, "xyzzy,undefined,undefined,xyzzy,true,false,false")
|
|
|
|
test(`
|
|
var abc = {};
|
|
|
|
function _get0() {
|
|
return 10;
|
|
}
|
|
|
|
function _set(value) {
|
|
abc.def = value;
|
|
}
|
|
|
|
Object.defineProperty(abc, "ghi", {
|
|
get: _get0,
|
|
set: _set,
|
|
configurable: true
|
|
});
|
|
|
|
function _get1() {
|
|
return 20;
|
|
}
|
|
|
|
Object.defineProperty(abc, "ghi", {
|
|
get: _get0
|
|
});
|
|
|
|
var descriptor = Object.getOwnPropertyDescriptor(abc, "ghi");
|
|
[ typeof descriptor.set ];
|
|
`, "function")
|
|
|
|
test(`raise:
|
|
var abc = [];
|
|
Object.defineProperty(abc, "length", {
|
|
get: function () {
|
|
return 2;
|
|
}
|
|
});
|
|
`, "TypeError")
|
|
|
|
test(`
|
|
var abc = {};
|
|
|
|
var getter = function() {
|
|
return 1;
|
|
}
|
|
|
|
Object.defineProperty(abc, "def", {
|
|
get: getter,
|
|
configurable: false
|
|
});
|
|
|
|
var jkl = undefined;
|
|
try {
|
|
Object.defineProperty(abc, "def", {
|
|
get: undefined
|
|
});
|
|
}
|
|
catch (err) {
|
|
jkl = err;
|
|
}
|
|
var ghi = Object.getOwnPropertyDescriptor(abc, "def");
|
|
[ jkl instanceof TypeError, ghi.get === getter, ghi.configurable, ghi.enumerable ];
|
|
`, "true,true,false,false")
|
|
|
|
test(`
|
|
var abc = {};
|
|
|
|
var getter = function() {
|
|
return 1;
|
|
};
|
|
|
|
Object.defineProperty(abc, "def", {
|
|
get: getter
|
|
});
|
|
|
|
Object.defineProperty(abc, "def", {
|
|
set: undefined
|
|
});
|
|
|
|
var ghi = Object.getOwnPropertyDescriptor(abc, "def");
|
|
[ ghi.get === getter, ghi.set === undefined, ghi.configurable, ghi.enumerable ];
|
|
`, "true,true,false,false")
|
|
|
|
test(`
|
|
var abc = {};
|
|
|
|
var getter = function() {
|
|
return 1;
|
|
};
|
|
|
|
Object.defineProperty(abc, "def", {
|
|
get: getter
|
|
});
|
|
|
|
var jkl = undefined;
|
|
try {
|
|
Object.defineProperty(abc, "def", {
|
|
set: function() {}
|
|
});
|
|
}
|
|
catch (err) {
|
|
jkl = err;
|
|
}
|
|
|
|
var ghi = Object.getOwnPropertyDescriptor(abc, "def");
|
|
[ jkl instanceof TypeError, ghi.get === getter, ghi.set, ghi.configurable, ghi.enumerable ];
|
|
`, "true,true,,false,false")
|
|
|
|
test(`
|
|
var abc = {};
|
|
var def = "xyzzy";
|
|
|
|
Object.defineProperty(abc, "ghi", {
|
|
get: undefined,
|
|
set: function(value) {
|
|
def = value;
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
|
|
var hasOwn = abc.hasOwnProperty("ghi");
|
|
var descriptor = Object.getOwnPropertyDescriptor(abc, "ghi");
|
|
|
|
[ hasOwn, typeof descriptor.get ];
|
|
`, "true,undefined")
|
|
|
|
test(`
|
|
var abc = "xyzzy";
|
|
Object.defineProperty(Array.prototype, "abc", {
|
|
get: function () {
|
|
return abc;
|
|
},
|
|
set: function (value) {
|
|
abc = value;
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
var def = [];
|
|
def.abc = 3.14159;
|
|
[ def.hasOwnProperty("abc"), def.abc, abc ];
|
|
`, "false,3.14159,3.14159")
|
|
})
|
|
}
|
|
|
|
func TestProperty(t *testing.T) {
|
|
tt(t, func() {
|
|
property := _property{}
|
|
property.writeOn()
|
|
is(property.writeSet(), true)
|
|
|
|
property.writeClear()
|
|
is(property.writeSet(), false)
|
|
|
|
property.writeOff()
|
|
is(property.writeSet(), true)
|
|
|
|
property.writeClear()
|
|
is(property.writeSet(), false)
|
|
})
|
|
}
|