From 3cf6b4057c17d8d1bb277d90b0e079ca489fe1c6 Mon Sep 17 00:00:00 2001 From: Cameron Kaiser Date: Tue, 2 Oct 2018 11:34:30 -0700 Subject: [PATCH] #392: Symbol.toStringTag M1114580 (w/o ESClassValue change; w/45ESR boilerplate) --- dom/plugins/base/nsJSNPRuntime.cpp | 1 + js/public/Class.h | 4 + js/src/builtin/MapObject.cpp | 14 +- js/src/builtin/Object.cpp | 150 +++++++++++++---- js/src/builtin/SymbolObject.cpp | 1 + js/src/builtin/TypedArray.js | 22 +++ js/src/builtin/WeakMapObject.cpp | 2 + js/src/builtin/WeakSetObject.cpp | 1 + .../tests/collections/Map-surfaces-1.js | 6 +- .../tests/collections/Set-surfaces-1.js | 6 +- .../tests/collections/WeakMap-surfaces.js | 2 +- .../tests/collections/WeakSet-surface.js | 2 +- .../collections/iterator-proto-surfaces.js | 8 +- js/src/jit-test/tests/debug/Object-class.js | 2 +- .../tests/proxy/operations-on-revoked.js | 4 +- js/src/jsapi.h | 1 + js/src/jsiter.cpp | 8 +- js/src/jsmath.cpp | 2 + js/src/json.cpp | 3 + js/src/proxy/ScriptedDirectProxyHandler.cpp | 7 +- js/src/tests/ecma_6/Generators/runtime.js | 4 +- js/src/tests/ecma_6/Symbol/toStringTag.js | 158 ++++++++++++++++++ js/src/tests/ecma_6/shell.js | 3 +- js/src/tests/js1_8_5/extensions/dataview.js | 2 +- js/src/vm/ArrayBufferObject.cpp | 3 + js/src/vm/CommonPropertyNames.h | 27 ++- js/src/vm/GeneratorObject.cpp | 13 +- js/src/vm/GlobalObject.cpp | 8 + js/src/vm/GlobalObject.h | 3 + js/src/vm/SelfHosting.cpp | 19 +++ js/src/vm/TypedArrayObject.cpp | 4 + js/xpconnect/wrappers/XrayWrapper.cpp | 7 + js/xpconnect/wrappers/XrayWrapper.h | 12 ++ .../ctypes/tests/unit/test_jsctypes.js | 40 ----- 34 files changed, 428 insertions(+), 121 deletions(-) create mode 100644 js/src/tests/ecma_6/Symbol/toStringTag.js diff --git a/dom/plugins/base/nsJSNPRuntime.cpp b/dom/plugins/base/nsJSNPRuntime.cpp index 6a25febdc..42668ac95 100644 --- a/dom/plugins/base/nsJSNPRuntime.cpp +++ b/dom/plugins/base/nsJSNPRuntime.cpp @@ -1327,6 +1327,7 @@ static bool NPObjWrapper_SetProperty(JSContext *cx, JS::Handle obj, JS::Handle id, JS::MutableHandle vp, JS::ObjectOpResult &result) { + MOZ_ASSERT(false, "See bug 1114580, 2f9eb93beee9"); // NYI XXX TenFourFox 392 NPObject *npobj = GetNPObject(cx, obj); if (!npobj || !npobj->_class || !npobj->_class->hasProperty || diff --git a/js/public/Class.h b/js/public/Class.h index 47180fd31..29bf814d3 100644 --- a/js/public/Class.h +++ b/js/public/Class.h @@ -847,6 +847,10 @@ enum ESClassValue { ESClass_Boolean, ESClass_RegExp, ESClass_ArrayBuffer, ESClass_SharedArrayBuffer, ESClass_Date, ESClass_Set, ESClass_Map, + /** Not yet implemented (TenFourFox issue 392). */ + ESClass_Promise, ESClass_MapIterator, ESClass_SetIterator, + ESClass_Arguments, ESClass_Error, + /** None of the above. */ ESClass_Other }; diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp index 53c9f65e2..5040b1ef4 100644 --- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -171,7 +171,8 @@ GlobalObject::initMapIteratorProto(JSContext* cx, Handle global) RootedPlainObject proto(cx, NewObjectWithGivenProto(cx, base)); if (!proto) return false; - if (!JS_DefineFunctions(cx, proto, MapIteratorObject::methods)) + if (!JS_DefineFunctions(cx, proto, MapIteratorObject::methods) || + !DefineToStringTag(cx, proto, cx->names().MapIterator)) return false; global->setReservedSlot(MAP_ITERATOR_PROTO, ObjectValue(*proto)); return true; @@ -320,6 +321,10 @@ MapObject::initClass(JSContext* cx, JSObject* obj) RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator)); if (!JS_DefinePropertyById(cx, proto, iteratorId, funval, 0)) return nullptr; + + // Define Map.prototype[@@toStringTag]. + if (!DefineToStringTag(cx, proto, cx->names().Map)) + return nullptr; } return proto; } @@ -897,7 +902,8 @@ GlobalObject::initSetIteratorProto(JSContext* cx, Handle global) RootedPlainObject proto(cx, NewObjectWithGivenProto(cx, base)); if (!proto) return false; - if (!JS_DefineFunctions(cx, proto, SetIteratorObject::methods)) + if (!JS_DefineFunctions(cx, proto, SetIteratorObject::methods) || + !DefineToStringTag(cx, proto, cx->names().SetIterator)) return false; global->setReservedSlot(SET_ITERATOR_PROTO, ObjectValue(*proto)); return true; @@ -1051,6 +1057,10 @@ SetObject::initClass(JSContext* cx, JSObject* obj) RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator)); if (!JS_DefinePropertyById(cx, proto, iteratorId, funval, 0)) return nullptr; + + // Define Set.prototype[@@toStringTag]. + if (!DefineToStringTag(cx, proto, cx->names().Set)) + return nullptr; } return proto; } diff --git a/js/src/builtin/Object.cpp b/js/src/builtin/Object.cpp index 0f7bdc3ca..faf52a24e 100644 --- a/js/src/builtin/Object.cpp +++ b/js/src/builtin/Object.cpp @@ -306,63 +306,141 @@ js::ObjectToSource(JSContext* cx, HandleObject obj) } #endif /* JS_HAS_TOSOURCE */ -JSString* -JS_BasicObjectToString(JSContext* cx, HandleObject obj) -{ - // Some classes are really common, don't allocate new strings for them. - // The ordering below is based on the measurements in bug 966264. - if (obj->is()) - return cx->names().objectObject; - if (obj->is()) - return cx->names().objectString; - if (obj->is()) - return cx->names().objectArray; - if (obj->is()) - return cx->names().objectFunction; - if (obj->is()) - return cx->names().objectNumber; - - const char* className = GetObjectClassName(cx, obj); - - if (strcmp(className, "Window") == 0) - return cx->names().objectWindow; - - StringBuffer sb(cx); - if (!sb.append("[object ") || !sb.append(className, strlen(className)) || - !sb.append("]")) - { - return nullptr; - } - return sb.finishString(); -} - -/* ES5 15.2.4.2. Note steps 1 and 2 are errata. */ +/* ES6 19.1.3.6 (after bug 1114580/TenFourFox issue 392) */ bool js::obj_toString(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - /* Step 1. */ + // Step 1. if (args.thisv().isUndefined()) { args.rval().setString(cx->names().objectUndefined); return true; } - /* Step 2. */ + // Step 2. if (args.thisv().isNull()) { args.rval().setString(cx->names().objectNull); return true; } - /* Step 3. */ + // Step 3. RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; - /* Steps 4-5. */ - JSString* str = JS_BasicObjectToString(cx, obj); + // Step 4. + bool isArray; + if (!IsArray(cx, obj, &isArray)) + return false; + + // Step 5. + RootedString builtinTag(cx); + if (isArray) { + builtinTag = cx->names().objectArray; + } else { + // Steps 6-13. + ESClassValue cls; + if (!GetBuiltinClass(cx, obj, &cls)) + return false; + + switch (cls) { + case ESClass_String: + builtinTag = cx->names().objectString; + break; + case ESClass_Arguments: // NYI XXX + builtinTag = cx->names().objectArguments; + break; + case ESClass_Error: // NYI XXX + builtinTag = cx->names().objectError; + break; + case ESClass_Boolean: + builtinTag = cx->names().objectBoolean; + break; + case ESClass_Number: + builtinTag = cx->names().objectNumber; + break; + case ESClass_Date: + builtinTag = cx->names().objectDate; + break; + case ESClass_RegExp: + builtinTag = cx->names().objectRegExp; + break; + default: + if (obj->isCallable()) { + // Non-standard: Prevent from showing up as Function. + RootedObject unwrapped(cx, CheckedUnwrap(obj)); + if (!unwrapped || !unwrapped->getClass()->isDOMClass()) + builtinTag = cx->names().objectFunction; + } + break; + } + } + // Step 14. + // Currently omitted for non-standard fallback. + + // Step 15. + RootedValue tag(cx); + RootedId toStringTagId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().toStringTag)); + if (!GetProperty(cx, obj, obj, toStringTagId, &tag)) { + if (IsProxy(obj)) { + // XXX: This is a dirty hack for jit-test/tests/basic/bug807623.js. + // Just pass through if the property lookup fails; assume that we + // didn't have a tag set in that situation. Proxy::get sets the tag + // to undefined for us in that case. TenFourFox issue 392. + // + // Note that this isn't an issue for current Firefox because + // Proxy.create() was removed. We can't do this because of our + // backwards compatibility, and other tests also rely on it + // currently (see M892903), but fortunately using proper ES6 Proxy + // methods works as expected even without this hack: + // + // var h={}; var p=new Proxy({[Symbol.toStringTag]:"abc"}, h); + // print(Object.prototype.toString.call(p)); /* [object abc] */ + // + // Thus, this code path is only entered in the legacy case, which + // shouldn't know about @@toStringTag anyway. + // + RootedValue receiver(cx, ObjectValue(*obj)); + + (void)proxy_GetProperty(cx, obj, receiver, toStringTagId, &tag); + cx->clearPendingException(); + } else + return false; + } + + // Step 16. + if (!tag.isString()) { + // Non-standard (bug 1277801): Use ClassName as a fallback in the interim + if (!builtinTag) { + const char* className = GetObjectClassName(cx, obj); + + StringBuffer sb(cx); + if (!sb.append("[object ") || !sb.append(className, strlen(className)) || + !sb.append("]")) + { + return false; + } + + builtinTag = sb.finishString(); + if (!builtinTag) + return false; + } + + args.rval().setString(builtinTag); + return true; + } + + // Step 17. + StringBuffer sb(cx); + if (!sb.append("[object ") || !sb.append(tag.toString()) || !sb.append("]")) + return false; + + RootedString str(cx, sb.finishString()); + if (!str) return false; + args.rval().setString(str); return true; } diff --git a/js/src/builtin/SymbolObject.cpp b/js/src/builtin/SymbolObject.cpp index b96c89def..25bde7cbd 100644 --- a/js/src/builtin/SymbolObject.cpp +++ b/js/src/builtin/SymbolObject.cpp @@ -79,6 +79,7 @@ SymbolObject::initClass(JSContext* cx, HandleObject obj) if (!LinkConstructorAndPrototype(cx, ctor, proto) || !DefinePropertiesAndFunctions(cx, proto, properties, methods) || + !DefineToStringTag(cx, proto, cx->names().Symbol) || !DefinePropertiesAndFunctions(cx, ctor, nullptr, staticMethods) || !GlobalObject::initBuiltinConstructor(cx, global, JSProto_Symbol, ctor, proto)) { diff --git a/js/src/builtin/TypedArray.js b/js/src/builtin/TypedArray.js index e3e76d51d..cf9dc35f7 100644 --- a/js/src/builtin/TypedArray.js +++ b/js/src/builtin/TypedArray.js @@ -1167,3 +1167,25 @@ function TypedArrayStaticOf(/*...items*/) { // Step 8. return newObj; } + +// ES 2016 draft Mar 25, 2016 22.2.2.4. +function TypedArraySpecies() { + // Step 1. + return this; +} + +// ES 2017 draft June 2, 2016 22.2.3.32 +function TypedArrayToStringTag() { + // Step 1. + var O = this; + + // Steps 2-3. + if (!IsObject(O) || !IsTypedArray(O)) + return undefined; + + // Steps 4-6. + // Modified to retrieve the [[TypedArrayName]] from the constructor. + return _NameForTypedArray(O); +} +_SetCanonicalName(TypedArrayToStringTag, "get [Symbol.toStringTag]"); + diff --git a/js/src/builtin/WeakMapObject.cpp b/js/src/builtin/WeakMapObject.cpp index 9a5592ef7..0085e0488 100644 --- a/js/src/builtin/WeakMapObject.cpp +++ b/js/src/builtin/WeakMapObject.cpp @@ -455,6 +455,8 @@ InitWeakMapClass(JSContext* cx, HandleObject obj, bool defineMembers) if (defineMembers) { if (!DefinePropertiesAndFunctions(cx, proto, nullptr, weak_map_methods)) return nullptr; + if (!DefineToStringTag(cx, proto, cx->names().WeakMap)) + return nullptr; } if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_WeakMap, ctor, proto)) diff --git a/js/src/builtin/WeakSetObject.cpp b/js/src/builtin/WeakSetObject.cpp index ebc76d020..a88bfc5e3 100644 --- a/js/src/builtin/WeakSetObject.cpp +++ b/js/src/builtin/WeakSetObject.cpp @@ -53,6 +53,7 @@ WeakSetObject::initClass(JSContext* cx, JSObject* obj) if (!ctor || !LinkConstructorAndPrototype(cx, ctor, proto) || !DefinePropertiesAndFunctions(cx, proto, properties, methods) || + !DefineToStringTag(cx, proto, cx->names().WeakSet) || !GlobalObject::initBuiltinConstructor(cx, global, JSProto_WeakSet, ctor, proto)) { return nullptr; diff --git a/js/src/jit-test/tests/collections/Map-surfaces-1.js b/js/src/jit-test/tests/collections/Map-surfaces-1.js index 9a4f20b9f..827dd7b1e 100644 --- a/js/src/jit-test/tests/collections/Map-surfaces-1.js +++ b/js/src/jit-test/tests/collections/Map-surfaces-1.js @@ -13,11 +13,7 @@ assertEq(Map.length, 0); assertEq(Map.name, "Map"); assertEq(Object.getPrototypeOf(Map.prototype), Object.prototype); -assertEq("toStringTag" in Symbol, false, - "if this fails, congratulations! implement " + - "Map.prototype[Symbol.toStringTag] = 'Map' in SpiderMonkey and make " + - "the next test check for '[object Map]' again"); -assertEq(Object.prototype.toString.call(Map.prototype), "[object Object]"); +assertEq(Object.prototype.toString.call(Map.prototype), "[object Map]"); assertEq(Object.prototype.toString.call(new Map()), "[object Map]"); assertEq(Object.keys(Map.prototype).join(), ""); assertEq(Map.prototype.constructor, Map); diff --git a/js/src/jit-test/tests/collections/Set-surfaces-1.js b/js/src/jit-test/tests/collections/Set-surfaces-1.js index 88fcb3404..cd8573868 100644 --- a/js/src/jit-test/tests/collections/Set-surfaces-1.js +++ b/js/src/jit-test/tests/collections/Set-surfaces-1.js @@ -13,11 +13,7 @@ assertEq(Set.length, 0); assertEq(Set.name, "Set"); assertEq(Object.getPrototypeOf(Set.prototype), Object.prototype); -assertEq("toStringTag" in Symbol, false, - "if this fails, congratulations! implement " + - "Set.prototype[Symbol.toStringTag] = 'Set' in SpiderMonkey and make " + - "the next test check for '[object Set]' again"); -assertEq(Object.prototype.toString.call(Set.prototype), "[object Object]"); +assertEq(Object.prototype.toString.call(Set.prototype), "[object Set]"); assertEq(Object.prototype.toString.call(new Set()), "[object Set]"); assertEq(Object.keys(Set.prototype).join(), ""); assertEq(Set.prototype.constructor, Set); diff --git a/js/src/jit-test/tests/collections/WeakMap-surfaces.js b/js/src/jit-test/tests/collections/WeakMap-surfaces.js index 5feae5f7d..5385f6156 100644 --- a/js/src/jit-test/tests/collections/WeakMap-surfaces.js +++ b/js/src/jit-test/tests/collections/WeakMap-surfaces.js @@ -11,7 +11,7 @@ assertEq(WeakMap.length, 0); assertEq(WeakMap.name, "WeakMap"); assertEq(Object.getPrototypeOf(WeakMap.prototype), Object.prototype); -assertEq(Object.prototype.toString.call(WeakMap.prototype), "[object Object]"); +assertEq(Object.prototype.toString.call(WeakMap.prototype), "[object WeakMap]"); assertEq(Object.prototype.toString.call(new WeakMap()), "[object WeakMap]"); assertEq(Object.keys(WeakMap.prototype).join(), ""); assertEq(WeakMap.prototype.constructor, WeakMap); diff --git a/js/src/jit-test/tests/collections/WeakSet-surface.js b/js/src/jit-test/tests/collections/WeakSet-surface.js index 1e3f155c5..253ff4646 100644 --- a/js/src/jit-test/tests/collections/WeakSet-surface.js +++ b/js/src/jit-test/tests/collections/WeakSet-surface.js @@ -11,7 +11,7 @@ assertEq(WeakSet.length, 0); assertEq(WeakSet.name, "WeakSet"); assertEq(Object.getPrototypeOf(WeakSet.prototype), Object.prototype); -assertEq(Object.prototype.toString.call(WeakSet.prototype), "[object Object]"); +assertEq(Object.prototype.toString.call(WeakSet.prototype), "[object WeakSet]"); assertEq(Object.prototype.toString.call(new WeakSet), "[object WeakSet]"); assertEq(Object.keys(WeakSet.prototype).length, 0); assertEq(WeakSet.prototype.constructor, WeakSet); diff --git a/js/src/jit-test/tests/collections/iterator-proto-surfaces.js b/js/src/jit-test/tests/collections/iterator-proto-surfaces.js index e40207fa8..e39ae777f 100644 --- a/js/src/jit-test/tests/collections/iterator-proto-surfaces.js +++ b/js/src/jit-test/tests/collections/iterator-proto-surfaces.js @@ -9,13 +9,9 @@ function test(constructor) { var iter = new constructor()[Symbol.iterator](); assertDeepEq(Reflect.ownKeys(iter), []); - // Iterator prototypes only have a .next property. - // At least until we support @@toStringTag. + // Iterator prototypes only have a .next and @@toStringTag property. var proto1 = Object.getPrototypeOf(iter); - - var names = Reflect.ownKeys(proto1); - names.sort(); - assertDeepEq(Reflect.ownKeys(proto1), ['next']); + assertDeepEq(Reflect.ownKeys(proto1), ['next', Symbol.toStringTag]); var desc = Object.getOwnPropertyDescriptor(proto1, 'next'); assertEq(desc.configurable, true); diff --git a/js/src/jit-test/tests/debug/Object-class.js b/js/src/jit-test/tests/debug/Object-class.js index 1907e6eff..a8fd986ee 100644 --- a/js/src/jit-test/tests/debug/Object-class.js +++ b/js/src/jit-test/tests/debug/Object-class.js @@ -12,7 +12,7 @@ dbg.onDebuggerStatement = function (frame) { assertEq(arr[3].class, "Date"); assertEq(arr[4].class, "Object"); assertEq(arr[5].class, "Function"); - assertEq(arr[6].class, "Date"); + assertEq(arr[6].class, "Object"); hits++; }; g.f(Object.prototype, [], eval, new Date, diff --git a/js/src/jit-test/tests/proxy/operations-on-revoked.js b/js/src/jit-test/tests/proxy/operations-on-revoked.js index 98514d112..181f4c6fc 100644 --- a/js/src/jit-test/tests/proxy/operations-on-revoked.js +++ b/js/src/jit-test/tests/proxy/operations-on-revoked.js @@ -11,8 +11,8 @@ var p2 = r2.proxy; assertThrowsInstanceOf(() => ({} instanceof p), TypeError); assertThrowsInstanceOf(() => ({} instanceof p2), TypeError); -assertEq(Object.prototype.toString.call(p), "[object Object]"); -assertEq(Object.prototype.toString.call(p2), "[object Function]"); +assertThrowsInstanceOf(() => Object.prototype.toString.call(p), TypeError); +assertThrowsInstanceOf(() => Object.prototype.toString.call(p2), TypeError); assertThrowsInstanceOf(() => RegExp.prototype.exec.call(p, ""), TypeError); assertThrowsInstanceOf(() => RegExp.prototype.exec.call(p2, ""), TypeError); diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 76e6fb495..8ad68a24c 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -4561,6 +4561,7 @@ GetSymbolDescription(HandleSymbol symbol); macro(match) \ macro(species) \ macro(toPrimitive) \ + macro(toStringTag) \ macro(unscopables) enum class SymbolCode : uint32_t { diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 1a8c2f0d6..68b36680e 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -1473,7 +1473,9 @@ GlobalObject::initArrayIteratorProto(JSContext* cx, Handle global const Class* cls = &ArrayIteratorPrototypeClass; RootedObject proto(cx, global->createBlankPrototypeInheriting(cx, cls, iteratorProto)); - if (!proto || !DefinePropertiesAndFunctions(cx, proto, nullptr, array_iterator_methods)) + if (!proto || + !DefinePropertiesAndFunctions(cx, proto, nullptr, array_iterator_methods) || + !DefineToStringTag(cx, proto, cx->names().ArrayIterator)) return false; global->setReservedSlot(ARRAY_ITERATOR_PROTO, ObjectValue(*proto)); @@ -1492,7 +1494,9 @@ GlobalObject::initStringIteratorProto(JSContext* cx, Handle globa const Class* cls = &StringIteratorPrototypeClass; RootedObject proto(cx, global->createBlankPrototypeInheriting(cx, cls, iteratorProto)); - if (!proto || !DefinePropertiesAndFunctions(cx, proto, nullptr, string_iterator_methods)) + if (!proto || + !DefinePropertiesAndFunctions(cx, proto, nullptr, string_iterator_methods) || + !DefineToStringTag(cx, proto, cx->names().StringIterator)) return false; global->setReservedSlot(STRING_ITERATOR_PROTO, ObjectValue(*proto)); diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index e381b42a8..9d32c9d8f 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -1647,6 +1647,8 @@ js::InitMathClass(JSContext* cx, HandleObject obj) return nullptr; if (!JS_DefineConstDoubles(cx, Math, math_constants)) return nullptr; + if (!DefineToStringTag(cx, Math, cx->names().Math)) + return nullptr; obj->as().setConstructor(JSProto_Math, ObjectValue(*Math)); diff --git a/js/src/json.cpp b/js/src/json.cpp index 79f10b993..4313c8bcf 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -954,6 +954,9 @@ js::InitJSONClass(JSContext* cx, HandleObject obj) if (!JS_DefineFunctions(cx, JSON, json_static_methods)) return nullptr; + if (!DefineToStringTag(cx, JSON, cx->names().JSON)) + return nullptr; + global->setConstructor(JSProto_JSON, ObjectValue(*JSON)); return JSON; diff --git a/js/src/proxy/ScriptedDirectProxyHandler.cpp b/js/src/proxy/ScriptedDirectProxyHandler.cpp index 3eeef27db..84fdaa2cc 100644 --- a/js/src/proxy/ScriptedDirectProxyHandler.cpp +++ b/js/src/proxy/ScriptedDirectProxyHandler.cpp @@ -1128,12 +1128,9 @@ const char* ScriptedDirectProxyHandler::className(JSContext* cx, HandleObject proxy) const { // Right now the caller is not prepared to handle failures. - RootedObject target(cx, proxy->as().target()); - if (!target) - return BaseProxyHandler::className(cx, proxy); - - return GetObjectClassName(cx, target); + return BaseProxyHandler::className(cx, proxy); } + JSString* ScriptedDirectProxyHandler::fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const diff --git a/js/src/tests/ecma_6/Generators/runtime.js b/js/src/tests/ecma_6/Generators/runtime.js index 9e09075cc..c4d3bb6a6 100644 --- a/js/src/tests/ecma_6/Generators/runtime.js +++ b/js/src/tests/ecma_6/Generators/runtime.js @@ -74,9 +74,7 @@ function TestGeneratorObjectPrototype() { found_property_names.sort(); assertDeepEq(found_property_names, expected_property_names); - - // No symbol properties, at least until we have @@toStringTag. - assertEq(Object.getOwnPropertySymbols(GeneratorObjectPrototype).length, 0); + assertDeepEq(Object.getOwnPropertySymbols(GeneratorObjectPrototype), [Symbol.toStringTag]); } TestGeneratorObjectPrototype(); diff --git a/js/src/tests/ecma_6/Symbol/toStringTag.js b/js/src/tests/ecma_6/Symbol/toStringTag.js new file mode 100644 index 000000000..f5acd1c92 --- /dev/null +++ b/js/src/tests/ecma_6/Symbol/toStringTag.js @@ -0,0 +1,158 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// ES6 19.1.3.6 Object.prototype.toString ( ) +function testToString() { + var tests = [ + [undefined, "[object Undefined]"], + [null, "[object Null]"], + [[], "[object Array]"], + [new String("abc"), "[object String]"], + [(function () {return arguments;})(), "[object Arguments]"], + [(function () {"use strict"; return arguments;})(), "[object Arguments]"], + [function() {}, "[object Function]"], + [new Error("abc"), "[object Error]"], + [true, "[object Boolean]"], + [5, "[object Number]"], + [new Date(), "[object Date]"], + [/regexp/, "[object RegExp]"], + [{[Symbol.toStringTag]: "abc"}, "[object abc]"], + [Object.create(JSON), "[object JSON]"], + [Object.create(new Number), "[object Object]"], + [Object.create(new Number, {[Symbol.toStringTag]: {value: "abc"}}), "[object abc]"], + [(function() { var x = new Number(); x[Symbol.toStringTag] = "abc"; return x; })(), "[object abc]"], + [[], "[object Array]"] + ]; + + // Testing if the values are obtained the right way. + for (let [value, expected] of tests) { + let result = Object.prototype.toString.call(value); + assertEq(result, expected); + } +} +testToString(); + +function testProxy() { + var count = 0; + var metaHandler = new Proxy({}, { + get(target, property, receiver) { + assertEq(property, "get"); + + return function(target, property, receiver) { + assertEq(property, Symbol.toStringTag); + count++; + return undefined; + } + } + }); + + assertEq(Object.prototype.toString.call(new Proxy({}, metaHandler)), "[object Object]") + assertEq(Object.prototype.toString.call(new Proxy(new Date, metaHandler)), "[object Object]") + assertEq(Object.prototype.toString.call(new Proxy([], metaHandler)), "[object Array]") + assertEq(Object.prototype.toString.call(new Proxy(function() {}, metaHandler)), "[object Function]") + var {proxy, revoke} = Proxy.revocable({}, metaHandler); + revoke(); + assertThrowsInstanceOf(() => Object.prototype.toString.call(proxy), TypeError); + + assertEq(count, 4); +} +testProxy(); + +// Tests the passed objects toStringTag values and ensures it's +// desc is writable: false, enumerable: false, configurable: true +function testDefault(object, expected) { + let desc = Object.getOwnPropertyDescriptor(object, Symbol.toStringTag); + assertEq(desc.value, expected); + assertEq(desc.writable, false); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); +} + +// ES6 19.4.3.5 Symbol.prototype [ @@toStringTag ] +testDefault(Symbol.prototype, "Symbol"); + +// ES6 20.2.1.9 Math [ @@toStringTag ] +testDefault(Math, "Math"); + +// ES6 21.1.5.2.2 %StringIteratorPrototype% [ @@toStringTag ] +testDefault(""[Symbol.iterator]().__proto__, "String Iterator") + +// ES6 22.1.5.2.2 %ArrayIteratorPrototype% [ @@toStringTag ] +testDefault([][Symbol.iterator]().__proto__, "Array Iterator") + +// ES6 22.2.3.31 get %TypedArray%.prototype [ @@toStringTag ] +function testTypedArray() { + let ta = (new Uint8Array(0)).__proto__.__proto__; + let desc = Object.getOwnPropertyDescriptor(ta, Symbol.toStringTag); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); + assertEq(desc.set, undefined); + + let get = desc.get; + assertEq(get.name, "get [Symbol.toStringTag]"); + assertEq(get.call(3.14), undefined); + assertEq(get.call({}), undefined); + assertEq(get.call(ta), undefined); + + let types = [ + Int8Array, + Uint8Array, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array + ]; + + for (let type of types) { + let array = new type(0); + assertEq(get.call(array), type.name); + assertEq(Object.prototype.toString.call(array), `[object ${type.name}]`); + } +} +testTypedArray(); + +// ES6 23.1.3.13 Map.prototype [ @@toStringTag ] +testDefault(Map.prototype, "Map"); + +// ES6 23.1.5.2.2 %MapIteratorPrototype% [ @@toStringTag ] +testDefault(new Map()[Symbol.iterator]().__proto__, "Map Iterator") + +// ES6 23.2.3.12 Set.prototype [ @@toStringTag ] +testDefault(Set.prototype, "Set"); + +// ES6 23.2.5.2.2 %SetIteratorPrototype% [ @@toStringTag ] +testDefault(new Set()[Symbol.iterator]().__proto__, "Set Iterator") + +// ES6 23.3.3.6 WeakMap.prototype [ @@toStringTag ] +testDefault(WeakMap.prototype, "WeakMap"); + +// ES6 23.4.3.5 WeakSet.prototype [ @@toStringTag ] +testDefault(WeakSet.prototype, "WeakSet"); + +// ES6 24.1.4.4 ArrayBuffer.prototype [ @@toStringTag ] +testDefault(ArrayBuffer.prototype, "ArrayBuffer"); + +// ES6 24.2.4.21 DataView.prototype[ @@toStringTag ] +testDefault(DataView.prototype, "DataView"); + +// ES6 24.3.3 JSON [ @@toStringTag ] +testDefault(JSON, "JSON"); + +// ES6 25.2.3.3 GeneratorFunction.prototype [ @@toStringTag ] +testDefault(function* () {}.constructor.prototype, "GeneratorFunction"); + +// ES6 25.3.1.5 Generator.prototype [ @@toStringTag ] +testDefault(function* () {}().__proto__.__proto__, "Generator"); + +// ES6 25.4.5.4 Promise.prototype [ @@toStringTag ] +// Not yet implemented! +if (typeof Promise !== "undefined") + testDefault(Promise.prototype, "Promise"); + +// AsyncFunction.prototype [ @@toStringTag ] +// Not yet implemented! +// testDefault(async function() {}.constructor.prototype, "AsyncFunction"); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_6/shell.js b/js/src/tests/ecma_6/shell.js index 1d5d37460..1150258d7 100644 --- a/js/src/tests/ecma_6/shell.js +++ b/js/src/tests/ecma_6/shell.js @@ -82,7 +82,8 @@ if (typeof assertDeepEq === 'undefined') { assertSameValue(ac, bc, msg); switch (ac) { case "[object Function]": - assertSameValue(Function_toString(a), Function_toString(b), msg); + if (typeof isProxy !== "undefined" && !isProxy(a) && !isProxy(b)) + assertSameValue(Function_toString(a), Function_toString(b), msg); } } diff --git a/js/src/tests/js1_8_5/extensions/dataview.js b/js/src/tests/js1_8_5/extensions/dataview.js index 98f7b1b59..1066ec6f5 100644 --- a/js/src/tests/js1_8_5/extensions/dataview.js +++ b/js/src/tests/js1_8_5/extensions/dataview.js @@ -1562,7 +1562,7 @@ function test() { assertEq(Object.prototype.toString.apply(new Float32Array(0)), "[object Float32Array]"); assertEq(Object.prototype.toString.apply(new ArrayBuffer()), "[object ArrayBuffer]"); assertEq(Object.prototype.toString.apply(new DataView(view.buffer)), "[object DataView]"); - assertEq(Object.prototype.toString.apply(DataView.prototype), "[object DataViewPrototype]"); + assertEq(Object.prototype.toString.apply(DataView.prototype), "[object DataView]"); // Technically the spec requires these throw a TypeError -- right now. It's // not clear this is desirable. Once we implement @@toStringTag we can see diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 35aaadc1a..581d268b2 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -1650,6 +1650,9 @@ js::InitArrayBufferClass(JSContext* cx, HandleObject obj) if (!JS_DefineFunctions(cx, arrayBufferProto, ArrayBufferObject::jsfuncs)) return nullptr; + if (!DefineToStringTag(cx, arrayBufferProto, cx->names().ArrayBuffer)) + return nullptr; + return arrayBufferProto; } diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h index 1a8aa25ec..2bba4fe64 100644 --- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -18,6 +18,7 @@ macro(apply, apply, "apply") \ macro(arguments, arguments, "arguments") \ macro(as, as, "as") \ + macro(ArrayIterator, ArrayIterator, "Array Iterator") \ macro(ArrayIteratorNext, ArrayIteratorNext, "ArrayIteratorNext") \ macro(ArrayType, ArrayType, "ArrayType") \ macro(ArrayValues, ArrayValues, "ArrayValues") \ @@ -99,6 +100,7 @@ macro(frame, frame, "frame") \ macro(from, from, "from") \ macro(gcCycleNumber, gcCycleNumber, "gcCycleNumber") \ + macro(Generator, Generator, "Generator") \ macro(GeneratorFunction, GeneratorFunction, "GeneratorFunction") \ macro(get, get, "get") \ macro(getInternals, getInternals, "getInternals") \ @@ -139,6 +141,7 @@ macro(keys, keys, "keys") \ macro(label, label, "label") \ macro(lastIndex, lastIndex, "lastIndex") \ + macro(LegacyGenerator, LegacyGenerator, "LegacyGenerator") \ macro(LegacyGeneratorCloseInternal, LegacyGeneratorCloseInternal, "LegacyGeneratorCloseInternal") \ macro(length, length, "length") \ macro(let, let, "let") \ @@ -148,6 +151,7 @@ macro(locale, locale, "locale") \ macro(lookupGetter, lookupGetter, "__lookupGetter__") \ macro(lookupSetter, lookupSetter, "__lookupSetter__") \ + macro(MapIterator, MapIterator, "Map Iterator") \ macro(maximumFractionDigits, maximumFractionDigits, "maximumFractionDigits") \ macro(maximumSignificantDigits, maximumSignificantDigits, "maximumSignificantDigits") \ macro(message, message, "message") \ @@ -171,15 +175,18 @@ macro(NumberFormat, NumberFormat, "NumberFormat") \ macro(NumberFormatFormatGet, NumberFormatFormatGet, "Intl_NumberFormat_format_get") \ macro(numeric, numeric, "numeric") \ - macro(objectArray, objectArray, "[object Array]") \ - macro(objectFunction, objectFunction, "[object Function]") \ - macro(objectNull, objectNull, "[object Null]") \ - macro(objectNumber, objectNumber, "[object Number]") \ - macro(objectObject, objectObject, "[object Object]") \ - macro(objects, objects, "objects") \ - macro(objectString, objectString, "[object String]") \ macro(objectUndefined, objectUndefined, "[object Undefined]") \ - macro(objectWindow, objectWindow, "[object Window]") \ + macro(objectNull, objectNull, "[object Null]") \ + macro(objectArray, objectArray, "[object Array]") \ + macro(objectString, objectString, "[object String]") \ + macro(objectArguments, objectArguments, "[object Arguments]") \ + macro(objectFunction, objectFunction, "[object Function]") \ + macro(objectError, objectError, "[object Error]") \ + macro(objectBoolean, objectBoolean, "[object Boolean]") \ + macro(objectNumber, objectNumber, "[object Number]") \ + macro(objectDate, objectDate, "[object Date]") \ + macro(objectRegExp, objectRegExp, "[object RegExp]") \ + macro(objects, objects, "objects") \ macro(of, of, "of") \ macro(offset, offset, "offset") \ macro(optimizedOut, optimizedOut, "optimizedOut") \ @@ -204,6 +211,7 @@ macro(scripts, scripts, "scripts") \ macro(sensitivity, sensitivity, "sensitivity") \ macro(set, set, "set") \ + macro(SetIterator, SetIterator, "Set Iterator") \ macro(shape, shape, "shape") \ macro(signMask, signMask, "signMask") \ macro(size, size, "size") \ @@ -215,6 +223,7 @@ macro(static, static_, "static") \ macro(sticky, sticky, "sticky") \ macro(strings, strings, "strings") \ + macro(StringIterator, StringIterator, "String Iterator") \ macro(StructType, StructType, "StructType") \ macro(style, style, "style") \ macro(super, super, "super") \ @@ -277,6 +286,7 @@ macro(match, match, "match") \ macro(species, species, "species") \ macro(toPrimitive, toPrimitive, "toPrimitive") \ + macro(toStringTag, toStringTag, "toStringTag") \ macro(unscopables, unscopables, "unscopables") \ /* Same goes for the descriptions of the well-known symbols. */ \ macro(Symbol_hasInstance, Symbol_hasInstance, "Symbol.hasInstance") \ @@ -285,6 +295,7 @@ macro(Symbol_match, Symbol_match, "Symbol.match") \ macro(Symbol_species, Symbol_species, "Symbol.species") \ macro(Symbol_toPrimitive, Symbol_toPrimitive, "Symbol.toPrimitive") \ + macro(Symbol_toStringTag, Symbol_toStringTag, "Symbol.toStringTag") \ macro(Symbol_unscopables, Symbol_unscopables, "Symbol.unscopables") \ /* Function names for properties named by symbols. */ \ macro(Symbol_iterator_fun, Symbol_iterator_fun, "[Symbol.iterator]") \ diff --git a/js/src/vm/GeneratorObject.cpp b/js/src/vm/GeneratorObject.cpp index af3efd77d..80bed69db 100644 --- a/js/src/vm/GeneratorObject.cpp +++ b/js/src/vm/GeneratorObject.cpp @@ -282,7 +282,14 @@ GlobalObject::initLegacyGeneratorProto(JSContext* cx, Handle glob RootedObject proto(cx, NewSingletonObjectWithObjectPrototype(cx, global)); if (!proto || !proto->setDelegate(cx)) return false; +#if(0) + /* XXX: Stub @@toStringTag for legacy generators. + TenFourFox issue 392 */ + if (!DefinePropertiesAndFunctions(cx, proto, nullptr, legacy_generator_methods) || + !DefineToStringTag(cx, proto, cx->names().LegacyGenerator)) +#else if (!DefinePropertiesAndFunctions(cx, proto, nullptr, legacy_generator_methods)) +#endif return false; global->setReservedSlot(LEGACY_GENERATOR_OBJECT_PROTO, ObjectValue(*proto)); @@ -304,13 +311,15 @@ GlobalObject::initStarGenerators(JSContext* cx, Handle global) iteratorProto)); if (!genObjectProto) return false; - if (!DefinePropertiesAndFunctions(cx, genObjectProto, nullptr, star_generator_methods)) + if (!DefinePropertiesAndFunctions(cx, genObjectProto, nullptr, star_generator_methods) || + !DefineToStringTag(cx, genObjectProto, cx->names().Generator)) return false; RootedObject genFunctionProto(cx, NewSingletonObjectWithFunctionPrototype(cx, global)); if (!genFunctionProto || !genFunctionProto->setDelegate(cx)) return false; - if (!LinkConstructorAndPrototype(cx, genFunctionProto, genObjectProto)) + if (!LinkConstructorAndPrototype(cx, genFunctionProto, genObjectProto) || + !DefineToStringTag(cx, genFunctionProto, cx->names().GeneratorFunction)) return false; RootedValue function(cx, global->getConstructor(JSProto_Function)); diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index fb54570d7..a387eaf87 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -529,6 +529,14 @@ js::DefinePropertiesAndFunctions(JSContext* cx, HandleObject obj, return true; } +bool +js::DefineToStringTag(JSContext *cx, HandleObject obj, JSAtom* tag) +{ + RootedId toStringTagId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().toStringTag)); + RootedValue tagString(cx, StringValue(tag)); + return DefineProperty(cx, obj, toStringTagId, tagString, nullptr, nullptr, JSPROP_READONLY); +} + static void GlobalDebuggees_finalize(FreeOp* fop, JSObject* obj) { diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index e19eced98..5a183b90f 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -905,6 +905,9 @@ DefinePropertiesAndFunctions(JSContext* cx, HandleObject obj, typedef HashSet, SystemAllocPolicy> GlobalObjectSet; +extern bool +DefineToStringTag(JSContext *cx, HandleObject obj, JSAtom* tag); + /* * Convenience templates to generic constructor and prototype creation functions * for ClassSpecs. diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index d4857f091..b1ed70c10 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -40,6 +40,7 @@ #include "vm/String.h" #include "vm/TypedArrayCommon.h" +#include "jsatominlines.h" #include "jsfuninlines.h" #include "jsscriptinlines.h" @@ -1281,6 +1282,23 @@ intrinsic_ConstructorForTypedArray(JSContext* cx, unsigned argc, Value* vp) return true; } +static bool +intrinsic_NameForTypedArray(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + MOZ_ASSERT(args.length() == 1); + MOZ_ASSERT(args[0].isObject()); + + RootedObject object(cx, &args[0].toObject()); + MOZ_ASSERT(object->is()); + + JSProtoKey protoKey = StandardProtoKeyOrNull(object); + MOZ_ASSERT(protoKey); + + args.rval().setString(ClassName(protoKey, cx)); + return true; +} + static bool intrinsic_HostResolveImportedModule(JSContext* cx, unsigned argc, Value* vp) { @@ -1531,6 +1549,7 @@ static const JSFunctionSpec intrinsic_functions[] = { JS_FN("AssertionFailed", intrinsic_AssertionFailed, 1,0), JS_FN("MakeConstructible", intrinsic_MakeConstructible, 2,0), JS_FN("_ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1,0), + JS_FN("_NameForTypedArray", intrinsic_NameForTypedArray, 1,0), JS_FN("DecompileArg", intrinsic_DecompileArg, 2,0), JS_FN("RuntimeDefaultLocale", intrinsic_RuntimeDefaultLocale, 0,0), JS_FN("LocalTZA", intrinsic_LocalTZA, 0,0), diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 3410640ed..4b5831c5e 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -832,6 +832,7 @@ TypedArrayObject::protoAccessors[] = { JS_PSG("buffer", TypedArray_bufferGetter, 0), JS_PSG("byteLength", TypedArray_byteLengthGetter, 0), JS_PSG("byteOffset", TypedArray_byteOffsetGetter, 0), + JS_SELF_HOSTED_SYM_GET(toStringTag, "TypedArrayToStringTag", 0), JS_PS_END }; @@ -2148,6 +2149,9 @@ DataViewObject::initClass(JSContext* cx) if (!JS_DefineFunctions(cx, proto, DataViewObject::jsfuncs)) return false; + if (!DefineToStringTag(cx, proto, cx->names().DataView)) + return false; + /* * Create a helper function to implement the craziness of * |new DataView(new otherWindow.ArrayBuffer())|, and install it in the diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index 4d177ba52..cee679146 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -2220,6 +2220,13 @@ XrayWrapper::construct(JSContext* cx, HandleObject wrapper, const return Traits::construct(cx, wrapper, args, Base::singleton); } +template +bool +XrayWrapper::getBuiltinClass(JSContext* cx, JS::HandleObject wrapper, js::ESClassValue* cls) const +{ + return Traits::getBuiltinClass(cx, wrapper, Base::singleton, cls); +} + template const char* XrayWrapper::className(JSContext* cx, HandleObject wrapper) const diff --git a/js/xpconnect/wrappers/XrayWrapper.h b/js/xpconnect/wrappers/XrayWrapper.h index 53d6eb13e..e92b0a1d9 100644 --- a/js/xpconnect/wrappers/XrayWrapper.h +++ b/js/xpconnect/wrappers/XrayWrapper.h @@ -83,6 +83,11 @@ public: return result.succeed(); } + static bool getBuiltinClass(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance, + js::ESClassValue* cls) { + return baseInstance.getBuiltinClass(cx, wrapper, cls); + } + static const char* className(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance) { return baseInstance.className(cx, wrapper); } @@ -407,6 +412,12 @@ public: return JS_WrapObject(cx, protop); } + static bool getBuiltinClass(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance, + js::ESClassValue* cls) { + *cls = js::ESClass_Other; + return true; + } + static const char* className(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance) { return "Opaque"; } @@ -473,6 +484,7 @@ class XrayWrapper : public Base { virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle wrapper, JS::AutoIdVector& props) const override; + virtual bool getBuiltinClass(JSContext* cx, JS::HandleObject wapper, js::ESClassValue* cls) const override; virtual const char* className(JSContext* cx, JS::HandleObject proxy) const override; static const XrayWrapper singleton; diff --git a/toolkit/components/ctypes/tests/unit/test_jsctypes.js b/toolkit/components/ctypes/tests/unit/test_jsctypes.js index 7f8bd0898..e3f48fc40 100644 --- a/toolkit/components/ctypes/tests/unit/test_jsctypes.js +++ b/toolkit/components/ctypes/tests/unit/test_jsctypes.js @@ -35,14 +35,6 @@ function do_check_throws(f, type, stack) do_throw("expected " + type.name + " exception, none thrown", stack); } -function do_check_class(obj, classname, stack) -{ - if (!stack) - stack = Components.stack.caller; - - do_check_eq(Object.prototype.toString.call(obj), "[object " + classname + "]", stack); -} - function run_test() { // Test ctypes.CType and ctypes.CData are set up correctly. @@ -231,10 +223,6 @@ function run_abstract_class_tests() do_check_throws(function() { ctypes.CType(); }, Error); do_check_throws(function() { new ctypes.CType() }, Error); - // Test that classes and prototypes are set up correctly. - do_check_class(ctypes.CType, "Function"); - do_check_class(ctypes.CType.prototype, "CType"); - do_check_true(ctypes.CType.hasOwnProperty("prototype")); do_check_throws(function() { ctypes.CType.prototype(); }, Error); do_check_throws(function() { new ctypes.CType.prototype() }, Error); @@ -269,10 +257,6 @@ function run_abstract_class_tests() do_check_throws(function() { ctypes.CData(); }, Error); do_check_throws(function() { new ctypes.CData() }, Error); - // Test that classes and prototypes are set up correctly. - do_check_class(ctypes.CData, "Function"); - do_check_class(ctypes.CData.prototype, "CData"); - do_check_true(ctypes.CData.__proto__ === ctypes.CType.prototype); do_check_true(ctypes.CData instanceof ctypes.CType); @@ -302,10 +286,6 @@ function run_abstract_class_tests() function run_Int64_tests() { do_check_throws(function() { ctypes.Int64(); }, TypeError); - // Test that classes and prototypes are set up correctly. - do_check_class(ctypes.Int64, "Function"); - do_check_class(ctypes.Int64.prototype, "Int64"); - do_check_true(ctypes.Int64.hasOwnProperty("prototype")); do_check_true(ctypes.Int64.prototype.hasOwnProperty("constructor")); do_check_true(ctypes.Int64.prototype.constructor === ctypes.Int64); @@ -473,10 +453,6 @@ function run_Int64_tests() { function run_UInt64_tests() { do_check_throws(function() { ctypes.UInt64(); }, TypeError); - // Test that classes and prototypes are set up correctly. - do_check_class(ctypes.UInt64, "Function"); - do_check_class(ctypes.UInt64.prototype, "UInt64"); - do_check_true(ctypes.UInt64.hasOwnProperty("prototype")); do_check_true(ctypes.UInt64.prototype.hasOwnProperty("constructor")); do_check_true(ctypes.UInt64.prototype.constructor === ctypes.UInt64); @@ -738,10 +714,6 @@ function offsetof(struct, member) { // Test the class and prototype hierarchy for a given basic type 't'. function run_basic_class_tests(t) { - // Test that classes and prototypes are set up correctly. - do_check_class(t, "CType"); - do_check_class(t.prototype, "CData"); - do_check_true(t.__proto__ === ctypes.CType.prototype); do_check_true(t instanceof ctypes.CType); @@ -762,7 +734,6 @@ function run_basic_class_tests(t) // Test that an instance 'd' of 't' is a CData. let d = t(); - do_check_class(d, "CData"); do_check_true(d.__proto__ === t.prototype); do_check_true(d instanceof t); do_check_true(d.constructor === t); @@ -1283,10 +1254,6 @@ function run_char16_tests(library, t, name, limits) { // Test the class and prototype hierarchy for a given type constructor 'c'. function run_type_ctor_class_tests(c, t, t2, props=[], fns=[], instanceProps=[], instanceFns=[], specialProps=[]) { - // Test that classes and prototypes are set up correctly on the type ctor 'c'. - do_check_class(c, "Function"); - do_check_class(c.prototype, "CType"); - do_check_true(c.prototype.__proto__ === ctypes.CType.prototype); do_check_true(c.prototype instanceof ctypes.CType); do_check_true(c.prototype.constructor === c); @@ -1303,15 +1270,9 @@ function run_type_ctor_class_tests(c, t, t2, props=[], fns=[], instanceProps=[], for (let f of fns) do_check_throws(function() { c.prototype[f](); }, Error); - // Test that classes and prototypes are set up correctly on a constructed - // type 't'. - do_check_class(t, "CType"); - do_check_class(t.prototype, "CData"); - do_check_true(t.__proto__ === c.prototype); do_check_true(t instanceof c); - do_check_class(t.prototype.__proto__, "CData"); // 't.prototype.__proto__' is the common ancestor of all types constructed // from 'c'; while not available from 'c' directly, it should be identically // equal to 't2.prototype.__proto__' where 't2' is a different CType @@ -1359,7 +1320,6 @@ function run_type_ctor_class_tests(c, t, t2, props=[], fns=[], instanceProps=[], // Test that an instance 'd' of 't' is a CData. if (t.__proto__ != ctypes.FunctionType.prototype) { let d = t(); - do_check_class(d, "CData"); do_check_true(d.__proto__ === t.prototype); do_check_true(d instanceof t); do_check_true(d.constructor === t);