// When there is another reference to the array somewhere (e.g. a handle),
// not zapping turns from a waste of memory into a source of crashes.
if (HasTransitionArray()) {
+#ifdef DEBUG
+ for (int i = 0; i < transitions()->number_of_transitions(); i++) {
+ Map* target = transitions()->GetTarget(i);
+ if (target->instance_descriptors() == instance_descriptors()) {
+ Name* key = transitions()->GetKey(i);
+ int new_target_index = transition_array->Search(key);
+ ASSERT(new_target_index != TransitionArray::kNotFound);
+ ASSERT(transition_array->GetTarget(new_target_index) == target);
+ }
+ }
+#endif
ASSERT(transitions() != transition_array);
ZapTransitions();
}
// Check for accessor in prototype chain removed here in clone.
if (!lookup.IsFound()) {
+ object->map()->LookupTransition(*object, *name, &lookup);
+ TransitionFlag flag = lookup.IsFound()
+ ? OMIT_TRANSITION : INSERT_TRANSITION;
// Neither properties nor transitions found.
return AddProperty(object, name, value, attributes, kNonStrictMode,
- MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode);
+ MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode, flag);
}
Handle<Object> old_value = isolate->factory()->the_hole_value();
}
+THREADED_TEST(EmptyInterceptorBreakTransitions) {
+ v8::HandleScope scope(CcTest::isolate());
+ Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
+ AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
+ LocalContext env;
+ env->Global()->Set(v8_str("Constructor"), templ->GetFunction());
+ CompileRun("var o1 = new Constructor;"
+ "o1.a = 1;" // Ensure a and x share the descriptor array.
+ "Object.defineProperty(o1, 'x', {value: 10});");
+ CompileRun("var o2 = new Constructor;"
+ "o2.a = 1;"
+ "Object.defineProperty(o2, 'x', {value: 10});");
+}
+
+
THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);