Revision: 23466
Author: [email protected]
Date: Wed Aug 27 15:54:23 2014 UTC
Log: Ensure that JSProxy::Fix gives the generated JSObject map a
constructor
All JSObjects in V8 either have a map()->constructor() field or are
JSFunctions. JSProxy::Fix, however, was not enforcing this, and
Object.observe's use of JSObject::GetCreationContext() exposed this.
Note that this is not Object.observe-specific: the API call
v8::Object::CreationContext() also would have revealed this bug.
This patch chooses Object as a reasonable constructor to put on the
newly-fixed object's map. Note that this has no effect on the "constructor"
property in JS. In doing so, I've also tightened up the code underlying
JSProxy::Fix to only support JSObject and JSFunction as possible output
types.
BUG=405844
LOG=N
[email protected], [email protected]
Review URL: https://codereview.chromium.org/505303004
https://code.google.com/p/v8/source/detail?r=23466
Added:
/branches/bleeding_edge/test/mjsunit/harmony/regress/regress-405844.js
Modified:
/branches/bleeding_edge/src/factory.cc
/branches/bleeding_edge/src/factory.h
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/harmony/regress/regress-405844.js
Wed Aug 27 15:54:23 2014 UTC
@@ -0,0 +1,13 @@
+// Copyright 2014 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.
+//
+// Flags: --harmony-proxies
+
+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(){});
=======================================
--- /branches/bleeding_edge/src/factory.cc Tue Aug 26 09:19:24 2014 UTC
+++ /branches/bleeding_edge/src/factory.cc Wed Aug 27 15:54:23 2014 UTC
@@ -1777,20 +1777,19 @@
}
-void Factory::ReinitializeJSReceiver(Handle<JSReceiver> object,
- InstanceType type,
- int size) {
- DCHECK(type >= FIRST_JS_OBJECT_TYPE);
+void Factory::ReinitializeJSProxy(Handle<JSProxy> proxy, InstanceType type,
+ int size) {
+ DCHECK(type == JS_OBJECT_TYPE || type == JS_FUNCTION_TYPE);
// Allocate fresh map.
// TODO(rossberg): Once we optimize proxies, cache these maps.
Handle<Map> map = NewMap(type, size);
// Check that the receiver has at least the size of the fresh object.
- int size_difference = object->map()->instance_size() -
map->instance_size();
+ int size_difference = proxy->map()->instance_size() -
map->instance_size();
DCHECK(size_difference >= 0);
- map->set_prototype(object->map()->prototype());
+ map->set_prototype(proxy->map()->prototype());
// Allocate the backing storage for the properties.
int prop_size = map->InitialPropertiesLength();
@@ -1811,24 +1810,31 @@
// Put in filler if the new object is smaller than the old.
if (size_difference > 0) {
- Address address = object->address();
+ Address address = proxy->address();
heap->CreateFillerObjectAt(address + map->instance_size(),
size_difference);
heap->AdjustLiveBytes(address, -size_difference, Heap::FROM_MUTATOR);
}
// Reset the map for the object.
- object->synchronized_set_map(*map);
- Handle<JSObject> jsobj = Handle<JSObject>::cast(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_function_with_prototype(true);
- Handle<JSFunction> js_function = Handle<JSFunction>::cast(object);
- Handle<Context> context(isolate()->native_context());
+ Handle<JSFunction> js_function = Handle<JSFunction>::cast(proxy);
InitializeFunction(js_function, shared.ToHandleChecked(), context);
+ } else {
+ // Provide JSObjects with a constructor.
+ map->set_constructor(context->object_function());
}
}
@@ -1866,13 +1872,13 @@
}
-void Factory::BecomeJSObject(Handle<JSReceiver> object) {
- ReinitializeJSReceiver(object, JS_OBJECT_TYPE, JSObject::kHeaderSize);
+void Factory::BecomeJSObject(Handle<JSProxy> proxy) {
+ ReinitializeJSProxy(proxy, JS_OBJECT_TYPE, JSObject::kHeaderSize);
}
-void Factory::BecomeJSFunction(Handle<JSReceiver> object) {
- ReinitializeJSReceiver(object, JS_FUNCTION_TYPE, JSFunction::kSize);
+void Factory::BecomeJSFunction(Handle<JSProxy> proxy) {
+ ReinitializeJSProxy(proxy, JS_FUNCTION_TYPE, JSFunction::kSize);
}
=======================================
--- /branches/bleeding_edge/src/factory.h Tue Aug 19 08:53:38 2014 UTC
+++ /branches/bleeding_edge/src/factory.h Wed Aug 27 15:54:23 2014 UTC
@@ -449,13 +449,6 @@
Handle<Object> construct_trap,
Handle<Object> prototype);
- // Reinitialize a JSReceiver 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 ReinitializeJSReceiver(
- Handle<JSReceiver> object, InstanceType type, int size);
-
// Reinitialize an JSGlobalProxy based on a constructor. The object
// must have the same size as objects allocated using the
// constructor. The object is reinitialized and behaves as an
@@ -464,8 +457,8 @@
Handle<JSFunction> constructor);
// Change the type of the argument into a JS object/function and
reinitialize.
- void BecomeJSObject(Handle<JSReceiver> object);
- void BecomeJSFunction(Handle<JSReceiver> object);
+ void BecomeJSObject(Handle<JSProxy> object);
+ void BecomeJSFunction(Handle<JSProxy> object);
Handle<JSFunction> NewFunction(Handle<String> name,
Handle<Code> code,
@@ -707,6 +700,12 @@
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 v8::internal
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.