Reviewers: rossberg,
Description:
Fix JavaScript accessors on objects with interceptors.
This fixes how Object.defineProperty() defines JavaScript accessors on
objects with installed API interceptors. The definition itself does not
cause any interceptors to be called, whereas any subsequent accesses on
said object will still fire the interceptor. This behavior is in sync
with API accessors.
[email protected]
BUG=v8:1651,chromium:94666
TEST=cctest/test-api
Please review this at http://codereview.chromium.org/9021019/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/objects.cc
M test/cctest/test-api.cc
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index
e1931887b864f6e1e8cf0ea722218df8e45cbcee..ae5aa78cae57fc078a87ed41d290a3c9b10a1597
100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -4352,7 +4352,7 @@ MaybeObject* JSObject::DefineGetterSetter(String*
name,
} else {
// Lookup the name.
LookupResult result(heap->isolate());
- LocalLookup(name, &result);
+ LocalLookupRealNamedProperty(name, &result);
if (result.IsProperty()) {
// TODO(mstarzinger): We should check for result.IsDontDelete() here
once
// we only call into the runtime once to set both getter and setter.
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index
8b618d4906125d77c88361235bedac41405f0226..d19ef61f17da3ebb1d2c736236a073ba073d0e07
100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -1459,6 +1459,54 @@ THREADED_TEST(SwitchFromAccessorToInterceptor) {
ExpectInt32("child.interceptor_age", 9999);
}
+THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
+ v8::HandleScope scope;
+ Handle<FunctionTemplate> child = FunctionTemplate::New();
+ AddInterceptor(child, InterceptorGetter, InterceptorSetter);
+ LocalContext env;
+ env->Global()->Set(v8_str("Child"), child->GetFunction());
+ CompileRun("var child = new Child;"
+ "function setter(i) { this.accessor_age = i; };"
+ "function getter() { return this.accessor_age; };"
+ "function setAge(i) { child.age = i; };"
+ "Object.defineProperty(child, 'age', { get:getter, set:setter
});"
+ "for(var i = 0; i <= 10000; i++) setAge(i);");
+ // All i < 10000 go to the interceptor.
+ ExpectInt32("child.interceptor_age", 9999);
+ // The last i goes to the JavaScript accessor.
+ ExpectInt32("child.accessor_age", 10000);
+ // The installed JavaScript getter is still intact.
+ // This last part is a regression test for issue 1651 and relies on the
fact
+ // that both interceptor and accessor are being installed on the same
object.
+ ExpectInt32("child.age", 10000);
+ ExpectBoolean("child.hasOwnProperty('age')", true);
+ ExpectUndefined("Object.getOwnPropertyDescriptor(child, 'age').value");
+}
+
+THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
+ v8::HandleScope scope;
+ Handle<FunctionTemplate> child = FunctionTemplate::New();
+ AddInterceptor(child, InterceptorGetter, InterceptorSetter);
+ LocalContext env;
+ env->Global()->Set(v8_str("Child"), child->GetFunction());
+ CompileRun("var child = new Child;"
+ "function setter(i) { this.accessor_age = i; };"
+ "function getter() { return this.accessor_age; };"
+ "function setAge(i) { child.age = i; };"
+ "Object.defineProperty(child, 'age', { get:getter, set:setter
});"
+ "for(var i = 20000; i >= 9999; i--) setAge(i);");
+ // All i >= 10000 go to the accessor.
+ ExpectInt32("child.accessor_age", 10000);
+ // The last i goes to the interceptor.
+ ExpectInt32("child.interceptor_age", 9999);
+ // The installed JavaScript getter is still intact.
+ // This last part is a regression test for issue 1651 and relies on the
fact
+ // that both interceptor and accessor are being installed on the same
object.
+ ExpectInt32("child.age", 10000);
+ ExpectBoolean("child.hasOwnProperty('age')", true);
+ ExpectUndefined("Object.getOwnPropertyDescriptor(child, 'age').value");
+}
+
THREADED_TEST(SwitchFromInterceptorToProperty) {
v8::HandleScope scope;
Handle<FunctionTemplate> parent = FunctionTemplate::New();
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev