[proxies] Remove "fix" functionality, add (still unused) target property.

BUG=

Review URL: https://codereview.chromium.org/1427743011

Cr-Commit-Position: refs/heads/master@{#31972}
This commit is contained in:
neis 2015-11-12 14:11:53 -08:00 committed by Commit bot
parent fa9c39eead
commit 69d218c03f
14 changed files with 912 additions and 1087 deletions

View File

@ -1936,7 +1936,8 @@ Handle<JSDataView> Factory::NewJSDataView(Handle<JSArrayBuffer> buffer,
}
Handle<JSProxy> Factory::NewJSProxy(Handle<Object> handler,
Handle<JSProxy> Factory::NewJSProxy(Handle<JSReceiver> target,
Handle<JSReceiver> handler,
Handle<Object> prototype) {
// Allocate map.
// TODO(rossberg): Once we optimize proxies, think about a scheme to share
@ -1946,14 +1947,15 @@ Handle<JSProxy> Factory::NewJSProxy(Handle<Object> handler,
// Allocate the proxy object.
Handle<JSProxy> result = New<JSProxy>(map, NEW_SPACE);
result->InitializeBody(map->instance_size(), Smi::FromInt(0));
result->set_target(*target);
result->set_handler(*handler);
result->set_hash(*undefined_value(), SKIP_WRITE_BARRIER);
return result;
}
Handle<JSProxy> Factory::NewJSFunctionProxy(Handle<Object> handler,
Handle<JSProxy> Factory::NewJSFunctionProxy(Handle<JSReceiver> target,
Handle<JSReceiver> handler,
Handle<JSReceiver> call_trap,
Handle<Object> construct_trap,
Handle<Object> prototype) {
@ -1967,7 +1969,7 @@ Handle<JSProxy> Factory::NewJSFunctionProxy(Handle<Object> handler,
// Allocate the proxy object.
Handle<JSFunctionProxy> result = New<JSFunctionProxy>(map, NEW_SPACE);
result->InitializeBody(map->instance_size(), Smi::FromInt(0));
result->set_target(*target);
result->set_handler(*handler);
result->set_hash(*undefined_value(), SKIP_WRITE_BARRIER);
result->set_call_trap(*call_trap);
@ -1976,66 +1978,6 @@ Handle<JSProxy> Factory::NewJSFunctionProxy(Handle<Object> handler,
}
void Factory::ReinitializeJSProxy(Handle<JSProxy> proxy, InstanceType type,
int size) {
DCHECK(type == JS_OBJECT_TYPE || type == JS_FUNCTION_TYPE);
Handle<Map> proxy_map(proxy->map());
Handle<Map> map = Map::FixProxy(proxy_map, type, size);
// Check that the receiver has at least the size of the fresh object.
int size_difference = proxy_map->instance_size() - map->instance_size();
DCHECK(size_difference >= 0);
// Allocate the backing storage for the properties.
Handle<FixedArray> properties = empty_fixed_array();
Heap* heap = isolate()->heap();
MaybeHandle<SharedFunctionInfo> shared;
if (type == JS_FUNCTION_TYPE) {
OneByteStringKey key(STATIC_CHAR_VECTOR("<freezing call trap>"),
heap->HashSeed());
Handle<String> name = InternalizeStringWithKey(&key);
shared = NewSharedFunctionInfo(name, MaybeHandle<Code>());
}
// In order to keep heap in consistent state there must be no allocations
// before object re-initialization is finished and filler object is installed.
DisallowHeapAllocation no_allocation;
// Put in filler if the new object is smaller than the old.
if (size_difference > 0) {
Address address = proxy->address();
heap->CreateFillerObjectAt(address + map->instance_size(), size_difference);
heap->AdjustLiveBytes(*proxy, -size_difference,
Heap::CONCURRENT_TO_SWEEPER);
}
// Reset the map for the object.
proxy->synchronized_set_map(*map);
Handle<JSObject> jsobj = Handle<JSObject>::cast(proxy);
// Reinitialize the object from the constructor map.
heap->InitializeJSObjectFromMap(*jsobj, *properties, *map);
// The current native context is used to set up certain bits.
// TODO(adamk): Using the current context seems wrong, it should be whatever
// context the JSProxy originated in. But that context isn't stored anywhere.
Handle<Context> context(isolate()->native_context());
// Functions require some minimal initialization.
if (type == JS_FUNCTION_TYPE) {
map->set_is_constructor(true);
map->set_is_callable();
Handle<JSFunction> js_function = Handle<JSFunction>::cast(proxy);
InitializeFunction(js_function, shared.ToHandleChecked(), context);
} else {
// Provide JSObjects with a constructor.
map->SetConstructor(context->object_function());
}
}
Handle<JSGlobalProxy> Factory::NewUninitializedJSGlobalProxy() {
// Create an empty shell of a JSGlobalProxy that needs to be reinitialized
// via ReinitializeJSGlobalProxy later.
@ -2080,16 +2022,6 @@ void Factory::ReinitializeJSGlobalProxy(Handle<JSGlobalProxy> object,
}
void Factory::BecomeJSObject(Handle<JSProxy> proxy) {
ReinitializeJSProxy(proxy, JS_OBJECT_TYPE, JSObject::kHeaderSize);
}
void Factory::BecomeJSFunction(Handle<JSProxy> proxy) {
ReinitializeJSProxy(proxy, JS_FUNCTION_TYPE, JSFunction::kSize);
}
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
Handle<String> name, int number_of_literals, FunctionKind kind,
Handle<Code> code, Handle<ScopeInfo> scope_info,

View File

@ -476,10 +476,13 @@ class Factory final {
Handle<Object> done);
// Allocates a Harmony proxy.
Handle<JSProxy> NewJSProxy(Handle<Object> handler, Handle<Object> prototype);
Handle<JSProxy> NewJSProxy(Handle<JSReceiver> target,
Handle<JSReceiver> handler,
Handle<Object> prototype);
// Allocates a Harmony function proxy.
Handle<JSProxy> NewJSFunctionProxy(Handle<Object> handler,
Handle<JSProxy> NewJSFunctionProxy(Handle<JSReceiver> target,
Handle<JSReceiver> handler,
Handle<JSReceiver> call_trap,
Handle<Object> construct_trap,
Handle<Object> prototype);
@ -493,10 +496,6 @@ class Factory final {
Handle<JSGlobalProxy> NewUninitializedJSGlobalProxy();
// Change the type of the argument into a JS object/function and reinitialize.
void BecomeJSObject(Handle<JSProxy> object);
void BecomeJSFunction(Handle<JSProxy> object);
Handle<JSFunction> NewFunction(Handle<String> name, Handle<Code> code,
Handle<Object> prototype,
bool read_only_prototype = false,
@ -713,12 +712,6 @@ class Factory final {
Handle<JSFunction> NewFunction(Handle<Map> map,
Handle<String> name,
MaybeHandle<Code> maybe_code);
// Reinitialize a JSProxy into an (empty) JS object of respective type and
// size, but keeping the original prototype. The receiver must have at least
// the size of the new object. The object is reinitialized and behaves as an
// object that has been freshly allocated.
void ReinitializeJSProxy(Handle<JSProxy> proxy, InstanceType type, int size);
};
} // namespace internal

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@ -30,7 +30,7 @@ function ProxyCreate(handler, proto) {
proto = null
else if (!(IS_SPEC_OBJECT(proto) || IS_NULL(proto)))
throw MakeTypeError(kProxyProtoNonObject)
return %CreateJSProxy(handler, proto)
return %CreateJSProxy({}, handler, proto)
}
function ProxyCreateFunction(handler, callTrap, constructTrap) {
@ -50,7 +50,7 @@ function ProxyCreateFunction(handler, callTrap, constructTrap) {
throw MakeTypeError(kProxyTrapFunctionExpected, "construct")
}
return %CreateJSFunctionProxy(
handler, callTrap, constructTrap, GlobalFunction.prototype)
{}, handler, callTrap, constructTrap, GlobalFunction.prototype)
}
// -------------------------------------------------------------------

View File

@ -1116,43 +1116,12 @@ function ObjectDefineProperties(obj, properties) {
}
// Harmony proxies.
function ProxyFix(obj) {
var handler = %GetHandler(obj);
var props = CallTrap0(handler, "fix", UNDEFINED);
if (IS_UNDEFINED(props)) {
throw MakeTypeError(kProxyHandlerReturned, handler, "undefined", "fix");
}
if (%IsJSFunctionProxy(obj)) {
var callTrap = %GetCallTrap(obj);
var constructTrap = %GetConstructTrap(obj);
var code = ProxyDelegateCallAndConstruct(callTrap, constructTrap);
%Fix(obj); // becomes a regular function
%SetCode(obj, code);
// TODO(rossberg): What about length and other properties? Not specified.
// We just put in some half-reasonable defaults for now.
var prototype = new GlobalObject();
ObjectDefineProperty(prototype, "constructor",
{value: obj, writable: true, enumerable: false, configurable: true});
// TODO(v8:1530): defineProperty does not handle prototype and length.
%FunctionSetPrototype(obj, prototype);
obj.length = 0;
} else {
%Fix(obj);
}
ObjectDefineProperties(obj, props);
}
// ES5 section 15.2.3.8.
function ObjectSealJS(obj) {
if (!IS_SPEC_OBJECT(obj)) return obj;
var isProxy = %_IsJSProxy(obj);
if (isProxy || %HasSloppyArgumentsElements(obj) || %IsObserved(obj)) {
if (isProxy) {
ProxyFix(obj);
}
// TODO(neis): For proxies, must call preventExtensions trap first.
var names = OwnPropertyKeys(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
@ -1180,9 +1149,7 @@ function ObjectFreezeJS(obj) {
// objects.
if (isProxy || %HasSloppyArgumentsElements(obj) || %IsObserved(obj) ||
IS_STRONG(obj)) {
if (isProxy) {
ProxyFix(obj);
}
// TODO(neis): For proxies, must call preventExtensions trap first.
var names = OwnPropertyKeys(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
@ -1206,11 +1173,7 @@ function ObjectFreezeJS(obj) {
// ES5 section 15.2.3.10
function ObjectPreventExtension(obj) {
if (!IS_SPEC_OBJECT(obj)) return obj;
if (%_IsJSProxy(obj)) {
ProxyFix(obj);
}
%PreventExtensions(obj);
return obj;
return %PreventExtensions(obj);
}
@ -1218,7 +1181,7 @@ function ObjectPreventExtension(obj) {
function ObjectIsSealed(obj) {
if (!IS_SPEC_OBJECT(obj)) return true;
if (%_IsJSProxy(obj)) {
return false;
return false; // TODO(neis): Must call isExtensible trap and ownKeys trap.
}
if (%IsExtensible(obj)) {
return false;
@ -1239,7 +1202,7 @@ function ObjectIsSealed(obj) {
function ObjectIsFrozen(obj) {
if (!IS_SPEC_OBJECT(obj)) return true;
if (%_IsJSProxy(obj)) {
return false;
return false; // TODO(neis): Must call isExtensible trap and ownKeys trap.
}
if (%IsExtensible(obj)) {
return false;

View File

@ -6402,20 +6402,13 @@ int JSFunction::NumberOfLiterals() {
}
ACCESSORS(JSProxy, target, Object, kTargetOffset)
ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
ACCESSORS(JSProxy, hash, Object, kHashOffset)
ACCESSORS(JSFunctionProxy, call_trap, JSReceiver, kCallTrapOffset)
ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
void JSProxy::InitializeBody(int object_size, Object* value) {
DCHECK(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
WRITE_FIELD(this, offset, value);
}
}
ACCESSORS(JSCollection, table, Object, kTableOffset)

View File

@ -4654,28 +4654,6 @@ Maybe<PropertyAttributes> JSProxy::GetPropertyAttributesWithHandler(
}
void JSProxy::Fix(Handle<JSProxy> proxy) {
Isolate* isolate = proxy->GetIsolate();
// Save identity hash.
Handle<Object> hash(proxy->GetIdentityHash(), isolate);
if (proxy->IsJSFunctionProxy()) {
isolate->factory()->BecomeJSFunction(proxy);
// Code will be set on the JavaScript side.
} else {
isolate->factory()->BecomeJSObject(proxy);
}
DCHECK(proxy->IsJSObject());
// Inherit identity, if it was present.
if (hash->IsSmi()) {
JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy),
Handle<Smi>::cast(hash));
}
}
MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy,
const char* name,
Handle<Object> derived,
@ -8421,25 +8399,6 @@ Handle<Map> Map::CopyForPreventExtensions(Handle<Map> map,
}
Handle<Map> Map::FixProxy(Handle<Map> map, InstanceType type, int size) {
DCHECK(type == JS_OBJECT_TYPE || type == JS_FUNCTION_TYPE);
DCHECK(map->IsJSProxyMap());
Isolate* isolate = map->GetIsolate();
// Allocate fresh map.
// TODO(rossberg): Once we optimize proxies, cache these maps.
Handle<Map> new_map = isolate->factory()->NewMap(type, size);
Handle<Object> prototype(map->prototype(), isolate);
Map::SetPrototype(new_map, prototype);
map->NotifyLeafMapLayoutChange();
return new_map;
}
bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
PropertyDetails details = GetDetails(descriptor);
switch (details.type()) {

View File

@ -9565,6 +9565,9 @@ class WeakCell : public HeapObject {
// The JSProxy describes EcmaScript Harmony proxies
class JSProxy: public JSReceiver {
public:
// [target]: The target property.
DECL_ACCESSORS(target, Object)
// [handler]: The handler property.
DECL_ACCESSORS(handler, Object)
@ -9596,21 +9599,6 @@ class JSProxy: public JSReceiver {
Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
Handle<Object> value, ShouldThrow should_throw);
// Turn the proxy into an (empty) JSObject.
static void Fix(Handle<JSProxy> proxy);
// Initializes the body after the handler slot.
inline void InitializeBody(int object_size, Object* value);
// Invoke a trap by name. If the trap does not exist on this's handler,
// but derived_trap is non-NULL, invoke that instead. May cause GC.
MUST_USE_RESULT static MaybeHandle<Object> CallTrap(
Handle<JSProxy> proxy,
const char* name,
Handle<Object> derived_trap,
int argc,
Handle<Object> args[]);
// Dispatched behavior.
DECLARE_PRINTER(JSProxy)
DECLARE_VERIFIER(JSProxy)
@ -9618,22 +9606,22 @@ class JSProxy: public JSReceiver {
// Layout description. We add padding so that a proxy has the same
// size as a virgin JSObject. This is essential for becoming a JSObject
// upon freeze.
static const int kHandlerOffset = HeapObject::kHeaderSize;
static const int kTargetOffset = HeapObject::kHeaderSize;
static const int kHandlerOffset = kTargetOffset + kPointerSize;
static const int kHashOffset = kHandlerOffset + kPointerSize;
static const int kPaddingOffset = kHashOffset + kPointerSize;
static const int kSize = JSObject::kHeaderSize;
static const int kHeaderSize = kPaddingOffset;
static const int kPaddingSize = kSize - kPaddingOffset;
static const int kSize = kHashOffset + kPointerSize;
STATIC_ASSERT(kPaddingSize >= 0);
typedef FixedBodyDescriptor<kHandlerOffset,
kPaddingOffset,
kSize> BodyDescriptor;
typedef FixedBodyDescriptor<kTargetOffset, kSize, kSize> BodyDescriptor;
private:
friend class JSReceiver;
// Invoke a trap by name. If the trap does not exist on this's handler,
// but derived_trap is non-NULL, invoke that instead. May cause GC.
MUST_USE_RESULT static MaybeHandle<Object> CallTrap(
Handle<JSProxy> proxy, const char* name, Handle<Object> derived_trap,
int argc, Handle<Object> args[]);
MUST_USE_RESULT static Maybe<bool> HasPropertyWithHandler(
Handle<JSProxy> proxy, Handle<Name> name);
@ -9663,17 +9651,11 @@ class JSFunctionProxy: public JSProxy {
DECLARE_VERIFIER(JSFunctionProxy)
// Layout description.
static const int kCallTrapOffset = JSProxy::kPaddingOffset;
static const int kCallTrapOffset = JSProxy::kSize;
static const int kConstructTrapOffset = kCallTrapOffset + kPointerSize;
static const int kPaddingOffset = kConstructTrapOffset + kPointerSize;
static const int kSize = JSFunction::kSize;
static const int kPaddingSize = kSize - kPaddingOffset;
static const int kSize = kConstructTrapOffset + kPointerSize;
STATIC_ASSERT(kPaddingSize >= 0);
typedef FixedBodyDescriptor<kHandlerOffset,
kConstructTrapOffset + kPointerSize,
kSize> BodyDescriptor;
typedef FixedBodyDescriptor<kTargetOffset, kSize, kSize> BodyDescriptor;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunctionProxy);

View File

@ -13,24 +13,26 @@ namespace internal {
RUNTIME_FUNCTION(Runtime_CreateJSProxy) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, handler, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, handler, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 2);
if (!prototype->IsJSReceiver()) prototype = isolate->factory()->null_value();
return *isolate->factory()->NewJSProxy(handler, prototype);
return *isolate->factory()->NewJSProxy(target, handler, prototype);
}
RUNTIME_FUNCTION(Runtime_CreateJSFunctionProxy) {
HandleScope scope(isolate);
DCHECK(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, handler, 0);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, call_trap, 1);
DCHECK(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, handler, 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, call_trap, 2);
RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
CONVERT_ARG_HANDLE_CHECKED(JSFunction, construct_trap, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 3);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, construct_trap, 3);
CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 4);
if (!prototype->IsJSReceiver()) prototype = isolate->factory()->null_value();
return *isolate->factory()->NewJSFunctionProxy(handler, call_trap,
return *isolate->factory()->NewJSFunctionProxy(target, handler, call_trap,
construct_trap, prototype);
}
@ -74,13 +76,5 @@ RUNTIME_FUNCTION(Runtime_GetConstructTrap) {
return proxy->construct_trap();
}
RUNTIME_FUNCTION(Runtime_Fix) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
JSProxy::Fix(proxy);
return isolate->heap()->undefined_value();
}
} // namespace internal
} // namespace v8

View File

@ -542,14 +542,13 @@ namespace internal {
F(BitwiseXor_Strong, 2, 1)
#define FOR_EACH_INTRINSIC_PROXY(F) \
F(CreateJSProxy, 2, 1) \
F(CreateJSFunctionProxy, 4, 1) \
F(CreateJSProxy, 3, 1) \
F(CreateJSFunctionProxy, 5, 1) \
F(IsJSProxy, 1, 1) \
F(IsJSFunctionProxy, 1, 1) \
F(GetHandler, 1, 1) \
F(GetCallTrap, 1, 1) \
F(GetConstructTrap, 1, 1) \
F(Fix, 1, 1)
F(GetConstructTrap, 1, 1)
#define FOR_EACH_INTRINSIC_REGEXP(F) \

File diff suppressed because it is too large Load Diff

View File

@ -70,9 +70,10 @@ function TestSet2(construct, fix, create) {
assertFalse(s.has(p3));
}
TestSet(Set, Object.seal)
TestSet(Set, Object.freeze)
TestSet(Set, Object.preventExtensions)
// TODO(neis): Reenable once proxies properly support these operations.
// TestSet(Set, Object.seal)
// TestSet(Set, Object.freeze)
// TestSet(Set, Object.preventExtensions)
// Maps and weak maps.
@ -113,10 +114,12 @@ function TestMap2(construct, fix, create) {
assertSame(undefined, m.get(p2));
}
TestMap(Map, Object.seal)
TestMap(Map, Object.freeze)
TestMap(Map, Object.preventExtensions)
// TODO(neis): Reenable once proxies properly support these operations.
// TestMap(Map, Object.seal)
// TestMap(Map, Object.freeze)
// TestMap(Map, Object.preventExtensions)
TestMap(WeakMap, Object.seal)
TestMap(WeakMap, Object.freeze)
TestMap(WeakMap, Object.preventExtensions)
// TODO(neis): Reenable once proxies properly support these operations.
// TestMap(WeakMap, Object.seal)
// TestMap(WeakMap, Object.freeze)
// TestMap(WeakMap, Object.preventExtensions)

View File

@ -1824,59 +1824,61 @@ TestKeysThrow({
// Object.isFrozen, Object.isSealed, Object.isExtensible)
function TestFix(names, handler) {
var proto = {p: 77}
var assertFixing = function(o, s, f, e) {
assertEquals(s, Object.isSealed(o))
assertEquals(f, Object.isFrozen(o))
assertEquals(e, Object.isExtensible(o))
}
var p1 = Proxy.create(handler, proto)
assertFixing(p1, false, false, true)
Object.seal(p1)
assertFixing(p1, true, names.length === 0, false)
assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p1).sort())
assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
Object.keys(p1).sort())
assertEquals(proto, Object.getPrototypeOf(p1))
assertEquals(77, p1.p)
for (var n in p1) {
var desc = Object.getOwnPropertyDescriptor(p1, n)
if (desc !== undefined) assertFalse(desc.configurable)
}
var p2 = Proxy.create(handler, proto)
assertFixing(p2, false, false, true)
Object.freeze(p2)
assertFixing(p2, true, true, false)
assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p2).sort())
assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
Object.keys(p2).sort())
assertEquals(proto, Object.getPrototypeOf(p2))
assertEquals(77, p2.p)
for (var n in p2) {
var desc = Object.getOwnPropertyDescriptor(p2, n)
if (desc !== undefined) assertFalse(desc.writable)
if (desc !== undefined) assertFalse(desc.configurable)
}
var p3 = Proxy.create(handler, proto)
assertFixing(p3, false, false, true)
Object.preventExtensions(p3)
assertFixing(p3, names.length === 0, names.length === 0, false)
assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p3).sort())
assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
Object.keys(p3).sort())
assertEquals(proto, Object.getPrototypeOf(p3))
assertEquals(77, p3.p)
var p = Proxy.create(handler, proto)
var o = Object.create(p)
assertFixing(p, false, false, true)
assertFixing(o, false, false, true)
Object.freeze(o)
assertFixing(p, false, false, true)
assertFixing(o, true, true, false)
// TODO(neis): Reenable/adapt once proxies properly support these operations.
//
// var proto = {p: 77}
// var assertFixing = function(o, s, f, e) {
// assertEquals(s, Object.isSealed(o))
// assertEquals(f, Object.isFrozen(o))
// assertEquals(e, Object.isExtensible(o))
// }
//
// var p1 = Proxy.create(handler, proto)
// assertFixing(p1, false, false, true)
// Object.seal(p1)
// assertFixing(p1, true, names.length === 0, false)
// assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p1).sort())
// assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
// Object.keys(p1).sort())
// assertEquals(proto, Object.getPrototypeOf(p1))
// assertEquals(77, p1.p)
// for (var n in p1) {
// var desc = Object.getOwnPropertyDescriptor(p1, n)
// if (desc !== undefined) assertFalse(desc.configurable)
// }
//
// var p2 = Proxy.create(handler, proto)
// assertFixing(p2, false, false, true)
// Object.freeze(p2)
// assertFixing(p2, true, true, false)
// assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p2).sort())
// assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
// Object.keys(p2).sort())
// assertEquals(proto, Object.getPrototypeOf(p2))
// assertEquals(77, p2.p)
// for (var n in p2) {
// var desc = Object.getOwnPropertyDescriptor(p2, n)
// if (desc !== undefined) assertFalse(desc.writable)
// if (desc !== undefined) assertFalse(desc.configurable)
// }
//
// var p3 = Proxy.create(handler, proto)
// assertFixing(p3, false, false, true)
// Object.preventExtensions(p3)
// assertFixing(p3, names.length === 0, names.length === 0, false)
// assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p3).sort())
// assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
// Object.keys(p3).sort())
// assertEquals(proto, Object.getPrototypeOf(p3))
// assertEquals(77, p3.p)
//
// var p = Proxy.create(handler, proto)
// var o = Object.create(p)
// assertFixing(p, false, false, true)
// assertFixing(o, false, false, true)
// Object.freeze(o)
// assertFixing(p, false, false, true)
// assertFixing(o, true, true, false)
}
TestFix([], {
@ -1912,23 +1914,25 @@ TestFix(["b"], {
function TestFixFunction(fix) {
var f1 = Proxy.createFunction({
fix: function() { return {} }
}, function() {})
fix(f1)
assertEquals(0, f1.length)
var f2 = Proxy.createFunction({
fix: function() { return {length: {value: 3}} }
}, function() {})
fix(f2)
assertEquals(3, f2.length)
var f3 = Proxy.createFunction({
fix: function() { return {length: {value: "huh"}} }
}, function() {})
fix(f3)
assertEquals(0, f1.length)
// TODO(neis): Reenable/adapt once proxies properly support these operations.
//
// var f1 = Proxy.createFunction({
// fix: function() { return {} }
// }, function() {})
// fix(f1)
// assertEquals(0, f1.length)
//
// var f2 = Proxy.createFunction({
// fix: function() { return {length: {value: 3}} }
// }, function() {})
// fix(f2)
// assertEquals(3, f2.length)
//
// var f3 = Proxy.createFunction({
// fix: function() { return {length: {value: "huh"}} }
// }, function() {})
// fix(f3)
// assertEquals(0, f1.length)
}
TestFixFunction(Object.seal)
@ -1941,10 +1945,12 @@ function TestFixThrow(handler) {
}
function TestFixThrow2(create, handler) {
var p = create(handler, {})
assertThrows(function(){ Object.seal(p) }, "myexn")
assertThrows(function(){ Object.freeze(p) }, "myexn")
assertThrows(function(){ Object.preventExtensions(p) }, "myexn")
// TODO(neis): Reenable/adapt once proxies properly support these operations.
//
// var p = create(handler, {})
// assertThrows(function(){ Object.seal(p) }, "myexn")
// assertThrows(function(){ Object.freeze(p) }, "myexn")
// assertThrows(function(){ Object.preventExtensions(p) }, "myexn")
}
TestFixThrow({
@ -1971,9 +1977,11 @@ TestFixThrow({
// TODO(rossberg): actual behaviour not specified consistently at the moment,
// just make sure that we do not crash.
function TestReentrantFix(f) {
TestWithProxies(f, Object.freeze)
TestWithProxies(f, Object.seal)
TestWithProxies(f, Object.preventExtensions)
// TODO(neis): Reenable/adapt once proxies properly support these operations.
//
// TestWithProxies(f, Object.freeze)
// TestWithProxies(f, Object.seal)
// TestWithProxies(f, Object.preventExtensions)
}
TestReentrantFix(function(create, freeze) {

View File

@ -4,10 +4,13 @@
//
// Flags: --harmony-proxies --harmony-object-observe
var proxy = Proxy.create({ fix: function() { return {}; } });
Object.preventExtensions(proxy);
Object.observe(proxy, function(){});
// TODO(neis): These tests are temporarily commented out because of ongoing
// changes to the implementation of proxies.
var functionProxy = Proxy.createFunction({ fix: function() { return {}; } }, function(){});
Object.preventExtensions(functionProxy);
Object.observe(functionProxy, function(){});
//var proxy = Proxy.create({ fix: function() { return {}; } });
//Object.preventExtensions(proxy);
//Object.observe(proxy, function(){});
//
//var functionProxy = Proxy.createFunction({ fix: function() { return {}; } }, function(){});
//Object.preventExtensions(functionProxy);
//Object.observe(functionProxy, function(){});

View File

@ -80,19 +80,21 @@ var childObjAccessor2 = { set foo(_){}, set "1"(_){}, __proto__: proxy2 };
// semantics.
Object.freeze(baseObj);
Object.freeze(proxy1);
assertThrows(function(){proxy1.foo}, TypeError);
assertThrows(function(){proxy1[1]}, TypeError);
assertThrows(function(){childObj1.foo}, TypeError);
assertThrows(function(){childObj1[1]}, TypeError);
assertThrows(function(){childObjAccessor1.foo}, TypeError);
assertThrows(function(){childObjAccessor1[1]}, TypeError);
Object.freeze(proxy2);
assertThrows(function(){proxy2.foo}, TypeError);
assertThrows(function(){proxy2[1]}, TypeError);
assertThrows(function(){childObj2.foo}, TypeError);
assertThrows(function(){childObj2[1]}, TypeError);
assertThrows(function(){childObjAccessor2.foo}, TypeError);
assertThrows(function(){childObjAccessor2[1]}, TypeError);
// TODO(neis): Reenable once proxies properly support freeze.
//
// Object.freeze(proxy1);
// assertThrows(function(){proxy1.foo}, TypeError);
// assertThrows(function(){proxy1[1]}, TypeError);
// assertThrows(function(){childObj1.foo}, TypeError);
// assertThrows(function(){childObj1[1]}, TypeError);
// assertThrows(function(){childObjAccessor1.foo}, TypeError);
// assertThrows(function(){childObjAccessor1[1]}, TypeError);
//
// Object.freeze(proxy2);
// assertThrows(function(){proxy2.foo}, TypeError);
// assertThrows(function(){proxy2[1]}, TypeError);
// assertThrows(function(){childObj2.foo}, TypeError);
// assertThrows(function(){childObj2[1]}, TypeError);
// assertThrows(function(){childObjAccessor2.foo}, TypeError);
// assertThrows(function(){childObjAccessor2[1]}, TypeError);
})();