[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:
parent
fa9c39eead
commit
69d218c03f
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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(){});
|
||||
|
@ -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);
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user