Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index defde30c44468f4b6190a14dabddcce05dd1284a..9feea5091c860fe0bb06d66591e93595f6e3b4c3 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -8681,6 +8681,17 @@ Handle<Map> Map::CopyNormalized(Handle<Map> map, |
| return result; |
| } |
| +// Return an immutable prototype exotic object version of the input map. |
| +// This is not cached in the transition tree because it is only used on |
|
Toon Verwaest
2016/06/30 15:35:33
The comment is a little inaccurate. The JS_GLOBAL_
Dan Ehrenberg
2016/06/30 23:12:41
Changed the comment; WDYT?
|
| +// the global object, and excluding it saves memory on the map transition |
| +// tree. |
| + |
| +// static |
| +Handle<Map> Map::TransitionToImmutableProto(Handle<Map> map) { |
| + Handle<Map> new_map = Map::Copy(map, "ImmutablePrototype"); |
| + new_map->set_immutable_proto(true); |
| + return new_map; |
| +} |
| Handle<Map> Map::CopyInitialMap(Handle<Map> map, int instance_size, |
| int in_object_properties, |
| @@ -14973,6 +14984,13 @@ Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object, |
| // Nothing to do if prototype is already set. |
| if (map->prototype() == *value) return Just(true); |
| + bool immutable_proto = object->map()->is_immutable_proto(); |
| + if (immutable_proto) { |
| + RETURN_FAILURE( |
| + isolate, should_throw, |
| + NewTypeError(MessageTemplate::kImmutablePrototypeSet, object)); |
| + } |
| + |
| // From 8.6.2 Object Internal Methods |
| // ... |
| // In addition, if [[Extensible]] is false the value of the [[Class]] and |
| @@ -15024,6 +15042,45 @@ Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object, |
| return Just(true); |
| } |
| +// static |
| +Maybe<bool> JSObject::SetImmutableProto(Handle<JSObject> object, |
| + bool from_javascript, |
| + ShouldThrow should_throw) { |
| + Isolate* isolate = object->GetIsolate(); |
| + |
| + if (from_javascript) { |
|
Toon Verwaest
2016/06/30 15:35:33
I guess this shouldn't be possible? So shouldn't b
Dan Ehrenberg
2016/06/30 23:12:41
Good point, nicer to not have that code. I include
|
| + if (object->IsAccessCheckNeeded() && |
| + !isolate->MayAccess(handle(isolate->context()), object)) { |
| + isolate->ReportFailedAccessCheck(object); |
| + RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
| + RETURN_FAILURE(isolate, should_throw, |
| + NewTypeError(MessageTemplate::kNoAccess)); |
| + } |
| + } else { |
| + DCHECK(!object->IsAccessCheckNeeded()); |
| + } |
| + |
| + Handle<JSObject> real_receiver = object; |
| + if (from_javascript) { |
| + // Find the first object in the chain whose prototype object is not |
| + // hidden. |
| + PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype, |
| + 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); |
| + iter.Advance(); |
| + } |
| + } |
| + Handle<Map> map(real_receiver->map()); |
| + |
| + // Nothing to do if prototype is already set. |
| + if (map->is_immutable_proto()) return Just(true); |
| + Handle<Map> new_map = Map::TransitionToImmutableProto(map); |
| + object->set_map(*new_map); |
| + return Just(true); |
| +} |
| void JSObject::EnsureCanContainElements(Handle<JSObject> object, |
| Arguments* args, |