Commit ddb782dc authored by rossberg@chromium.org's avatar rossberg@chromium.org

Implement Object.getOwnPropertyDescriptor for proxies.

Fix bug in compilation of calls with proxy receivers.

R=kmillikin@chromium.org,ager@chromium.org
BUG=
TEST=

Review URL: http://codereview.chromium.org/7237050

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8630 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5c57d0d6
......@@ -206,6 +206,7 @@ class LookupResult BASE_EMBEDDED {
lookup_type_ = HANDLER_TYPE;
holder_ = NULL;
details_ = PropertyDetails(NONE, HANDLER);
cacheable_ = false;
}
void InterceptorResult(JSObject* holder) {
......
......@@ -595,7 +595,7 @@ function GetProperty(obj, p) {
var descriptor = %_CallFunction(handler, p, getProperty);
if (IS_UNDEFINED(descriptor)) return descriptor;
var desc = ToCompletePropertyDescriptor(descriptor);
if (!desc.configurable) {
if (!desc.isConfigurable()) {
throw MakeTypeError("proxy_prop_not_configurable",
[handler, "getPropertyDescriptor", p, descriptor]);
}
......@@ -624,6 +624,23 @@ function HasProperty(obj, p) {
// ES5 section 8.12.1.
function GetOwnProperty(obj, p) {
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var getOwnProperty = handler.getOwnPropertyDescriptor;
if (IS_UNDEFINED(getOwnProperty)) {
throw MakeTypeError("handler_trap_missing",
[handler, "getOwnPropertyDescriptor"]);
}
var descriptor = %_CallFunction(handler, p, getOwnProperty);
if (IS_UNDEFINED(descriptor)) return descriptor;
var desc = ToCompletePropertyDescriptor(descriptor);
if (!desc.isConfigurable()) {
throw MakeTypeError("proxy_prop_not_configurable",
[handler, "getOwnPropertyDescriptor", p, descriptor]);
}
return desc;
}
// GetOwnProperty returns an array indexed by the constants
// defined in macros.py.
// If p is not a property on obj undefined is returned.
......@@ -836,7 +853,8 @@ function ObjectGetPrototypeOf(obj) {
// ES5 section 15.2.3.3
function ObjectGetOwnPropertyDescriptor(obj, p) {
if (!IS_SPEC_OBJECT(obj))
throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyDescriptor"]);
throw MakeTypeError("obj_ctor_property_non_object",
["getOwnPropertyDescriptor"]);
var desc = GetOwnProperty(obj, p);
return FromPropertyDescriptor(desc);
}
......
......@@ -35,7 +35,6 @@ function TestGet(handler) {
var o = Proxy.create(handler)
assertEquals(42, o.a)
assertEquals(42, o["b"])
// assertEquals(Object.getOwnPropertyDescriptor(o, "b").value, 42)
}
TestGet({
......@@ -69,6 +68,64 @@ TestGet(Proxy.create({
}))
function TestGetCall(handler) {
var p = Proxy.create(handler)
assertEquals(55, p.f())
assertEquals(55, p.f("unused", "arguments"))
assertEquals(55, p.f.call(p))
assertEquals(55, p.withargs(45, 5))
assertEquals(55, p.withargs.call(p, 11, 22))
assertEquals("6655", "66" + p) // calls p.toString
}
TestGetCall({
get: function(r, k) { return function() { return 55 } }
})
TestGetCall({
get: function(r, k) { return this.get2(r, k) },
get2: function(r, k) { return function() { return 55 } }
})
TestGetCall({
getPropertyDescriptor: function(k) {
return {value: function() { return 55 }}
}
})
TestGetCall({
getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
getPropertyDescriptor2: function(k) {
return {value: function() { return 55 }}
}
})
TestGetCall({
getPropertyDescriptor: function(k) {
return {get value() { return function() { return 55 } }}
}
})
TestGetCall({
get: undefined,
getPropertyDescriptor: function(k) {
return {value: function() { return 55 }}
}
})
TestGetCall({
get: function(r, k) {
if (k == "gg") {
return function() { return 55 }
} else if (k == "withargs") {
return function(n, m) { return n + m * 2 }
} else {
return function() { return this.gg() }
}
}
})
TestGetCall(Proxy.create({
get: function(pr, pk) {
return function(r, k) { return function() { return 55 } }
}
}))
// Setters.
......@@ -82,9 +139,6 @@ function TestSet(handler) {
assertEquals(43, o["b"] = 43)
assertEquals("b", key)
assertEquals(43, val)
// assertTrue(Object.defineProperty(o, "c", {value: 44}))
// assertEquals("c", key)
// assertEquals(44, val)
}
TestSet({
......@@ -149,7 +203,7 @@ TestSet(Proxy.create({
// Property definition (Object.defineProperty).
// Property definition (Object.defineProperty and Object.defineProperties).
var key
var desc
......@@ -193,7 +247,7 @@ function TestDefine(handler) {
assertEquals("zzz", key)
assertEquals(0, Object.getOwnPropertyNames(desc).length)
// This test requires [s in proxy] to be implemented first.
// TODO(rossberg): This test requires [s in proxy] to be implemented first.
// var d = Proxy.create({
// get: function(r, k) { return (k === "value") ? 77 : void 0 },
// getOwnPropertyNames: function() { return ["value"] }
......@@ -204,6 +258,20 @@ function TestDefine(handler) {
// assertEquals("p", key)
// assertEquals(1, Object.getOwnPropertyNames(desc).length)
// assertEquals(77, desc.value)
var props = {
'bla': {},
blub: {get: function() { return true }},
'': {get value() { return 20 }},
last: {value: 21, configurable: true, mine: "eyes"}
}
Object.defineProperty(props, "hidden", {value: "hidden", enumerable: false})
assertEquals(o, Object.defineProperties(o, props))
assertEquals("last", key)
assertEquals(2, Object.getOwnPropertyNames(desc).length)
assertEquals(21, desc.value)
assertEquals(true, desc.configurable)
assertEquals(undefined, desc.mine) // Arguably a bug in the spec...
}
TestDefine({
......@@ -221,6 +289,44 @@ TestDefine(Proxy.create({
// Property descriptors (Object.getOwnPropertyDescriptor).
function TestDescriptor(handler) {
var o = Proxy.create(handler)
var descs = [
{configurable: true},
{value: 34, enumerable: true, configurable: true},
{value: 3, writable: false, mine: "eyes", configurable: true},
{get value() { return 20 }, get configurable() { return true }},
{get: function() { "get" }, set: function() { "set" }, configurable: true}
]
for (var i = 0; i < descs.length; ++i) {
assertEquals(o, Object.defineProperty(o, i, descs[i]))
var desc = Object.getOwnPropertyDescriptor(o, i)
for (p in descs[i]) {
// TODO(rossberg): Ignore user attributes as long as the spec isn't
// fixed suitably.
if (p != "mine") assertEquals(descs[i][p], desc[p])
}
assertEquals(undefined, Object.getOwnPropertyDescriptor(o, "absent"))
}
}
TestDescriptor({
defineProperty: function(k, d) { this["__" + k] = d; return true },
getOwnPropertyDescriptor: function(k) { return this["__" + k] }
})
TestDescriptor({
defineProperty: function(k, d) { this["__" + k] = d; return true },
getOwnPropertyDescriptor: function(k) {
return this.getOwnPropertyDescriptor2(k)
},
getOwnPropertyDescriptor2: function(k) { return this["__" + k] }
})
// Comparison.
function TestComparison(eq) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment