Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 9a393a833a93203bd31157194e62f4acb050d1ce..0a306059d396f62489e7d667e0ff2cfe10a72278 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. |
+// Never even try to cache it in the transition tree, as it is intended |
+// for the global object and its prototype chain, 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, |
@@ -14955,6 +14966,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 |
@@ -15006,6 +15024,17 @@ Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object, |
return Just(true); |
} |
+// static |
+void JSObject::SetImmutableProto(Handle<JSObject> object) { |
+ DCHECK(!object->IsAccessCheckNeeded()); // Never called from JS |
+ Handle<Map> map(object->map()); |
+ |
+ // Nothing to do if prototype is already set. |
+ if (map->is_immutable_proto()) return; |
+ |
+ Handle<Map> new_map = Map::TransitionToImmutableProto(map); |
+ object->set_map(*new_map); |
+} |
void JSObject::EnsureCanContainElements(Handle<JSObject> object, |
Arguments* args, |