Commit 05449f74 authored by ishell's avatar ishell Committed by Commit bot

Allow in-object properties in JSArrayBuffer.

BUG=v8:4531
LOG=Y

Review URL: https://codereview.chromium.org/1479483004

Cr-Commit-Position: refs/heads/master@{#32321}
parent 39efa434
...@@ -166,22 +166,14 @@ class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase { ...@@ -166,22 +166,14 @@ class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase {
static bool IsValidSlot(HeapObject* obj, int offset) { static bool IsValidSlot(HeapObject* obj, int offset) {
if (offset < kBackingStoreOffset) return true; if (offset < kBackingStoreOffset) return true;
if (offset < kSize) return false; if (offset < kSize) return false;
if (offset < kSizeWithInternalFields) return true; return IsValidSlotImpl(obj, offset);
// TODO(ishell): v8:4531, fix when JSArrayBuffers are allowed to have
// in-object properties
// return IsValidSlotImpl(obj, offset);
return true;
} }
template <typename ObjectVisitor> template <typename ObjectVisitor>
static inline void IterateBody(HeapObject* obj, int object_size, static inline void IterateBody(HeapObject* obj, int object_size,
ObjectVisitor* v) { ObjectVisitor* v) {
IteratePointers(obj, kPropertiesOffset, kBackingStoreOffset, v); IteratePointers(obj, kPropertiesOffset, kBackingStoreOffset, v);
IteratePointers(obj, kSize, kSizeWithInternalFields, v); IterateBodyImpl(obj, kSize, object_size, v);
// TODO(ishell): v8:4531, fix when JSArrayBuffers are allowed to have
// in-object properties
// IterateBodyImpl(obj, kSize, object_size, v);
} }
template <typename StaticVisitor> template <typename StaticVisitor>
...@@ -189,18 +181,11 @@ class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase { ...@@ -189,18 +181,11 @@ class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase {
Heap* heap = obj->GetHeap(); Heap* heap = obj->GetHeap();
IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset, IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
kBackingStoreOffset); kBackingStoreOffset);
IteratePointers<StaticVisitor>(heap, obj, kSize, kSizeWithInternalFields); IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
// TODO(ishell): v8:4531, fix when JSArrayBuffers are allowed to have
// in-object properties
// IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
} }
static inline int SizeOf(Map* map, HeapObject* object) { static inline int SizeOf(Map* map, HeapObject* object) {
// TODO(ishell): v8:4531, fix when JSArrayBuffers are allowed to have return map->instance_size();
// in-object properties
// return map->instance_size();
return kSizeWithInternalFields;
} }
}; };
......
...@@ -51,13 +51,15 @@ class BodyDescriptorBase BASE_EMBEDDED { ...@@ -51,13 +51,15 @@ class BodyDescriptorBase BASE_EMBEDDED {
static inline void IteratePointer(Heap* heap, HeapObject* obj, int offset); static inline void IteratePointer(Heap* heap, HeapObject* obj, int offset);
protected: protected:
// Returns true for all header fields. // Returns true for all header and internal fields.
static inline bool IsValidSlotImpl(HeapObject* obj, int offset); static inline bool IsValidSlotImpl(HeapObject* obj, int offset);
// Treats all header and internal fields in the range as tagged.
template <typename ObjectVisitor> template <typename ObjectVisitor>
static inline void IterateBodyImpl(HeapObject* obj, int start_offset, static inline void IterateBodyImpl(HeapObject* obj, int start_offset,
int end_offset, ObjectVisitor* v); int end_offset, ObjectVisitor* v);
// Treats all header and internal fields in the range as tagged.
template <typename StaticVisitor> template <typename StaticVisitor>
static inline void IterateBodyImpl(Heap* heap, HeapObject* obj, static inline void IterateBodyImpl(Heap* heap, HeapObject* obj,
int start_offset, int end_offset); int start_offset, int end_offset);
......
...@@ -12061,6 +12061,7 @@ void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map, ...@@ -12061,6 +12061,7 @@ void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
} }
#ifdef DEBUG
namespace { namespace {
bool CanSubclassHaveInobjectProperties(InstanceType instance_type) { bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
...@@ -12073,6 +12074,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) { ...@@ -12073,6 +12074,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_DATE_TYPE: case JS_DATE_TYPE:
case JS_ARRAY_TYPE: case JS_ARRAY_TYPE:
case JS_MESSAGE_OBJECT_TYPE: case JS_MESSAGE_OBJECT_TYPE:
case JS_ARRAY_BUFFER_TYPE:
case JS_TYPED_ARRAY_TYPE: case JS_TYPED_ARRAY_TYPE:
case JS_DATA_VIEW_TYPE: case JS_DATA_VIEW_TYPE:
case JS_SET_TYPE: case JS_SET_TYPE:
...@@ -12087,11 +12089,8 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) { ...@@ -12087,11 +12089,8 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_FUNCTION_TYPE: case JS_FUNCTION_TYPE:
return true; return true;
case JS_PROXY_TYPE:
case JS_FUNCTION_PROXY_TYPE: case JS_FUNCTION_PROXY_TYPE:
case JS_ARRAY_BUFFER_TYPE: case JS_PROXY_TYPE:
return false;
case JS_GLOBAL_PROXY_TYPE: case JS_GLOBAL_PROXY_TYPE:
case JS_GLOBAL_OBJECT_TYPE: case JS_GLOBAL_OBJECT_TYPE:
case FIXED_ARRAY_TYPE: case FIXED_ARRAY_TYPE:
...@@ -12129,6 +12128,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) { ...@@ -12129,6 +12128,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
} }
} // namespace } // namespace
#endif
void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
...@@ -12205,27 +12205,21 @@ Handle<Map> JSFunction::EnsureDerivedHasInitialMap( ...@@ -12205,27 +12205,21 @@ Handle<Map> JSFunction::EnsureDerivedHasInitialMap(
// Finally link initial map and constructor function if the original // Finally link initial map and constructor function if the original
// constructor is actually a subclass constructor. // constructor is actually a subclass constructor.
if (IsSubclassConstructor(new_target->shared()->kind())) { if (IsSubclassConstructor(new_target->shared()->kind())) {
// TODO(ishell): v8:4531, allow ES6 built-ins subclasses to have
// in-object properties.
InstanceType instance_type = constructor_initial_map->instance_type(); InstanceType instance_type = constructor_initial_map->instance_type();
Handle<Map> map; DCHECK(CanSubclassHaveInobjectProperties(instance_type));
if (CanSubclassHaveInobjectProperties(instance_type)) { int internal_fields =
int internal_fields = JSObject::GetInternalFieldCount(*constructor_initial_map);
JSObject::GetInternalFieldCount(*constructor_initial_map); int pre_allocated = constructor_initial_map->GetInObjectProperties() -
int pre_allocated = constructor_initial_map->GetInObjectProperties() - constructor_initial_map->unused_property_fields();
constructor_initial_map->unused_property_fields(); int instance_size;
int instance_size; int in_object_properties;
int in_object_properties; new_target->CalculateInstanceSizeForDerivedClass(
new_target->CalculateInstanceSizeForDerivedClass( instance_type, internal_fields, &instance_size, &in_object_properties);
instance_type, internal_fields, &instance_size,
&in_object_properties); int unused_property_fields = in_object_properties - pre_allocated;
Handle<Map> map =
int unused_property_fields = in_object_properties - pre_allocated; Map::CopyInitialMap(constructor_initial_map, instance_size,
map = Map::CopyInitialMap(constructor_initial_map, instance_size, in_object_properties, unused_property_fields);
in_object_properties, unused_property_fields);
} else {
map = Map::CopyInitialMap(constructor_initial_map);
}
JSFunction::SetInitialMap(new_target, map, prototype); JSFunction::SetInitialMap(new_target, map, prototype);
map->SetConstructor(*constructor); map->SetConstructor(*constructor);
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --allow-natives-syntax --harmony-reflect --harmony-regexp-subclass // Flags: --allow-natives-syntax --harmony-reflect --harmony-regexp-subclass
// Flags: --expose-gc
"use strict"; "use strict";
...@@ -24,6 +25,7 @@ function checkPrototypeChain(object, constructors) { ...@@ -24,6 +25,7 @@ function checkPrototypeChain(object, constructors) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
...@@ -34,6 +36,7 @@ function checkPrototypeChain(object, constructors) { ...@@ -34,6 +36,7 @@ function checkPrototypeChain(object, constructors) {
checkPrototypeChain(s, [A, Object]); checkPrototypeChain(s, [A, Object]);
assertEquals(42, s.a); assertEquals(42, s.a);
assertEquals(4.2, s.d); assertEquals(4.2, s.d);
assertEquals(153, s.o.foo);
var s1 = new A("bar"); var s1 = new A("bar");
assertTrue(%HaveSameMap(s, s1)); assertTrue(%HaveSameMap(s, s1));
...@@ -46,6 +49,7 @@ function checkPrototypeChain(object, constructors) { ...@@ -46,6 +49,7 @@ function checkPrototypeChain(object, constructors) {
checkPrototypeChain(s, [A, Object]); checkPrototypeChain(s, [A, Object]);
assertEquals(42, n.a); assertEquals(42, n.a);
assertEquals(4.2, n.d); assertEquals(4.2, n.d);
assertEquals(153, n.o.foo);
var n1 = new A(312); var n1 = new A(312);
assertTrue(%HaveSameMap(n, n1)); assertTrue(%HaveSameMap(n, n1));
...@@ -59,10 +63,13 @@ function checkPrototypeChain(object, constructors) { ...@@ -59,10 +63,13 @@ function checkPrototypeChain(object, constructors) {
checkPrototypeChain(s, [A, Object]); checkPrototypeChain(s, [A, Object]);
assertEquals(42, b.a); assertEquals(42, b.a);
assertEquals(4.2, b.d); assertEquals(4.2, b.d);
assertEquals(153, b.o.foo);
var b1 = new A(true); var b1 = new A(true);
assertTrue(%HaveSameMap(b, b1)); assertTrue(%HaveSameMap(b, b1));
assertTrue(%HaveSameMap(b, s)); assertTrue(%HaveSameMap(b, s));
gc();
})(); })();
...@@ -73,10 +80,11 @@ function checkPrototypeChain(object, constructors) { ...@@ -73,10 +80,11 @@ function checkPrototypeChain(object, constructors) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
var o = new A("this.foo = 153;"); var o = new A("this.foo = 113;");
assertTrue(o instanceof Object); assertTrue(o instanceof Object);
assertTrue(o instanceof Function); assertTrue(o instanceof Function);
assertTrue(o instanceof A); assertTrue(o instanceof A);
...@@ -84,11 +92,14 @@ function checkPrototypeChain(object, constructors) { ...@@ -84,11 +92,14 @@ function checkPrototypeChain(object, constructors) {
checkPrototypeChain(o, [A, Function, Object]); checkPrototypeChain(o, [A, Function, Object]);
assertEquals(42, o.a); assertEquals(42, o.a);
assertEquals(4.2, o.d); assertEquals(4.2, o.d);
assertEquals(153, o.o.foo);
var oo = new o(); var oo = new o();
assertEquals(153, oo.foo); assertEquals(113, oo.foo);
var o1 = new A("return 312;"); var o1 = new A("return 312;");
assertTrue(%HaveSameMap(o, o1)); assertTrue(%HaveSameMap(o, o1));
gc();
})(); })();
...@@ -99,6 +110,7 @@ function checkPrototypeChain(object, constructors) { ...@@ -99,6 +110,7 @@ function checkPrototypeChain(object, constructors) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
...@@ -111,9 +123,12 @@ function checkPrototypeChain(object, constructors) { ...@@ -111,9 +123,12 @@ function checkPrototypeChain(object, constructors) {
assertTrue(o.valueOf()); assertTrue(o.valueOf());
assertEquals(42, o.a); assertEquals(42, o.a);
assertEquals(4.2, o.d); assertEquals(4.2, o.d);
assertEquals(153, o.o.foo);
var o1 = new A(false); var o1 = new A(false);
assertTrue(%HaveSameMap(o, o1)); assertTrue(%HaveSameMap(o, o1));
gc();
})(); })();
...@@ -124,6 +139,7 @@ function TestErrorSubclassing(error) { ...@@ -124,6 +139,7 @@ function TestErrorSubclassing(error) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
...@@ -142,9 +158,12 @@ function TestErrorSubclassing(error) { ...@@ -142,9 +158,12 @@ function TestErrorSubclassing(error) {
assertEquals(error.name + ": message", o.toString()); assertEquals(error.name + ": message", o.toString());
assertEquals(42, o.a); assertEquals(42, o.a);
assertEquals(4.2, o.d); assertEquals(4.2, o.d);
assertEquals(153, o.o.foo);
var o1 = new A("achtung!"); var o1 = new A("achtung!");
assertTrue(%HaveSameMap(o, o1)); assertTrue(%HaveSameMap(o, o1));
gc();
} }
...@@ -166,6 +185,7 @@ function TestErrorSubclassing(error) { ...@@ -166,6 +185,7 @@ function TestErrorSubclassing(error) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
...@@ -178,9 +198,12 @@ function TestErrorSubclassing(error) { ...@@ -178,9 +198,12 @@ function TestErrorSubclassing(error) {
assertEquals(153, o.valueOf()); assertEquals(153, o.valueOf());
assertEquals(42, o.a); assertEquals(42, o.a);
assertEquals(4.2, o.d); assertEquals(4.2, o.d);
assertEquals(153, o.o.foo);
var o1 = new A(312); var o1 = new A(312);
assertTrue(%HaveSameMap(o, o1)); assertTrue(%HaveSameMap(o, o1));
gc();
})(); })();
...@@ -191,6 +214,7 @@ function TestErrorSubclassing(error) { ...@@ -191,6 +214,7 @@ function TestErrorSubclassing(error) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
...@@ -203,12 +227,15 @@ function TestErrorSubclassing(error) { ...@@ -203,12 +227,15 @@ function TestErrorSubclassing(error) {
assertEquals(1234567890, o.getTime()); assertEquals(1234567890, o.getTime());
assertEquals(42, o.a); assertEquals(42, o.a);
assertEquals(4.2, o.d); assertEquals(4.2, o.d);
assertEquals(153, o.o.foo);
var o1 = new A(2015, 10, 29); var o1 = new A(2015, 10, 29);
assertEquals(2015, o1.getFullYear()); assertEquals(2015, o1.getFullYear());
assertEquals(10, o1.getMonth()); assertEquals(10, o1.getMonth());
assertEquals(29, o1.getDate()); assertEquals(29, o1.getDate());
assertTrue(%HaveSameMap(o, o1)); assertTrue(%HaveSameMap(o, o1));
gc();
})(); })();
...@@ -219,6 +246,7 @@ function TestErrorSubclassing(error) { ...@@ -219,6 +246,7 @@ function TestErrorSubclassing(error) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
...@@ -232,9 +260,12 @@ function TestErrorSubclassing(error) { ...@@ -232,9 +260,12 @@ function TestErrorSubclassing(error) {
assertEquals("foo", o.valueOf()); assertEquals("foo", o.valueOf());
assertEquals(42, o.a); assertEquals(42, o.a);
assertEquals(4.2, o.d); assertEquals(4.2, o.d);
assertEquals(153, o.o.foo);
var o1 = new A("bar"); var o1 = new A("bar");
assertTrue(%HaveSameMap(o, o1)); assertTrue(%HaveSameMap(o, o1));
gc();
})(); })();
...@@ -245,6 +276,7 @@ function TestErrorSubclassing(error) { ...@@ -245,6 +276,7 @@ function TestErrorSubclassing(error) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
...@@ -263,9 +295,12 @@ function TestErrorSubclassing(error) { ...@@ -263,9 +295,12 @@ function TestErrorSubclassing(error) {
assertEquals(10, o.lastIndex); assertEquals(10, o.lastIndex);
assertEquals(42, o.a); assertEquals(42, o.a);
assertEquals(4.2, o.d); assertEquals(4.2, o.d);
assertEquals(153, o.o.foo);
var o1 = new A(7); var o1 = new A(7);
assertTrue(%HaveSameMap(o, o1)); assertTrue(%HaveSameMap(o, o1));
gc();
})(); })();
...@@ -276,6 +311,7 @@ function TestArraySubclassing(array) { ...@@ -276,6 +311,7 @@ function TestArraySubclassing(array) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
...@@ -295,6 +331,7 @@ function TestArraySubclassing(array) { ...@@ -295,6 +331,7 @@ function TestArraySubclassing(array) {
assertEquals(10, o.length); assertEquals(10, o.length);
assertEquals(42, o.a); assertEquals(42, o.a);
assertEquals(4.2, o.d); assertEquals(4.2, o.d);
assertEquals(153, o.o.foo);
var o1 = new A(7); var o1 = new A(7);
assertTrue(%HaveSameMap(o, o1)); assertTrue(%HaveSameMap(o, o1));
...@@ -324,6 +361,7 @@ function TestMapSetSubclassing(container, is_map) { ...@@ -324,6 +361,7 @@ function TestMapSetSubclassing(container, is_map) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
...@@ -358,9 +396,12 @@ function TestMapSetSubclassing(container, is_map) { ...@@ -358,9 +396,12 @@ function TestMapSetSubclassing(container, is_map) {
} }
assertEquals(42, o.a); assertEquals(42, o.a);
assertEquals(4.2, o.d); assertEquals(4.2, o.d);
assertEquals(153, o.o.foo);
var o1 = new A(); var o1 = new A();
assertTrue(%HaveSameMap(o, o1)); assertTrue(%HaveSameMap(o, o1));
gc();
} }
...@@ -379,6 +420,7 @@ function TestMapSetSubclassing(container, is_map) { ...@@ -379,6 +420,7 @@ function TestMapSetSubclassing(container, is_map) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
...@@ -392,6 +434,7 @@ function TestMapSetSubclassing(container, is_map) { ...@@ -392,6 +434,7 @@ function TestMapSetSubclassing(container, is_map) {
assertEquals(16, o.byteLength); assertEquals(16, o.byteLength);
assertEquals(42, o.a); assertEquals(42, o.a);
assertEquals(4.2, o.d); assertEquals(4.2, o.d);
assertEquals(153, o.o.foo);
var o1 = new A("bar"); var o1 = new A("bar");
assertTrue(%HaveSameMap(o, o1)); assertTrue(%HaveSameMap(o, o1));
...@@ -423,6 +466,8 @@ function TestMapSetSubclassing(container, is_map) { ...@@ -423,6 +466,8 @@ function TestMapSetSubclassing(container, is_map) {
assertEquals(-1, int32view[1]); assertEquals(-1, int32view[1]);
assertEquals(0xfffffffe, uint32view[0]); assertEquals(0xfffffffe, uint32view[0]);
assertEquals(0xffffffff, uint32view[1]); assertEquals(0xffffffff, uint32view[1]);
gc();
})(); })();
...@@ -433,6 +478,7 @@ function TestMapSetSubclassing(container, is_map) { ...@@ -433,6 +478,7 @@ function TestMapSetSubclassing(container, is_map) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
...@@ -449,10 +495,12 @@ function TestMapSetSubclassing(container, is_map) { ...@@ -449,10 +495,12 @@ function TestMapSetSubclassing(container, is_map) {
assertEquals(0xbebafeca, o.getUint32(0, true)); assertEquals(0xbebafeca, o.getUint32(0, true));
assertEquals(42, o.a); assertEquals(42, o.a);
assertEquals(4.2, o.d); assertEquals(4.2, o.d);
assertEquals(153, o.o.foo);
var o1 = new A(buffer); var o1 = new A(buffer);
assertTrue(%HaveSameMap(o, o1)); assertTrue(%HaveSameMap(o, o1));
gc();
})(); })();
...@@ -465,6 +513,7 @@ function TestMapSetSubclassing(container, is_map) { ...@@ -465,6 +513,7 @@ function TestMapSetSubclassing(container, is_map) {
super(...args); super(...args);
this.a = 42; this.a = 42;
this.d = 4.2; this.d = 4.2;
this.o = {foo:153};
} }
} }
var generator_func = new A("var index = 0; while (index < 5) { yield ++index; }"); var generator_func = new A("var index = 0; while (index < 5) { yield ++index; }");
...@@ -476,6 +525,7 @@ function TestMapSetSubclassing(container, is_map) { ...@@ -476,6 +525,7 @@ function TestMapSetSubclassing(container, is_map) {
checkPrototypeChain(generator_func, [A, GeneratorFunction, Function, Object]); checkPrototypeChain(generator_func, [A, GeneratorFunction, Function, Object]);
assertEquals(42, generator_func.a); assertEquals(42, generator_func.a);
assertEquals(4.2, generator_func.d); assertEquals(4.2, generator_func.d);
assertEquals(153, generator_func.o.foo);
var o = new generator_func(); var o = new generator_func();
assertTrue(o instanceof Object); assertTrue(o instanceof Object);
...@@ -491,6 +541,8 @@ function TestMapSetSubclassing(container, is_map) { ...@@ -491,6 +541,8 @@ function TestMapSetSubclassing(container, is_map) {
var generator_func1 = new A("return 0;"); var generator_func1 = new A("return 0;");
assertTrue(%HaveSameMap(generator_func, generator_func1)); assertTrue(%HaveSameMap(generator_func, generator_func1));
gc();
})(); })();
...@@ -584,6 +636,8 @@ function TestMapSetSubclassing(container, is_map) { ...@@ -584,6 +636,8 @@ function TestMapSetSubclassing(container, is_map) {
assertTrue(o instanceof C); assertTrue(o instanceof C);
assertEquals("object", typeof o); assertEquals("object", typeof o);
checkPrototypeChain(o, [C, B, A, Boolean, Object]); checkPrototypeChain(o, [C, B, A, Boolean, Object]);
gc();
})(); })();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment