Revision: 12001
Author: [email protected]
Date: Fri Jul 6 04:34:22 2012
Log: Fix unhandlified code calling Harmony Proxy traps.
[email protected]
BUG=v8:2219
TEST=mjsunit/regress/regress-2219
Review URL: https://chromiumcodereview.appspot.com/10703103
http://code.google.com/p/v8/source/detail?r=12001
Added:
/branches/bleeding_edge/test/mjsunit/regress/regress-2219.js
Modified:
/branches/bleeding_edge/src/objects.cc
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-2219.js Fri Jul 6
04:34:22 2012
@@ -0,0 +1,32 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-proxies --expose-gc
+
+var p = Proxy.create({getPropertyDescriptor: function() { gc() }});
+var o = Object.create(p);
+assertSame(23, o.x = 23);
=======================================
--- /branches/bleeding_edge/src/objects.cc Fri Jul 6 03:02:15 2012
+++ /branches/bleeding_edge/src/objects.cc Fri Jul 6 04:34:22 2012
@@ -2827,8 +2827,8 @@
MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
- String* name,
- Object* value,
+ String* name_raw,
+ Object* value_raw,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
StoreFromKeyed store_mode) {
@@ -2840,51 +2840,56 @@
// Optimization for 2-byte strings often used as keys in a decompression
// dictionary. We make these short keys into symbols to avoid constantly
// reallocating them.
- if (!name->IsSymbol() && name->length() <= 2) {
+ if (!name_raw->IsSymbol() && name_raw->length() <= 2) {
Object* symbol_version;
- { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name);
+ { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name_raw);
if (maybe_symbol_version->ToObject(&symbol_version)) {
- name = String::cast(symbol_version);
+ name_raw = String::cast(symbol_version);
}
}
}
// Check access rights if needed.
if (IsAccessCheckNeeded()) {
- if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
+ if (!heap->isolate()->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
return SetPropertyWithFailedAccessCheck(
- result, name, value, true, strict_mode);
+ result, name_raw, value_raw, true, strict_mode);
}
}
if (IsJSGlobalProxy()) {
Object* proto = GetPrototype();
- if (proto->IsNull()) return value;
+ if (proto->IsNull()) return value_raw;
ASSERT(proto->IsJSGlobalObject());
return JSObject::cast(proto)->SetPropertyForResult(
- result, name, value, attributes, strict_mode, store_mode);
+ result, name_raw, value_raw, attributes, strict_mode, store_mode);
}
- if (!result->IsProperty() && !IsJSContextExtensionObject()) {
+ // From this point on everything needs to be handlified, because
+ // SetPropertyViaPrototypes might call back into JavaScript.
+ Handle<JSObject> self(this);
+ Handle<String> name(name_raw);
+ Handle<Object> value(value_raw);
+
+ if (!result->IsProperty() && !self->IsJSContextExtensionObject()) {
bool done = false;
- MaybeObject* result_object =
- SetPropertyViaPrototypes(name, value, attributes, strict_mode,
&done);
+ MaybeObject* result_object = self->SetPropertyViaPrototypes(
+ *name, *value, attributes, strict_mode, &done);
if (done) return result_object;
}
if (!result->IsFound()) {
// Neither properties nor transitions found.
- return AddProperty(name, value, attributes, strict_mode, store_mode);
+ return self->AddProperty(
+ *name, *value, attributes, strict_mode, store_mode);
}
if (result->IsProperty() && result->IsReadOnly()) {
if (strict_mode == kStrictMode) {
- Handle<JSObject> self(this);
- Handle<String> hname(name);
- Handle<Object> args[] = { hname, self };
+ Handle<Object> args[] = { name, self };
return
heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
"strict_read_only_property", HandleVector(args,
ARRAY_SIZE(args))));
} else {
- return value;
+ return *value;
}
}
@@ -2892,76 +2897,82 @@
// transition or null descriptor and there are no setters in the
prototypes.
switch (result->type()) {
case NORMAL:
- return SetNormalizedProperty(result, value);
+ return self->SetNormalizedProperty(result, *value);
case FIELD:
- return FastPropertyAtPut(result->GetFieldIndex(), value);
+ return self->FastPropertyAtPut(result->GetFieldIndex(), *value);
case CONSTANT_FUNCTION:
// Only replace the function if necessary.
- if (value == result->GetConstantFunction()) return value;
+ if (*value == result->GetConstantFunction()) return *value;
// Preserve the attributes of this existing property.
attributes = result->GetAttributes();
- return ConvertDescriptorToField(name, value, attributes);
+ return self->ConvertDescriptorToField(*name, *value, attributes);
case CALLBACKS: {
Object* callback_object = result->GetCallbackObject();
- return SetPropertyWithCallback(callback_object,
- name,
- value,
- result->holder(),
- strict_mode);
+ return self->SetPropertyWithCallback(callback_object,
+ *name,
+ *value,
+ result->holder(),
+ strict_mode);
}
case INTERCEPTOR:
- return SetPropertyWithInterceptor(name, value, attributes,
strict_mode);
+ return self->SetPropertyWithInterceptor(*name,
+ *value,
+ attributes,
+ strict_mode);
case TRANSITION: {
Object* transition = result->GetTransitionValue();
if (transition->IsAccessorPair()) {
if (!AccessorPair::cast(transition)->ContainsAccessor()) {
- return ConvertDescriptorToField(name, value, attributes);
- }
- return SetPropertyWithCallback(transition,
- name,
- value,
- result->holder(),
- strict_mode);
+ return self->ConvertDescriptorToField(*name,
+ *value,
+ attributes);
+ }
+ return self->SetPropertyWithCallback(transition,
+ *name,
+ *value,
+ result->holder(),
+ strict_mode);
}
Map* transition_map = Map::cast(transition);
DescriptorArray* descriptors =
transition_map->instance_descriptors();
- int descriptor = descriptors->SearchWithCache(name);
+ int descriptor = descriptors->SearchWithCache(*name);
PropertyDetails details = descriptors->GetDetails(descriptor);
ASSERT(details.type() == FIELD || details.type() ==
CONSTANT_FUNCTION);
if (details.type() == FIELD) {
if (attributes == details.attributes()) {
int field_index = descriptors->GetFieldIndex(descriptor);
- return AddFastPropertyUsingMap(transition_map,
- name,
- value,
- field_index);
- }
- return ConvertDescriptorToField(name, value, attributes);
+ return self->AddFastPropertyUsingMap(transition_map,
+ *name,
+ *value,
+ field_index);
+ }
+ return self->ConvertDescriptorToField(*name, *value, attributes);
}
// Is transition to CONSTANT_FUNCTION.
Object* constant_function = descriptors->GetValue(descriptor);
// If the same constant function is being added we can simply
// transition to the target map.
- if (constant_function == value) {
- set_map(transition_map);
+ if (constant_function == *value) {
+ self->set_map(transition_map);
return this;
}
// Otherwise, replace with a map transition to a new map with a
FIELD,
// even if the value is a constant function.
- return ConvertDescriptorToFieldAndMapTransition(
- name, value, attributes);
+ return self->ConvertDescriptorToFieldAndMapTransition(*name,
+ *value,
+ attributes);
}
case HANDLER:
case NONEXISTENT:
UNREACHABLE();
- return value;
+ return *value;
}
UNREACHABLE(); // keep the compiler happy
- return value;
+ return *value;
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev