From: adamk@chromium.org Date: Wed, 27 Aug 2014 15:54:23 +0000 (+0000) Subject: Ensure that JSProxy::Fix gives the generated JSObject map a constructor X-Git-Tag: upstream/4.7.83~7319 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=71fbe7d4ec414238d768df48842480f1554b1d9b;p=platform%2Fupstream%2Fv8.git 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 R=rossberg@chromium.org, verwaest@chromium.org Review URL: https://codereview.chromium.org/505303004 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23466 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/factory.cc b/src/factory.cc index 643329c..5a07708 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -1777,20 +1777,19 @@ Handle Factory::NewJSFunctionProxy(Handle handler, } -void Factory::ReinitializeJSReceiver(Handle object, - InstanceType type, - int size) { - DCHECK(type >= FIRST_JS_OBJECT_TYPE); +void Factory::ReinitializeJSProxy(Handle 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 = 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 @@ void Factory::ReinitializeJSReceiver(Handle object, // 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 jsobj = Handle::cast(object); + proxy->synchronized_set_map(*map); + Handle jsobj = Handle::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(isolate()->native_context()); + // Functions require some minimal initialization. if (type == JS_FUNCTION_TYPE) { map->set_function_with_prototype(true); - Handle js_function = Handle::cast(object); - Handle context(isolate()->native_context()); + Handle js_function = Handle::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::ReinitializeJSGlobalProxy(Handle object, } -void Factory::BecomeJSObject(Handle object) { - ReinitializeJSReceiver(object, JS_OBJECT_TYPE, JSObject::kHeaderSize); +void Factory::BecomeJSObject(Handle proxy) { + ReinitializeJSProxy(proxy, JS_OBJECT_TYPE, JSObject::kHeaderSize); } -void Factory::BecomeJSFunction(Handle object) { - ReinitializeJSReceiver(object, JS_FUNCTION_TYPE, JSFunction::kSize); +void Factory::BecomeJSFunction(Handle proxy) { + ReinitializeJSProxy(proxy, JS_FUNCTION_TYPE, JSFunction::kSize); } diff --git a/src/factory.h b/src/factory.h index c3ad0dc..f9329ae 100644 --- a/src/factory.h +++ b/src/factory.h @@ -449,13 +449,6 @@ class Factory V8_FINAL { Handle construct_trap, Handle 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 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 @@ class Factory V8_FINAL { Handle constructor); // Change the type of the argument into a JS object/function and reinitialize. - void BecomeJSObject(Handle object); - void BecomeJSFunction(Handle object); + void BecomeJSObject(Handle object); + void BecomeJSFunction(Handle object); Handle NewFunction(Handle name, Handle code, @@ -707,6 +700,12 @@ class Factory V8_FINAL { Handle NewFunction(Handle map, Handle name, MaybeHandle 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 proxy, InstanceType type, int size); }; } } // namespace v8::internal diff --git a/test/mjsunit/harmony/regress/regress-405844.js b/test/mjsunit/harmony/regress/regress-405844.js new file mode 100644 index 0000000..fbe7310 --- /dev/null +++ b/test/mjsunit/harmony/regress/regress-405844.js @@ -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(){});