Bug 789897 - Add scripting support + tests for isExtensible, preventExtensions traps. r=jwalden, r=jorendorff

--HG--
extra : rebase_source : 509886634ea50735b82c12d00e61840010359d74
This commit is contained in:
Eddy Bruel 2013-03-22 19:43:12 -07:00
parent afdc0a14d8
commit 0f0dc9862c
8 changed files with 94 additions and 2 deletions

View File

@ -24,5 +24,12 @@ var desc = {
enumerable: false,
configurable: true
};
Object.defineProperty(new Proxy(target, handler), 'foo', desc);
var p = new Proxy(target, handler);
Object.defineProperty(p, 'foo', desc);
assertEq(called, true);
assertEq(Object.isExtensible(target), true);
assertEq(Object.isExtensible(p), true);
Object.preventExtensions(target);
assertEq(Object.isExtensible(target), false);
assertEq(Object.isExtensible(p), false);

View File

@ -0,0 +1,4 @@
// Forward to the target if the trap is not defined
var target = {};
Object.preventExtensions(new Proxy(target, {}));
assertEq(Object.isExtensible(target), false);

View File

@ -0,0 +1,17 @@
/*
* Call the trap with the handler as the this value and the target as the first
* argument.
*/
var target = {};
var called = false;
var handler = {
preventExtensions: function (target1) {
assertEq(this, handler);
assertEq(target1, target);
Object.preventExtensions(target1);
called = true;
return true;
}
};
Object.preventExtensions(new Proxy(target, handler));
assertEq(called, true);

View File

@ -0,0 +1,10 @@
load(libdir + "asserts.js");
// Throw a TypeError if the trap reports an extensible object as non-extensible
assertThrowsInstanceOf(function () {
Object.preventExtensions(new Proxy({}, {
preventExtensions: function () {
return true;
}
}));
}, TypeError);

View File

@ -0,0 +1,10 @@
load(libdir + "asserts.js");
// Throw a TypeError if the object refuses to be made non-extensible
assertThrowsInstanceOf(function () {
Object.preventExtensions(new Proxy({}, {
preventExtensions: function () {
return false;
}
}));
}, TypeError);

View File

@ -235,7 +235,7 @@ MSG_DEF(JSMSG_UNUSED181, 181, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_BAD_GENERATOR_SEND, 182, 1, JSEXN_TYPEERR, "attempt to send {0} to newborn generator")
MSG_DEF(JSMSG_UNUSED183, 183, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED184, 184, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED185, 185, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_CANT_REPORT_AS_NON_EXTENSIBLE, 185, 0, JSEXN_TYPEERR, "proxy can't report an extensible object as non-extensible")
MSG_DEF(JSMSG_UNUSED186, 186, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED187, 187, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 188, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}")

View File

@ -1044,6 +1044,7 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler {
virtual ~ScriptedDirectProxyHandler();
/* ES5 Harmony fundamental proxy traps. */
virtual bool preventExtensions(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
PropertyDescriptor *desc, unsigned flags) MOZ_OVERRIDE;
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
@ -1612,6 +1613,48 @@ ScriptedDirectProxyHandler::~ScriptedDirectProxyHandler()
{
}
bool
ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
{
// step a
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step b
RootedObject target(cx, GetProxyTargetObject(proxy));
// step c
RootedValue trap(cx);
if (!JSObject::getProperty(cx, handler, handler, cx->names().preventExtensions, &trap))
return false;
// step d
if (trap.isUndefined())
return DirectProxyHandler::preventExtensions(cx, proxy);
// step e
Value argv[] = {
ObjectValue(*target)
};
RootedValue trapResult(cx);
if (!Invoke(cx, ObjectValue(*handler), trap, 1, argv, trapResult.address()))
return false;
// step f
bool success = ToBoolean(trapResult);
if (success) {
// step g
if (target->isExtensible()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_REPORT_AS_NON_EXTENSIBLE);
return false;
}
return true;
}
// step h
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CHANGE_EXTENSIBILITY);
return false;
}
// FIXME: Move to Proxy::getPropertyDescriptor once ScriptedIndirectProxy is removed
bool
ScriptedDirectProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,

View File

@ -114,6 +114,7 @@
macro(parseFloat, parseFloat, "parseFloat") \
macro(parseInt, parseInt, "parseInt") \
macro(pattern, pattern, "pattern") \
macro(preventExtensions, preventExtensions, "preventExtensions") \
macro(propertyIsEnumerable, propertyIsEnumerable, "propertyIsEnumerable") \
macro(proto, proto, "__proto__") \
macro(return, return_, "return") \