| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 8933e6ce34011bbcd8ac41adf425b55dfa75aa9d..9636024ae9b1d9cf72fcff8dfc98a71d967b5dc4 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -1021,9 +1021,10 @@ Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate,
|
| if (recv_type->IsUndefined()) return receiver;
|
| FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
|
| // Check the receiver.
|
| - for (PrototypeIterator iter(isolate, receiver,
|
| - PrototypeIterator::START_AT_RECEIVER);
|
| - !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
|
| + for (PrototypeIterator iter(isolate, JSObject::cast(receiver),
|
| + PrototypeIterator::START_AT_RECEIVER,
|
| + PrototypeIterator::END_AT_NON_HIDDEN);
|
| + !iter.IsAtEnd(); iter.Advance()) {
|
| if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent();
|
| }
|
| return isolate->heap()->null_value();
|
| @@ -1098,7 +1099,7 @@ MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
|
| Object);
|
| // 6. If trap is undefined, then return target.[[GetPrototypeOf]]().
|
| if (trap->IsUndefined()) {
|
| - return Object::GetPrototype(isolate, target);
|
| + return JSReceiver::GetPrototype(isolate, target);
|
| }
|
| // 7. Let handlerProto be ? Call(trap, handler, «target»).
|
| Handle<Object> argv[] = {target};
|
| @@ -1120,7 +1121,7 @@ MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
|
| // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
|
| Handle<Object> target_proto;
|
| ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
|
| - Object::GetPrototype(isolate, target), Object);
|
| + JSReceiver::GetPrototype(isolate, target), Object);
|
| // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError.
|
| if (!handler_proto->SameValue(*target_proto)) {
|
| THROW_NEW_ERROR(
|
| @@ -1436,14 +1437,16 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object,
|
| }
|
| }
|
|
|
| -
|
| -Maybe<bool> Object::HasInPrototypeChain(Isolate* isolate, Handle<Object> object,
|
| - Handle<Object> proto) {
|
| +Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
|
| + Handle<JSReceiver> object,
|
| + Handle<Object> proto) {
|
| PrototypeIterator iter(isolate, object, PrototypeIterator::START_AT_RECEIVER);
|
| while (true) {
|
| if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
|
| if (iter.IsAtEnd()) return Just(false);
|
| - if (iter.IsAtEnd(proto)) return Just(true);
|
| + if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) {
|
| + return Just(true);
|
| + }
|
| }
|
| }
|
|
|
| @@ -8742,8 +8745,8 @@ static Maybe<bool> GetKeys_Internal(Isolate* isolate,
|
| ? PrototypeIterator::END_AT_NON_HIDDEN
|
| : PrototypeIterator::END_AT_NULL;
|
| for (PrototypeIterator iter(isolate, object,
|
| - PrototypeIterator::START_AT_RECEIVER);
|
| - !iter.IsAtEnd(end); iter.Advance()) {
|
| + PrototypeIterator::START_AT_RECEIVER, end);
|
| + !iter.IsAtEnd(); iter.Advance()) {
|
| Handle<JSReceiver> current =
|
| PrototypeIterator::GetCurrent<JSReceiver>(iter);
|
| Maybe<bool> result = Just(false); // Dummy initialization.
|
| @@ -12323,7 +12326,7 @@ bool CheckEquivalent(Map* first, Map* second) {
|
| first->is_extensible() == second->is_extensible() &&
|
| first->is_strong() == second->is_strong() &&
|
| first->new_target_is_base() == second->new_target_is_base() &&
|
| - first->is_hidden_prototype() == second->is_hidden_prototype();
|
| + first->has_hidden_prototype() == second->has_hidden_prototype();
|
| }
|
|
|
| } // namespace
|
| @@ -12886,10 +12889,22 @@ Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
|
| // static
|
| void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
|
| PrototypeOptimizationMode proto_mode) {
|
| + bool is_hidden = false;
|
| if (prototype->IsJSObject()) {
|
| Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
|
| JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
|
| +
|
| + Object* maybe_constructor = prototype_jsobj->map()->GetConstructor();
|
| + if (maybe_constructor->IsJSFunction()) {
|
| + JSFunction* constructor = JSFunction::cast(maybe_constructor);
|
| + Object* data = constructor->shared()->function_data();
|
| + is_hidden = (data->IsFunctionTemplateInfo() &&
|
| + FunctionTemplateInfo::cast(data)->hidden_prototype()) ||
|
| + prototype->IsJSGlobalObject();
|
| + }
|
| }
|
| + map->set_has_hidden_prototype(is_hidden);
|
| +
|
| WriteBarrierMode wb_mode =
|
| prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
|
| map->set_prototype(*prototype, wb_mode);
|
| @@ -15651,7 +15666,7 @@ Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value,
|
| // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
|
| Handle<Object> target_proto;
|
| ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto,
|
| - Object::GetPrototype(isolate, target),
|
| + JSReceiver::GetPrototype(isolate, target),
|
| Nothing<bool>());
|
| // 12. If booleanTrapResult is true and SameValue(V, targetProto) is false,
|
| // throw a TypeError exception.
|
| @@ -15677,7 +15692,7 @@ Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
|
| Handle<Object> old_value;
|
| if (observed) {
|
| ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, old_value,
|
| - Object::GetPrototype(isolate, object),
|
| + JSReceiver::GetPrototype(isolate, object),
|
| Nothing<bool>());
|
| }
|
|
|
| @@ -15688,7 +15703,7 @@ Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
|
| if (result.FromJust() && observed) {
|
| Handle<Object> new_value;
|
| ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, new_value,
|
| - Object::GetPrototype(isolate, object),
|
| + JSReceiver::GetPrototype(isolate, object),
|
| Nothing<bool>());
|
| if (!new_value->SameValue(*old_value)) {
|
| RETURN_ON_EXCEPTION_VALUE(
|
| @@ -15744,8 +15759,10 @@ Maybe<bool> JSObject::SetPrototypeUnobserved(Handle<JSObject> object,
|
| if (from_javascript) {
|
| // Find the first object in the chain whose prototype object is not
|
| // hidden.
|
| - PrototypeIterator iter(isolate, real_receiver);
|
| - while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
|
| + PrototypeIterator iter(isolate, real_receiver,
|
| + PrototypeIterator::START_AT_PROTOTYPE,
|
| + PrototypeIterator::END_AT_NON_HIDDEN);
|
| + while (!iter.IsAtEnd()) {
|
| // Casting to JSObject is fine because hidden prototypes are never
|
| // JSProxies.
|
| real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
|
| @@ -15774,13 +15791,15 @@ Maybe<bool> JSObject::SetPrototypeUnobserved(Handle<JSObject> object,
|
| // Before we can set the prototype we need to be sure prototype cycles are
|
| // prevented. It is sufficient to validate that the receiver is not in the
|
| // new prototype chain.
|
| - for (PrototypeIterator iter(isolate, *value,
|
| - PrototypeIterator::START_AT_RECEIVER);
|
| - !iter.IsAtEnd(); iter.Advance()) {
|
| - if (iter.GetCurrent<JSReceiver>() == *object) {
|
| - // Cycle detected.
|
| - RETURN_FAILURE(isolate, should_throw,
|
| - NewTypeError(MessageTemplate::kCyclicProto));
|
| + if (value->IsJSReceiver()) {
|
| + for (PrototypeIterator iter(isolate, JSReceiver::cast(*value),
|
| + PrototypeIterator::START_AT_RECEIVER);
|
| + !iter.IsAtEnd(); iter.Advance()) {
|
| + if (iter.GetCurrent<JSReceiver>() == *object) {
|
| + // Cycle detected.
|
| + RETURN_FAILURE(isolate, should_throw,
|
| + NewTypeError(MessageTemplate::kCyclicProto));
|
| + }
|
| }
|
| }
|
|
|
|
|