diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp index 63b6aecf7d6f..4da2c76d402e 100644 --- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -41,6 +41,11 @@ const Class js::TypedObjectClass = { JS_ConvertStub }; +static const JSFunctionSpec TypedObjectMethods[] = { + JS_SELF_HOSTED_FN("objectType", "TypeOfTypedDatum", 1, 0), + JS_FS_END +}; + static void ReportCannotConvertTo(JSContext *cx, HandleValue fromValue, const char *toType) { @@ -1349,6 +1354,9 @@ js_InitTypedObjectClass(JSContext *cx, HandleObject obj) if (!module) return nullptr; + if (!JS_DefineFunctions(cx, module, TypedObjectMethods)) + return nullptr; + // Define TypedObject global. RootedValue moduleValue(cx, ObjectValue(*module)); @@ -2518,6 +2526,15 @@ const JSJitInfo js::MemcpyJitInfo = JS_JITINFO_NATIVE_PARALLEL( JSParallelNativeThreadSafeWrapper); +bool +js::StandardTypeObjectDescriptors(JSContext *cx, unsigned argc, Value *vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + Rooted global(cx, cx->global()); + args.rval().setObject(global->getTypedObject()); + return true; +} + #define JS_STORE_SCALAR_CLASS_IMPL(_constant, T, _name) \ bool \ js::StoreScalar##T::Func(ThreadSafeContext *, unsigned argc, Value *vp) \ diff --git a/js/src/builtin/TypedObject.h b/js/src/builtin/TypedObject.h index a8391055ac7c..d99c9efb3c34 100644 --- a/js/src/builtin/TypedObject.h +++ b/js/src/builtin/TypedObject.h @@ -426,6 +426,17 @@ extern const JSJitInfo ClampToUint8JitInfo; bool Memcpy(ThreadSafeContext *cx, unsigned argc, Value *vp); extern const JSJitInfo MemcpyJitInfo; +/* + * Usage: StandardTypeObjectDescriptors() + * + * Returns the global "typed object" object, which provides access + * to the various builtin type descriptors. These are currently + * exported as immutable properties so it is safe for self-hosted code + * to access them; eventually this should be linked into the module + * system. + */ +bool StandardTypeObjectDescriptors(JSContext *cx, unsigned argc, Value *vp); + /* * Usage: Store_int8(targetDatum, targetOffset, value) * ... diff --git a/js/src/builtin/TypedObject.js b/js/src/builtin/TypedObject.js index 3ebd50b65008..052acb0bb896 100644 --- a/js/src/builtin/TypedObject.js +++ b/js/src/builtin/TypedObject.js @@ -608,6 +608,31 @@ function HandleTest(obj) { /////////////////////////////////////////////////////////////////////////// // Miscellaneous +// This is the `objectType()` function defined in the spec. +// It returns the type of its argument. +// +// Warning: user exposed! +function TypeOfTypedDatum(obj) { + if (IsObject(obj) && ObjectIsTypedDatum(obj)) + return DATUM_TYPE_OBJ(obj); + + // Note: Do not create bindings for `Any`, `String`, etc in + // Utilities.js, but rather access them through + // `StandardTypeObjectDescriptors()`. The reason is that bindings + // you create in Utilities.js are part of the self-hosted global, + // vs the user-accessible global, and hence should not escape to + // user script. + var T = StandardTypeObjectDescriptors(); + switch (typeof obj) { + case "object": return T.Object; + case "function": return T.Object; + case "string": return T.String; + case "number": return T.float64; + case "undefined": return T.Any; + default: return T.Any; + } +} + function ObjectIsTypedDatum(obj) { assert(IsObject(obj), "ObjectIsTypedDatum invoked with non-object") return ObjectIsTypedObject(obj) || ObjectIsTypedHandle(obj); diff --git a/js/src/jsprototypes.h b/js/src/jsprototypes.h index b0fee8c468fa..00401a0fbe8a 100644 --- a/js/src/jsprototypes.h +++ b/js/src/jsprototypes.h @@ -54,7 +54,7 @@ macro(DataView, 35, js_InitTypedArrayClasses) \ macro(ParallelArray, 36, js_InitParallelArrayClass) \ macro(Intl, 37, js_InitIntlClass) \ - macro(TypedObject, 38, js_InitTypedObjectDummy) \ + macro(TypedObject, 38, js_InitTypedObjectClass) \ macro(GeneratorFunction, 39, js_InitIteratorClasses) \ #endif /* jsprototypes_h */ diff --git a/js/src/tests/ecma_6/TypedObject/objecttype.js b/js/src/tests/ecma_6/TypedObject/objecttype.js new file mode 100644 index 000000000000..7a8f0a1f7118 --- /dev/null +++ b/js/src/tests/ecma_6/TypedObject/objecttype.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty("TypedObject")) +var BUGNUMBER = 917454; +var summary = 'objecttype'; + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var T = TypedObject; + +function runTests() { + var Point = new T.ArrayType(T.float32, 3); + var Line = new T.StructType({from: Point, to: Point}); + var Lines = new T.ArrayType(Line, 3); + + var lines = new Lines([ + {from: [1, 2, 3], to: [4, 5, 6]}, + {from: [7, 8, 9], to: [10, 11, 12]}, + {from: [13, 14, 15], to: [16, 17, 18]} + ]); + + assertEq(T.objectType(lines), Lines); + assertEq(T.objectType(lines[0]), Line); + assertEq(T.objectType(lines[0].from[0]), T.float64); + assertEq(T.objectType(""), T.String); + assertEq(T.objectType({}), T.Object); + assertEq(T.objectType([]), T.Object); + assertEq(T.objectType(function() { }), T.Object); + assertEq(T.objectType(undefined), T.Any); + + reportCompare(true, true); + print("Tests complete"); +} + +runTests(); + + diff --git a/js/src/tests/ecma_6/TypedObject/referencetypetrace.js b/js/src/tests/ecma_6/TypedObject/referencetypetrace.js index e1b90399d8cb..e0fa221716ec 100644 --- a/js/src/tests/ecma_6/TypedObject/referencetypetrace.js +++ b/js/src/tests/ecma_6/TypedObject/referencetypetrace.js @@ -4,6 +4,11 @@ var summary = 'TypedObjects reference type trace'; var actual = ''; var expect = ''; +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + var ArrayType = TypedObject.ArrayType; var StructType = TypedObject.StructType; var Any = TypedObject.Any; diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index cbe9ee03d224..6cebb57bd068 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -418,6 +418,13 @@ class GlobalObject : public JSObject return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_Intl, initIntlObject); } + JSObject &getTypedObject() { + Value v = getConstructor(JSProto_TypedObject); + // only gets called from contexts where TypedObject must be initialized + JS_ASSERT(v.isObject()); + return v.toObject(); + } + JSObject *getIteratorPrototype() { return &getPrototype(JSProto_Iterator).toObject(); } diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index d5122bb506c4..48a2f44546e9 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -658,6 +658,9 @@ static const JSFunctionSpec intrinsic_functions[] = { JS_FNINFO("Memcpy", JSNativeThreadSafeWrapper, &js::MemcpyJitInfo, 5, 0), + JS_FN("StandardTypeObjectDescriptors", + js::StandardTypeObjectDescriptors, + 0, 0), #define LOAD_AND_STORE_SCALAR_FN_DECLS(_constant, _type, _name) \ JS_FNINFO("Store_" #_name, \