diff --git a/content/xbl/test/chrome.ini b/content/xbl/test/chrome.ini
index cf117273acf..162e1d21fea 100644
--- a/content/xbl/test/chrome.ini
+++ b/content/xbl/test/chrome.ini
@@ -1,6 +1,7 @@
[DEFAULT]
support-files =
file_bug944407.xml
+ file_bug950909.xml
[test_bug378518.xul]
[test_bug398135.xul]
@@ -9,3 +10,4 @@ support-files =
[test_bug723676.xul]
[test_bug772966.xul]
[test_bug944407.xul]
+[test_bug950909.xul]
diff --git a/content/xbl/test/file_bug950909.html b/content/xbl/test/file_bug950909.html
new file mode 100644
index 00000000000..d85ee31d052
--- /dev/null
+++ b/content/xbl/test/file_bug950909.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/content/xbl/test/file_bug950909.xml b/content/xbl/test/file_bug950909.xml
new file mode 100644
index 00000000000..a022cc2d5b3
--- /dev/null
+++ b/content/xbl/test/file_bug950909.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/content/xbl/test/mochitest.ini b/content/xbl/test/mochitest.ini
index b390426f19a..36de94fb7c3 100644
--- a/content/xbl/test/mochitest.ini
+++ b/content/xbl/test/mochitest.ini
@@ -14,6 +14,7 @@ support-files =
file_bug844783.xhtml
file_bug944407.html
file_bug944407.xml
+ file_bug950909.html
[test_bug310107.html]
[test_bug366770.html]
diff --git a/content/xbl/test/test_bug950909.xul b/content/xbl/test/test_bug950909.xul
new file mode 100644
index 00000000000..68146d3b957
--- /dev/null
+++ b/content/xbl/test/test_bug950909.xul
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+ Mozilla Bug 950909
+
+
+
+
+
+
diff --git a/docshell/base/nsIMarkupDocumentViewer.idl b/docshell/base/nsIMarkupDocumentViewer.idl
index 342f741435c..27eef2b6261 100644
--- a/docshell/base/nsIMarkupDocumentViewer.idl
+++ b/docshell/base/nsIMarkupDocumentViewer.idl
@@ -82,6 +82,18 @@ interface nsIMarkupDocumentViewer : nsISupports
*/
void changeMaxLineBoxWidth(in int32_t maxLineBoxWidth);
+ /**
+ * Instruct the refresh driver to discontinue painting until further
+ * notice.
+ */
+ void pausePainting();
+
+ /**
+ * Instruct the refresh driver to resume painting after a previous call to
+ * pausePainting().
+ */
+ void resumePainting();
+
/*
* Render the document as if being viewed on a device with the specified
* media type. This will cause a reflow.
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index 36c240b4a40..4d4062dea33 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1365,6 +1365,7 @@ void
nsGlobalWindow::DropOuterWindowDocs()
{
MOZ_ASSERT(IsOuterWindow());
+ MOZ_ASSERT_IF(mDoc, !mDoc->EventHandlingSuppressed());
mDoc = nullptr;
mSuspendedDoc = nullptr;
}
@@ -1547,7 +1548,7 @@ nsGlobalWindow::FreeInnerObjects()
mDocumentURI = mDoc->GetDocumentURI();
mDocBaseURI = mDoc->GetDocBaseURI();
- if (mDoc->EventHandlingSuppressed()) {
+ while (mDoc->EventHandlingSuppressed()) {
mDoc->UnsuppressEventHandlingAndFireEvents(false);
}
}
diff --git a/dom/bindings/CallbackObject.cpp b/dom/bindings/CallbackObject.cpp
index 325135e0e75..4035c06b0cb 100644
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -242,8 +242,7 @@ CallbackObjectHolderBase::ToXPCOMCallback(CallbackObject* aCallback,
JSAutoCompartment ac(cx, callback);
nsRefPtr wrappedJS;
nsresult rv =
- nsXPCWrappedJS::GetNewOrUsed(callback, aIID,
- nullptr, getter_AddRefs(wrappedJS));
+ nsXPCWrappedJS::GetNewOrUsed(callback, aIID, getter_AddRefs(wrappedJS));
if (NS_FAILED(rv) || !wrappedJS) {
return nullptr;
}
diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py
index 4814b3596c9..f054cf05e27 100644
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3299,13 +3299,14 @@ for (uint32_t i = 0; i < length; ++i) {
holderType = CGTemplatedType("Maybe", holderType)
# If we're isOptional and not nullable the normal optional handling will
- # handle lazy construction of our holder. If we're nullable we do it
- # all by hand because we do not want our holder constructed if we're
- # null.
+ # handle lazy construction of our holder. If we're nullable and not
+ # isMember we do it all by hand because we do not want our holder
+ # constructed if we're null. But if we're isMember we don't have a
+ # holder anyway, so we can do the normal Optional codepath.
declLoc = "${declName}"
constructDecl = None
if nullable:
- if isOptional:
+ if isOptional and not isMember:
holderArgs = "${declName}.Value().SetValue()"
declType = CGTemplatedType("Optional", declType)
constructDecl = CGGeneric("${declName}.Construct();")
@@ -3374,7 +3375,7 @@ for (uint32_t i = 0; i < length; ++i) {
declType=declType,
holderType=holderType,
holderArgs=holderArgs,
- dealWithOptional=isOptional and not nullable)
+ dealWithOptional=isOptional and (not nullable or isMember))
if type.isGeckoInterface():
assert not isEnforceRange and not isClamp
diff --git a/dom/bindings/test/TestCodeGen.webidl b/dom/bindings/test/TestCodeGen.webidl
index b5e531fa84f..4fafd038a31 100644
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -791,6 +791,7 @@ dictionary Dict : ParentDict {
#ifdef DEBUG
(EventInit or long) eventInitOrLong;
(EventInit or long)? nullableEventInitOrLong;
+ (Node or long)? nullableNodeOrLong;
// CustomEventInit is useful to test because it needs rooting.
(CustomEventInit or long) eventInitOrLong2;
(CustomEventInit or long)? nullableEventInitOrLong2;
diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html
index 21dede8b555..f6c6217451b 100644
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -74,6 +74,7 @@ var ecmaGlobals =
"ReferenceError",
"RegExp",
"Set",
+ {name: "SIMD", nightly: true},
"StopIteration",
"String",
"SyntaxError",
diff --git a/js/public/Class.h b/js/public/Class.h
index 67021d24f0f..0b00f9079e0 100644
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -568,7 +568,7 @@ struct JSClass {
// with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
// previously allowed, but is now an ES5 violation and thus unsupported.
//
-#define JSCLASS_GLOBAL_SLOT_COUNT (3 + JSProto_LIMIT * 3 + 27)
+#define JSCLASS_GLOBAL_SLOT_COUNT (3 + JSProto_LIMIT * 3 + 29)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \
diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp
new file mode 100644
index 00000000000..3bf7e430928
--- /dev/null
+++ b/js/src/builtin/SIMD.cpp
@@ -0,0 +1,952 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * JS SIMD pseudo-module.
+ * Specification matches polyfill:
+ * https://github.com/johnmccutchan/ecmascript_simd/blob/master/src/ecmascript_simd.js
+ * The objects float32x4 and int32x4 are installed on the SIMD pseudo-module.
+ */
+
+#include "builtin/SIMD.h"
+#include "jsapi.h"
+#include "jsfriendapi.h"
+#include "builtin/TypedObject.h"
+#include "jsobjinlines.h"
+
+using namespace js;
+
+using mozilla::ArrayLength;
+using mozilla::IsFinite;
+using mozilla::IsNaN;
+
+namespace js {
+extern const JSFunctionSpec Float32x4Methods[];
+extern const JSFunctionSpec Int32x4Methods[];
+}
+
+///////////////////////////////////////////////////////////////////////////
+// X4
+
+namespace js {
+struct Float32x4 {
+ typedef float Elem;
+ static const int32_t lanes = 4;
+ static const X4TypeRepresentation::Type type =
+ X4TypeRepresentation::TYPE_FLOAT32;
+
+ static JSObject &GetTypeObject(GlobalObject &global) {
+ return global.float32x4TypeObject();
+ }
+ static Elem toType(Elem a) {
+ return a;
+ }
+ static void toType2(JSContext *cx, JS::Handle v, Elem *out) {
+ *out = v.toNumber();
+ }
+ static void setReturn(CallArgs &args, float value) {
+ args.rval().setDouble(value);
+ }
+};
+
+struct Int32x4 {
+ typedef int32_t Elem;
+ static const int32_t lanes = 4;
+ static const X4TypeRepresentation::Type type =
+ X4TypeRepresentation::TYPE_INT32;
+
+ static JSObject &GetTypeObject(GlobalObject &global) {
+ return global.int32x4TypeObject();
+ }
+ static Elem toType(Elem a) {
+ return ToInt32(a);
+ }
+ static void toType2(JSContext *cx, JS::Handle v, Elem *out) {
+ ToInt32(cx,v,out);
+ }
+ static void setReturn(CallArgs &args, int32_t value) {
+ args.rval().setInt32(value);
+ }
+};
+} // namespace js
+
+#define LANE_ACCESSOR(Type32x4, lane) \
+ bool Type32x4##Lane##lane(JSContext *cx, unsigned argc, Value *vp) { \
+ static const char *laneNames[] = {"lane 0", "lane 1", "lane 2", "lane3"}; \
+ CallArgs args = CallArgsFromVp(argc, vp); \
+ if(!args.thisv().isObject() || !IsTypedDatum(args.thisv().toObject())) { \
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, \
+ X4Type::class_.name, laneNames[lane], \
+ InformalValueTypeName(args.thisv())); \
+ return false; \
+ } \
+ TypedDatum &datum = AsTypedDatum(args.thisv().toObject()); \
+ TypeRepresentation *typeRepr = datum.datumTypeRepresentation(); \
+ if (typeRepr->kind() != TypeRepresentation::X4 || typeRepr->asX4()->type() != Type32x4::type) { \
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, \
+ X4Type::class_.name, laneNames[lane], \
+ InformalValueTypeName(args.thisv())); \
+ return false; \
+ } \
+ Type32x4::Elem *data = reinterpret_cast(datum.typedMem()); \
+ Type32x4::setReturn(args, data[lane]); \
+ return true; \
+ }
+ LANE_ACCESSOR(Float32x4, 0);
+ LANE_ACCESSOR(Float32x4, 1);
+ LANE_ACCESSOR(Float32x4, 2);
+ LANE_ACCESSOR(Float32x4, 3);
+ LANE_ACCESSOR(Int32x4, 0);
+ LANE_ACCESSOR(Int32x4, 1);
+ LANE_ACCESSOR(Int32x4, 2);
+ LANE_ACCESSOR(Int32x4, 3);
+#undef LANE_ACCESSOR
+
+#define SIGN_MASK(Type32x4) \
+ bool Type32x4##SignMask(JSContext *cx, unsigned argc, Value *vp) { \
+ CallArgs args = CallArgsFromVp(argc, vp); \
+ if(!args.thisv().isObject() || !IsTypedDatum(args.thisv().toObject())) { \
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, \
+ X4Type::class_.name, "signMask", \
+ InformalValueTypeName(args.thisv())); \
+ return false; \
+ } \
+ TypedDatum &datum = AsTypedDatum(args.thisv().toObject()); \
+ TypeRepresentation *typeRepr = datum.datumTypeRepresentation(); \
+ if (typeRepr->kind() != TypeRepresentation::X4 || typeRepr->asX4()->type() != Type32x4::type) { \
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, \
+ X4Type::class_.name, "signMask", \
+ InformalValueTypeName(args.thisv())); \
+ return false; \
+ } \
+ Type32x4::Elem *data = reinterpret_cast(datum.typedMem()); \
+ int32_t mx = data[0] < 0.0 ? 1 : 0; \
+ int32_t my = data[1] < 0.0 ? 1 : 0; \
+ int32_t mz = data[2] < 0.0 ? 1 : 0; \
+ int32_t mw = data[3] < 0.0 ? 1 : 0; \
+ int32_t result = mx | my << 1 | mz << 2 | mw << 3; \
+ args.rval().setInt32(result); \
+ return true; \
+ }
+ SIGN_MASK(Float32x4);
+ SIGN_MASK(Int32x4);
+#undef SIGN_MASK
+
+const Class X4Type::class_ = {
+ "X4",
+ JSCLASS_HAS_RESERVED_SLOTS(JS_TYPEOBJ_X4_SLOTS),
+ JS_PropertyStub, /* addProperty */
+ JS_DeletePropertyStub, /* delProperty */
+ JS_PropertyStub, /* getProperty */
+ JS_StrictPropertyStub, /* setProperty */
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ JS_ConvertStub,
+ nullptr, /* finalize */
+ nullptr, /* checkAccess */
+ call, /* call */
+ nullptr, /* hasInstance */
+ nullptr, /* construct */
+ nullptr
+};
+
+// These classes just exist to group together various properties and so on.
+namespace js {
+class Int32x4Defn {
+ public:
+ static const X4TypeRepresentation::Type type = X4TypeRepresentation::TYPE_INT32;
+ static const JSFunctionSpec TypeDescriptorMethods[];
+ static const JSPropertySpec TypeObjectProperties[];
+ static const JSFunctionSpec TypeObjectMethods[];
+};
+class Float32x4Defn {
+ public:
+ static const X4TypeRepresentation::Type type = X4TypeRepresentation::TYPE_FLOAT32;
+ static const JSFunctionSpec TypeDescriptorMethods[];
+ static const JSPropertySpec TypeObjectProperties[];
+ static const JSFunctionSpec TypeObjectMethods[];
+};
+} // namespace js
+
+const JSFunctionSpec js::Float32x4Defn::TypeDescriptorMethods[] = {
+ JS_FN("toSource", TypeObjectToSource, 0, 0),
+ JS_SELF_HOSTED_FN("handle", "HandleCreate", 2, 0),
+ JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, 0),
+ JS_SELF_HOSTED_FN("equivalent", "TypeObjectEquivalent", 1, 0),
+ JS_FS_END
+};
+
+const JSPropertySpec js::Float32x4Defn::TypeObjectProperties[] = {
+ JS_PSG("x", Float32x4Lane0, JSPROP_PERMANENT),
+ JS_PSG("y", Float32x4Lane1, JSPROP_PERMANENT),
+ JS_PSG("z", Float32x4Lane2, JSPROP_PERMANENT),
+ JS_PSG("w", Float32x4Lane3, JSPROP_PERMANENT),
+ JS_PSG("signMask", Float32x4SignMask, JSPROP_PERMANENT),
+ JS_PS_END
+};
+
+const JSFunctionSpec js::Float32x4Defn::TypeObjectMethods[] = {
+ JS_SELF_HOSTED_FN("toSource", "X4ToSource", 0, 0),
+ JS_FS_END
+};
+
+const JSFunctionSpec js::Int32x4Defn::TypeDescriptorMethods[] = {
+ JS_FN("toSource", TypeObjectToSource, 0, 0),
+ JS_SELF_HOSTED_FN("handle", "HandleCreate", 2, 0),
+ JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, 0),
+ JS_SELF_HOSTED_FN("equivalent", "TypeObjectEquivalent", 1, 0),
+ JS_FS_END,
+};
+
+const JSPropertySpec js::Int32x4Defn::TypeObjectProperties[] = {
+ JS_PSG("x", Int32x4Lane0, JSPROP_PERMANENT),
+ JS_PSG("y", Int32x4Lane1, JSPROP_PERMANENT),
+ JS_PSG("z", Int32x4Lane2, JSPROP_PERMANENT),
+ JS_PSG("w", Int32x4Lane3, JSPROP_PERMANENT),
+ JS_PSG("signMask", Int32x4SignMask, JSPROP_PERMANENT),
+ JS_PS_END
+};
+
+const JSFunctionSpec js::Int32x4Defn::TypeObjectMethods[] = {
+ JS_SELF_HOSTED_FN("toSource", "X4ToSource", 0, 0),
+ JS_FS_END
+};
+
+template
+static JSObject *
+CreateX4Class(JSContext *cx, Handle global)
+{
+ RootedObject funcProto(cx, global->getOrCreateFunctionPrototype(cx));
+ if (!funcProto)
+ return nullptr;
+
+ // Create type representation.
+
+ RootedObject typeReprObj(cx);
+ typeReprObj = X4TypeRepresentation::Create(cx, T::type);
+ if (!typeReprObj)
+ return nullptr;
+
+ // Create prototype property, which inherits from Object.prototype.
+
+ RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
+ if (!objProto)
+ return nullptr;
+ RootedObject proto(cx);
+ proto = NewObjectWithGivenProto(cx, &JSObject::class_, objProto, global, SingletonObject);
+ if (!proto)
+ return nullptr;
+
+ // Create type constructor itself.
+
+ RootedObject x4(cx);
+ x4 = NewObjectWithClassProto(cx, &X4Type::class_, funcProto, global);
+ if (!x4 ||
+ !InitializeCommonTypeDescriptorProperties(cx, x4, typeReprObj) ||
+ !DefinePropertiesAndBrand(cx, proto, nullptr, nullptr))
+ {
+ return nullptr;
+ }
+
+ // Link type constructor to the type representation.
+
+ x4->initReservedSlot(JS_TYPEOBJ_SLOT_TYPE_REPR, ObjectValue(*typeReprObj));
+
+ // Link constructor to prototype and install properties.
+
+ if (!JS_DefineFunctions(cx, x4, T::TypeDescriptorMethods))
+ return nullptr;
+
+ if (!LinkConstructorAndPrototype(cx, x4, proto) ||
+ !DefinePropertiesAndBrand(cx, proto, T::TypeObjectProperties,
+ T::TypeObjectMethods))
+ {
+ return nullptr;
+ }
+
+ return x4;
+}
+
+bool
+X4Type::call(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+ const uint32_t LANES = 4;
+
+ if (args.length() < LANES) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
+ args.callee().getClass()->name, "3", "s");
+ return false;
+ }
+
+ double values[LANES];
+ for (uint32_t i = 0; i < LANES; i++) {
+ if (!ToNumber(cx, args[i], &values[i]))
+ return false;
+ }
+
+ RootedObject typeObj(cx, &args.callee());
+ Rooted result(cx, TypedObject::createZeroed(cx, typeObj, 0));
+ if (!result)
+ return false;
+
+ X4TypeRepresentation *typeRepr = typeRepresentation(*typeObj)->asX4();
+ switch (typeRepr->type()) {
+#define STORE_LANES(_constant, _type, _name) \
+ case _constant: \
+ { \
+ _type *mem = reinterpret_cast<_type*>(result->typedMem()); \
+ for (uint32_t i = 0; i < LANES; i++) { \
+ mem[i] = ConvertScalar<_type>(values[i]); \
+ } \
+ break; \
+ }
+ JS_FOR_EACH_X4_TYPE_REPR(STORE_LANES)
+#undef STORE_LANES
+ }
+ args.rval().setObject(*result);
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// SIMD class
+
+const Class SIMDObject::class_ = {
+ "SIMD",
+ JSCLASS_HAS_CACHED_PROTO(JSProto_SIMD),
+ JS_PropertyStub, /* addProperty */
+ JS_DeletePropertyStub, /* delProperty */
+ JS_PropertyStub, /* getProperty */
+ JS_StrictPropertyStub, /* setProperty */
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ JS_ConvertStub,
+ nullptr, /* finalize */
+ nullptr, /* checkAccess */
+ nullptr, /* call */
+ nullptr, /* hasInstance */
+ nullptr, /* construct */
+ nullptr
+};
+
+JSObject *
+SIMDObject::initClass(JSContext *cx, Handle global)
+{
+ // Create SIMD Object.
+ RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
+ if(!objProto)
+ return nullptr;
+ RootedObject SIMD(cx, NewObjectWithGivenProto(cx, &SIMDObject::class_, objProto,
+ global, SingletonObject));
+ if (!SIMD)
+ return nullptr;
+
+ // float32x4
+
+ RootedObject float32x4Object(cx, CreateX4Class(cx, global));
+ if (!float32x4Object)
+ return nullptr;
+
+ // Define float32x4 functions and install as a property of the SIMD object.
+ global->setFloat32x4TypeObject(*float32x4Object);
+ RootedValue float32x4Value(cx, ObjectValue(*float32x4Object));
+ if (!JS_DefineFunctions(cx, float32x4Object, Float32x4Methods) ||
+ !JSObject::defineProperty(cx, SIMD, cx->names().float32x4,
+ float32x4Value, nullptr, nullptr,
+ JSPROP_READONLY | JSPROP_PERMANENT))
+ {
+ return nullptr;
+ }
+
+ // int32x4
+
+ RootedObject int32x4Object(cx, CreateX4Class(cx, global));
+ if (!int32x4Object)
+ return nullptr;
+
+ // Define int32x4 functions and install as a property of the SIMD object.
+ global->setInt32x4TypeObject(*int32x4Object);
+ RootedValue int32x4Value(cx, ObjectValue(*int32x4Object));
+ if (!JS_DefineFunctions(cx, int32x4Object, Int32x4Methods) ||
+ !JSObject::defineProperty(cx, SIMD, cx->names().int32x4,
+ int32x4Value, nullptr, nullptr,
+ JSPROP_READONLY | JSPROP_PERMANENT))
+ {
+ return nullptr;
+ }
+
+ RootedValue SIMDValue(cx, ObjectValue(*SIMD));
+ global->setConstructor(JSProto_SIMD, SIMDValue);
+
+ // Everything is set up, install SIMD on the global object.
+ if (!JSObject::defineProperty(cx, global, cx->names().SIMD, SIMDValue, nullptr, nullptr, 0)) {
+ return nullptr;
+ }
+
+ return SIMD;
+}
+
+JSObject *
+js_InitSIMDClass(JSContext *cx, HandleObject obj)
+{
+ JS_ASSERT(obj->is());
+ Rooted global(cx, &obj->as());
+ return SIMDObject::initClass(cx, global);
+}
+
+template
+static bool
+ObjectIsVector(JSObject &obj) {
+ if (!IsTypedDatum(obj))
+ return false;
+ TypeRepresentation *typeRepr = AsTypedDatum(obj).datumTypeRepresentation();
+ if (typeRepr->kind() != TypeRepresentation::X4)
+ return false;
+ return typeRepr->asX4()->type() == V::type;
+}
+
+template
+static JSObject *
+Create(JSContext *cx, typename V::Elem *data)
+{
+ RootedObject typeObj(cx, &V::GetTypeObject(*cx->global()));
+ JS_ASSERT(typeObj);
+
+ Rooted result(cx, TypedObject::createZeroed(cx, typeObj, 0));
+ if (!result)
+ return nullptr;
+
+ typename V::Elem *resultMem = reinterpret_cast(result->typedMem());
+ memcpy(resultMem, data, sizeof(typename V::Elem) * V::lanes);
+ return result;
+}
+
+namespace js {
+template
+struct Abs {
+ static inline T apply(T x, T zero) {return V::toType(x < 0 ? -1 * x : x);}
+};
+template
+struct Neg {
+ static inline T apply(T x, T zero) {return V::toType(-1 * x);}
+};
+template
+struct Not {
+ static inline T apply(T x, T zero) {return V::toType(~x);}
+};
+template
+struct Rec {
+ static inline T apply(T x, T zero) {return V::toType(1 / x);}
+};
+template
+struct RecSqrt {
+ static inline T apply(T x, T zero) {return V::toType(1 / sqrt(x));}
+};
+template
+struct Sqrt {
+ static inline T apply(T x, T zero) {return V::toType(sqrt(x));}
+};
+template
+struct Add {
+ static inline T apply(T l, T r) {return V::toType(l + r);}
+};
+template
+struct Sub {
+ static inline T apply(T l, T r) {return V::toType(l - r);}
+};
+template
+struct Div {
+ static inline T apply(T l, T r) {return V::toType(l / r);}
+};
+template
+struct Mul {
+ static inline T apply(T l, T r) {return V::toType(l * r);}
+};
+template
+struct Minimum {
+ static inline T apply(T l, T r) {return V::toType(l < r ? l : r);}
+};
+template
+struct Maximum {
+ static inline T apply(T l, T r) {return V::toType(l > r ? l : r);}
+};
+template
+struct LessThan {
+ static inline T apply(T l, T r) {return V::toType(l < r ? 0xFFFFFFFF: 0x0);}
+};
+template
+struct LessThanOrEqual {
+ static inline T apply(T l, T r) {return V::toType(l <= r ? 0xFFFFFFFF: 0x0);}
+};
+template
+struct GreaterThan {
+ static inline T apply(T l, T r) {return V::toType(l > r ? 0xFFFFFFFF: 0x0);}
+};
+template
+struct GreaterThanOrEqual {
+ static inline T apply(T l, T r) {return V::toType(l >= r ? 0xFFFFFFFF: 0x0);}
+};
+template
+struct Equal {
+ static inline T apply(T l, T r) {return V::toType(l == r ? 0xFFFFFFFF: 0x0);}
+};
+template
+struct NotEqual {
+ static inline T apply(T l, T r) {return V::toType(l != r ? 0xFFFFFFFF: 0x0);}
+};
+template
+struct Xor {
+ static inline T apply(T l, T r) {return V::toType(l ^ r);}
+};
+template
+struct And {
+ static inline T apply(T l, T r) {return V::toType(l & r);}
+};
+template
+struct Or {
+ static inline T apply(T l, T r) {return V::toType(l | r);}
+};
+template
+struct Scale {
+ static inline T apply(int32_t lane, T scalar, T x) {return V::toType(scalar * x);}
+};
+template
+struct WithX {
+ static inline T apply(int32_t lane, T scalar, T x) {return V::toType(lane == 0 ? scalar : x);}
+};
+template
+struct WithY {
+ static inline T apply(int32_t lane, T scalar, T x) {return V::toType(lane == 1 ? scalar : x);}
+};
+template
+struct WithZ {
+ static inline T apply(int32_t lane, T scalar, T x) {return V::toType(lane == 2 ? scalar : x);}
+};
+template
+struct WithW {
+ static inline T apply(int32_t lane, T scalar, T x) {return V::toType(lane == 3 ? scalar : x);}
+};
+template
+struct WithFlagX {
+ static inline T apply(T l, T f, T x) { return V::toType(l == 0 ? (f ? 0xFFFFFFFF : 0x0) : x);}
+};
+template
+struct WithFlagY {
+ static inline T apply(T l, T f, T x) { return V::toType(l == 1 ? (f ? 0xFFFFFFFF : 0x0) : x);}
+};
+template
+struct WithFlagZ {
+ static inline T apply(T l, T f, T x) { return V::toType(l == 2 ? (f ? 0xFFFFFFFF : 0x0) : x);}
+};
+template
+struct WithFlagW {
+ static inline T apply(T l, T f, T x) { return V::toType(l == 3 ? (f ? 0xFFFFFFFF : 0x0) : x);}
+};
+template
+struct Shuffle {
+ static inline int32_t apply(int32_t l, int32_t mask) {return V::toType((mask >> l) & 0x3);}
+};
+}
+
+template
+static bool
+Func(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ if (argc == 1) {
+ if((!args[0].isObject() || !ObjectIsVector(args[0].toObject()))) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+ typename V::Elem *val =
+ reinterpret_cast(AsTypedDatum(args[0].toObject()).typedMem());
+ typename Vret::Elem result[Vret::lanes];
+ for (int32_t i = 0; i < Vret::lanes; i++)
+ result[i] = Op::apply(val[i], 0);
+
+ RootedObject obj(cx, Create(cx, result));
+ if (!obj)
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+
+ } else if (argc == 2) {
+ if((!args[0].isObject() || !ObjectIsVector(args[0].toObject())) ||
+ (!args[1].isObject() || !ObjectIsVector(args[1].toObject())))
+ {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+
+ typename V::Elem *left =
+ reinterpret_cast(AsTypedDatum(args[0].toObject()).typedMem());
+ typename V::Elem *right =
+ reinterpret_cast(AsTypedDatum(args[1].toObject()).typedMem());
+
+ typename Vret::Elem result[Vret::lanes];
+ for (int32_t i = 0; i < Vret::lanes; i++)
+ result[i] = Op::apply(left[i], right[i]);
+
+ RootedObject obj(cx, Create(cx, result));
+ if (!obj)
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+ } else {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+}
+
+template
+static bool
+FuncWith(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ if ((argc != 2) ||
+ (!args[0].isObject() || !ObjectIsVector(args[0].toObject())) ||
+ (!args[1].isNumber() && !args[1].isBoolean()))
+ {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+
+ typename V::Elem *val =
+ reinterpret_cast(AsTypedDatum(args[0].toObject()).typedMem());
+
+ typename Vret::Elem result[Vret::lanes];
+ for (int32_t i = 0; i < Vret::lanes; i++) {
+ if(args[1].isNumber()) {
+ typename Vret::Elem arg1;
+ Vret::toType2(cx, args[1], &arg1);
+ result[i] = OpWith::apply(i, arg1, val[i]);
+ } else if (args[1].isBoolean()) {
+ result[i] = OpWith::apply(i, args[1].toBoolean(), val[i]);
+ }
+ }
+ RootedObject obj(cx, Create(cx, result));
+ if (!obj)
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+}
+
+template
+static bool
+FuncShuffle(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ if(argc == 2){
+ if ((!args[0].isObject() || !ObjectIsVector(args[0].toObject())) ||
+ (!args[1].isNumber()))
+ {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+
+ typename V::Elem *val =
+ reinterpret_cast(AsTypedDatum(args[0].toObject()).typedMem());
+ typename Vret::Elem result[Vret::lanes];
+ for (int32_t i = 0; i < Vret::lanes; i++) {
+ typename Vret::Elem arg1;
+ Vret::toType2(cx, args[1], &arg1);
+ result[i] = val[OpShuffle::apply(i * 2, arg1)];
+ }
+ RootedObject obj(cx, Create(cx, result));
+ if (!obj)
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+ } else if (argc == 3){
+ if ((!args[0].isObject() || !ObjectIsVector(args[0].toObject())) ||
+ (!args[1].isObject() || !ObjectIsVector(args[1].toObject())) ||
+ (!args[2].isNumber()))
+ {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+ typename V::Elem *val1 =
+ reinterpret_cast(AsTypedDatum(args[0].toObject()).typedMem());
+ typename V::Elem *val2 =
+ reinterpret_cast(AsTypedDatum(args[1].toObject()).typedMem());
+ typename Vret::Elem result[Vret::lanes];
+ for (int32_t i = 0; i < Vret::lanes; i++) {
+ typename Vret::Elem arg2;
+ Vret::toType2(cx, args[2], &arg2);
+ if(i < Vret::lanes / 2) {
+ result[i] = val1[OpShuffle::apply(i * 2, arg2)];
+ } else {
+ result[i] = val2[OpShuffle::apply(i * 2, arg2)];
+ }
+ }
+ RootedObject obj(cx, Create(cx, result));
+ if (!obj)
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+ } else {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+}
+
+template
+static bool
+FuncConvert(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ if ((argc != 1) ||
+ (!args[0].isObject() || !ObjectIsVector(args[0].toObject())))
+ {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+ typename V::Elem *val =
+ reinterpret_cast(AsTypedDatum(args[0].toObject()).typedMem());
+ typename Vret::Elem result[Vret::lanes];
+ for (int32_t i = 0; i < Vret::lanes; i++)
+ result[i] = static_cast(val[i]);
+
+ RootedObject obj(cx, Create(cx, result));
+ if (!obj)
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+}
+
+template
+static bool
+FuncConvertBits(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ if ((argc != 1) ||
+ (!args[0].isObject() || !ObjectIsVector(args[0].toObject())))
+ {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+ typename Vret::Elem *val =
+ reinterpret_cast(AsTypedDatum(args[0].toObject()).typedMem());
+
+ RootedObject obj(cx, Create(cx, val));
+ if (!obj)
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+}
+
+template
+static bool
+FuncZero(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ if (argc != 0) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+ typename Vret::Elem result[Vret::lanes];
+ for (int32_t i = 0; i < Vret::lanes; i++)
+ result[i] = static_cast(0);
+
+ RootedObject obj(cx, Create(cx, result));
+ if (!obj)
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+}
+
+template
+static bool
+FuncSplat(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ if ((argc != 1) || (!args[0].isNumber())) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+ typename Vret::Elem result[Vret::lanes];
+ for (int32_t i = 0; i < Vret::lanes; i++) {
+ typename Vret::Elem arg0;
+ Vret::toType2(cx, args[0], &arg0);
+ result[i] = static_cast(arg0);
+ }
+
+ RootedObject obj(cx, Create(cx, result));
+ if (!obj)
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+}
+
+static bool
+Int32x4Bool(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ if ((argc != 4) ||
+ (!args[0].isBoolean()) || !args[1].isBoolean() ||
+ (!args[2].isBoolean()) || !args[3].isBoolean())
+ {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+ int32_t result[Int32x4::lanes];
+ for (int32_t i = 0; i < Int32x4::lanes; i++)
+ result[i] = args[i].toBoolean() ? 0xFFFFFFFF : 0x0;
+
+ RootedObject obj(cx, Create(cx, result));
+ if (!obj)
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+}
+
+static bool
+Float32x4Clamp(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ if ((argc != 3) ||
+ (!args[0].isObject() || !ObjectIsVector(args[0].toObject())) ||
+ (!args[1].isObject() || !ObjectIsVector(args[1].toObject())) ||
+ (!args[2].isObject() || !ObjectIsVector(args[2].toObject())))
+ {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+ float *val = reinterpret_cast(AsTypedDatum(args[0].toObject()).typedMem());
+ float *lowerLimit = reinterpret_cast(AsTypedDatum(args[1].toObject()).typedMem());
+ float *upperLimit = reinterpret_cast(AsTypedDatum(args[2].toObject()).typedMem());
+
+ float result[Float32x4::lanes];
+ result[0] = val[0] < lowerLimit[0] ? lowerLimit[0] : val[0];
+ result[1] = val[1] < lowerLimit[1] ? lowerLimit[1] : val[1];
+ result[2] = val[2] < lowerLimit[2] ? lowerLimit[2] : val[2];
+ result[3] = val[3] < lowerLimit[3] ? lowerLimit[3] : val[3];
+ result[0] = result[0] > upperLimit[0] ? upperLimit[0] : result[0];
+ result[1] = result[1] > upperLimit[1] ? upperLimit[1] : result[1];
+ result[2] = result[2] > upperLimit[2] ? upperLimit[2] : result[2];
+ result[3] = result[3] > upperLimit[3] ? upperLimit[3] : result[3];
+ RootedObject obj(cx, Create(cx, result));
+ if (!obj)
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+}
+
+static bool
+Int32x4Select(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ if ((argc != 3) ||
+ (!args[0].isObject() || !ObjectIsVector(args[0].toObject())) ||
+ (!args[1].isObject() || !ObjectIsVector(args[1].toObject())) ||
+ (!args[2].isObject() || !ObjectIsVector(args[2].toObject())))
+ {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
+ return false;
+ }
+ int32_t *val = reinterpret_cast(AsTypedDatum(args[0].toObject()).typedMem());
+ int32_t *tv = reinterpret_cast(AsTypedDatum(args[1].toObject()).typedMem());
+ int32_t *fv = reinterpret_cast(AsTypedDatum(args[2].toObject()).typedMem());
+ int32_t tr[Int32x4::lanes];
+ for (int32_t i = 0; i < Int32x4::lanes; i++)
+ tr[i] = And::apply(val[i], tv[i]);
+ int32_t fr[Int32x4::lanes];
+ for (int32_t i = 0; i < Int32x4::lanes; i++)
+ fr[i] = And::apply(Not::apply(val[i], 0), fv[i]);
+ int32_t orInt[Int32x4::lanes];
+ for (int32_t i = 0; i < Int32x4::lanes; i++)
+ orInt[i] = Or::apply(tr[i], fr[i]);
+ float *result[Float32x4::lanes];
+ *result = reinterpret_cast(&orInt);
+ RootedObject obj(cx, Create(cx, *result));
+ if (!obj)
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+}
+
+const JSFunctionSpec js::Float32x4Methods[] = {
+ JS_FN("abs", (Func, Float32x4>), 1, 0),
+ JS_FN("neg", (Func, Float32x4>), 1, 0),
+ JS_FN("reciprocal", (Func, Float32x4>), 1, 0),
+ JS_FN("reciprocalSqrt", (Func, Float32x4>), 1, 0),
+ JS_FN("sqrt", (Func, Float32x4>), 1, 0),
+ JS_FN("add", (Func, Float32x4>), 2, 0),
+ JS_FN("sub", (Func, Float32x4>), 2, 0),
+ JS_FN("div", (Func, Float32x4>), 2, 0),
+ JS_FN("mul", (Func, Float32x4>), 2, 0),
+ JS_FN("max", (Func, Float32x4>), 2, 0),
+ JS_FN("min", (Func, Float32x4>), 2, 0),
+ JS_FN("lessThan", (Func, Int32x4>), 2, 0),
+ JS_FN("lessThanOrEqual", (Func, Int32x4>), 2, 0),
+ JS_FN("greaterThan", (Func, Int32x4>), 2, 0),
+ JS_FN("greaterThanOrEqual", (Func, Int32x4>), 2, 0),
+ JS_FN("equal", (Func, Int32x4>), 2, 0),
+ JS_FN("notEqual", (Func, Int32x4>), 2, 0),
+ JS_FN("withX", (FuncWith, Float32x4>), 2, 0),
+ JS_FN("withY", (FuncWith, Float32x4>), 2, 0),
+ JS_FN("withZ", (FuncWith, Float32x4>), 2, 0),
+ JS_FN("withW", (FuncWith, Float32x4>), 2, 0),
+ JS_FN("shuffle", (FuncShuffle, Float32x4>), 2, 0),
+ JS_FN("shuffleMix", (FuncShuffle, Float32x4>), 3, 0),
+ JS_FN("scale", (FuncWith, Float32x4>), 2, 0),
+ JS_FN("clamp", Float32x4Clamp, 3, 0),
+ JS_FN("toInt32x4", (FuncConvert), 1, 0),
+ JS_FN("bitsToInt32x4", (FuncConvertBits), 1, 0),
+ JS_FN("zero", (FuncZero), 0, 0),
+ JS_FN("splat", (FuncSplat), 0, 0),
+ JS_FS_END
+};
+
+const JSFunctionSpec js::Int32x4Methods[] = {
+ JS_FN("not", (Func, Int32x4>), 1, 0),
+ JS_FN("neg", (Func, Int32x4>), 1, 0),
+ JS_FN("add", (Func, Int32x4>), 2, 0),
+ JS_FN("sub", (Func, Int32x4>), 2, 0),
+ JS_FN("mul", (Func, Int32x4>), 2, 0),
+ JS_FN("xor", (Func, Int32x4>), 2, 0),
+ JS_FN("and", (Func, Int32x4>), 2, 0),
+ JS_FN("or", (Func, Int32x4>), 2, 0),
+ JS_FN("withX", (FuncWith, Int32x4>), 2, 0),
+ JS_FN("withY", (FuncWith, Int32x4>), 2, 0),
+ JS_FN("withZ", (FuncWith, Int32x4>), 2, 0),
+ JS_FN("withW", (FuncWith, Int32x4>), 2, 0),
+ JS_FN("withFlagX", (FuncWith, Int32x4>), 2, 0),
+ JS_FN("withFlagY", (FuncWith, Int32x4>), 2, 0),
+ JS_FN("withFlagZ", (FuncWith, Int32x4>), 2, 0),
+ JS_FN("withFlagW", (FuncWith, Int32x4>), 2, 0),
+ JS_FN("shuffle", (FuncShuffle, Int32x4>), 2, 0),
+ JS_FN("shuffleMix", (FuncShuffle, Int32x4>), 3, 0),
+ JS_FN("toFloat32x4", (FuncConvert), 1, 0),
+ JS_FN("bitsToFloat32x4", (FuncConvertBits), 1, 0),
+ JS_FN("zero", (FuncZero), 0, 0),
+ JS_FN("splat", (FuncSplat), 0, 0),
+ JS_FN("select", Int32x4Select, 3, 0),
+ JS_FN("bool", Int32x4Bool, 4, 0),
+ JS_FS_END
+};
diff --git a/js/src/builtin/SIMD.h b/js/src/builtin/SIMD.h
new file mode 100644
index 00000000000..b26ae5818c7
--- /dev/null
+++ b/js/src/builtin/SIMD.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef builtin_SIMD_h
+#define builtin_SIMD_h
+
+#include "jsapi.h"
+#include "jsobj.h"
+
+/*
+ * JS SIMD functions.
+ * Spec matching polyfill:
+ * https://github.com/johnmccutchan/ecmascript_simd/blob/master/src/ecmascript_simd.js
+ */
+
+namespace js {
+
+class SIMDObject : public JSObject
+{
+ public:
+ static const Class class_;
+ static JSObject* initClass(JSContext *cx, Handle global);
+ static bool toString(JSContext *cx, unsigned int argc, jsval *vp);
+};
+
+} /* namespace js */
+
+JSObject *
+js_InitSIMDClass(JSContext *cx, js::HandleObject obj);
+
+#endif /* builtin_SIMD_h */
diff --git a/js/src/builtin/TypeRepresentation.cpp b/js/src/builtin/TypeRepresentation.cpp
index 276a7f5c25f..10eedf9fee2 100644
--- a/js/src/builtin/TypeRepresentation.cpp
+++ b/js/src/builtin/TypeRepresentation.cpp
@@ -367,15 +367,13 @@ TypeRepresentation::addToTableOrFree(JSContext *cx,
Rooted global(cx, cx->global());
JSCompartment *comp = cx->compartment();
- // First, try to create the typed object to associate with this
+ // First, try to create the TI type object to associate with this
// type representation. Since nothing is in the table yet, if this
// fails we can just return and pretend this whole endeavor was
// just a bad dream.
RootedObject proto(cx);
const Class *clasp;
- if (!global->getTypedObjectModule().getSuitableClaspAndProto(cx, kind(),
- &clasp, &proto))
- {
+ if (!TypedObjectModuleObject::getSuitableClaspAndProto(cx, kind(), &clasp, &proto)) {
return nullptr;
}
RootedTypeObject typeObject(cx, comp->types.newTypeObject(cx, clasp, proto));
diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp
index 213ffed57f7..25ce74ed551 100644
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -63,88 +63,72 @@ ToObjectIfObject(HandleValue value)
return &value.toObject();
}
-static inline bool
-IsTypedDatum(JSObject &obj)
-{
- return obj.is() || obj.is();
-}
-
static inline uint8_t *
-TypedMem(JSObject &val)
+TypedMem(const JSObject &val)
{
JS_ASSERT(IsTypedDatum(val));
return (uint8_t*) val.getPrivate();
}
-static inline bool IsTypeObject(JSObject &type);
+static inline bool IsTypeObject(const JSObject &type);
-/*
- * Given a user-visible type descriptor object, returns the
- * owner object for the TypeRepresentation* that we use internally.
- */
-static JSObject *
-typeRepresentationOwnerObj(JSObject &typeObj)
+JSObject *
+js::typeRepresentationOwnerObj(const JSObject &typeObj)
{
JS_ASSERT(IsTypeObject(typeObj));
return &typeObj.getReservedSlot(JS_TYPEOBJ_SLOT_TYPE_REPR).toObject();
}
-/*
- * Given a user-visible type descriptor object, returns the
- * TypeRepresentation* that we use internally.
- *
- * Note: this pointer is valid only so long as `typeObj` remains rooted.
- */
-static TypeRepresentation *
-typeRepresentation(JSObject &typeObj)
+TypeRepresentation *
+js::typeRepresentation(const JSObject &typeObj)
{
return TypeRepresentation::fromOwnerObject(*typeRepresentationOwnerObj(typeObj));
}
static inline bool
-IsScalarTypeObject(JSObject &type)
+IsScalarTypeObject(const JSObject &type)
{
return type.hasClass(&ScalarType::class_);
}
static inline bool
-IsReferenceTypeObject(JSObject &type)
+IsReferenceTypeObject(const JSObject &type)
{
return type.hasClass(&ReferenceType::class_);
}
static inline bool
-IsSimpleTypeObject(JSObject &type)
+IsSimpleTypeObject(const JSObject &type)
{
return IsScalarTypeObject(type) || IsReferenceTypeObject(type);
}
static inline bool
-IsArrayTypeObject(JSObject &type)
+IsArrayTypeObject(const JSObject &type)
{
return type.hasClass(&ArrayType::class_);
}
static inline bool
-IsStructTypeObject(JSObject &type)
+IsStructTypeObject(const JSObject &type)
{
return type.hasClass(&StructType::class_);
}
static inline bool
-IsX4TypeObject(JSObject &type)
+IsX4TypeObject(const JSObject &type)
{
return type.hasClass(&X4Type::class_);
}
static inline bool
-IsComplexTypeObject(JSObject &type)
+IsComplexTypeObject(const JSObject &type)
{
return IsArrayTypeObject(type) || IsStructTypeObject(type);
}
static inline bool
-IsTypeObject(JSObject &type)
+IsTypeObject(const JSObject &type)
{
return IsScalarTypeObject(type) ||
IsReferenceTypeObject(type) ||
@@ -171,14 +155,14 @@ IsSizedTypeObject(JSObject &type)
}
static inline JSObject *
-GetType(JSObject &datum)
+GetType(const JSObject &datum)
{
JS_ASSERT(IsTypedDatum(datum));
return &datum.getReservedSlot(JS_DATUM_SLOT_TYPE_OBJ).toObject();
}
-static bool
-TypeObjectToSource(JSContext *cx, unsigned int argc, Value *vp)
+bool
+js::TypeObjectToSource(JSContext *cx, unsigned int argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
@@ -404,20 +388,6 @@ const JSFunctionSpec js::ScalarType::typeObjectMethods[] = {
JS_FS_END
};
-template
-static T ConvertScalar(double d)
-{
- if (TypeIsFloatingPoint()) {
- return T(d);
- } else if (TypeIsUnsigned()) {
- uint32_t n = ToUint32(d);
- return T(n);
- } else {
- int32_t n = ToInt32(d);
- return T(n);
- }
-}
-
bool
ScalarType::call(JSContext *cx, unsigned argc, Value *vp)
{
@@ -631,10 +601,10 @@ ArrayElementType(JSObject &array)
return &array.getReservedSlot(JS_TYPEOBJ_SLOT_ARRAY_ELEM_TYPE).toObject();
}
-static bool
-InitializeCommonTypeDescriptorProperties(JSContext *cx,
- HandleObject obj,
- HandleObject typeReprOwnerObj)
+bool
+js::InitializeCommonTypeDescriptorProperties(JSContext *cx,
+ HandleObject obj,
+ HandleObject typeReprOwnerObj)
{
TypeRepresentation *typeRepr =
TypeRepresentation::fromOwnerObject(*typeReprOwnerObj);
@@ -1174,183 +1144,6 @@ DefineSimpleTypeObject(JSContext *cx,
return true;
}
-///////////////////////////////////////////////////////////////////////////
-// X4
-
-const Class X4Type::class_ = {
- "X4",
- JSCLASS_HAS_RESERVED_SLOTS(JS_TYPEOBJ_X4_SLOTS),
- JS_PropertyStub,
- JS_DeletePropertyStub,
- JS_PropertyStub,
- JS_StrictPropertyStub,
- JS_EnumerateStub,
- JS_ResolveStub,
- JS_ConvertStub,
- nullptr,
- nullptr,
- call,
- nullptr,
- nullptr,
- nullptr
-};
-
-// These classes just exist to group together various properties and so on.
-namespace js {
-class Int32x4Defn {
- public:
- static const X4TypeRepresentation::Type type = X4TypeRepresentation::TYPE_INT32;
- static const JSFunctionSpec TypeDescriptorMethods[];
- static const JSPropertySpec TypedObjectProperties[];
- static const JSFunctionSpec TypedObjectMethods[];
-};
-class Float32x4Defn {
- public:
- static const X4TypeRepresentation::Type type = X4TypeRepresentation::TYPE_FLOAT32;
- static const JSFunctionSpec TypeDescriptorMethods[];
- static const JSPropertySpec TypedObjectProperties[];
- static const JSFunctionSpec TypedObjectMethods[];
-};
-} // namespace js
-
-const JSFunctionSpec js::Int32x4Defn::TypeDescriptorMethods[] = {
- JS_FN("toSource", TypeObjectToSource, 0, 0),
- {"handle", {nullptr, nullptr}, 2, 0, "HandleCreate"},
- {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
- {"equivalent", {nullptr, nullptr}, 1, 0, "TypeObjectEquivalent"},
- JS_FS_END
-};
-
-const JSPropertySpec js::Int32x4Defn::TypedObjectProperties[] = {
- JS_SELF_HOSTED_GET("x", "Int32x4Lane0", JSPROP_PERMANENT),
- JS_SELF_HOSTED_GET("y", "Int32x4Lane1", JSPROP_PERMANENT),
- JS_SELF_HOSTED_GET("z", "Int32x4Lane2", JSPROP_PERMANENT),
- JS_SELF_HOSTED_GET("w", "Int32x4Lane3", JSPROP_PERMANENT),
- JS_PS_END
-};
-
-const JSFunctionSpec js::Int32x4Defn::TypedObjectMethods[] = {
- JS_SELF_HOSTED_FN("toSource", "X4ToSource", 0, 0),
- JS_FS_END
-};
-
-const JSFunctionSpec js::Float32x4Defn::TypeDescriptorMethods[] = {
- JS_FN("toSource", TypeObjectToSource, 0, 0),
- {"handle", {nullptr, nullptr}, 2, 0, "HandleCreate"},
- {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
- {"equivalent", {nullptr, nullptr}, 1, 0, "TypeObjectEquivalent"},
- JS_FS_END
-};
-
-const JSPropertySpec js::Float32x4Defn::TypedObjectProperties[] = {
- JS_SELF_HOSTED_GET("x", "Float32x4Lane0", JSPROP_PERMANENT),
- JS_SELF_HOSTED_GET("y", "Float32x4Lane1", JSPROP_PERMANENT),
- JS_SELF_HOSTED_GET("z", "Float32x4Lane2", JSPROP_PERMANENT),
- JS_SELF_HOSTED_GET("w", "Float32x4Lane3", JSPROP_PERMANENT),
- JS_PS_END
-};
-
-const JSFunctionSpec js::Float32x4Defn::TypedObjectMethods[] = {
- JS_SELF_HOSTED_FN("toSource", "X4ToSource", 0, 0),
- JS_FS_END
-};
-
-template
-static JSObject *
-CreateX4Class(JSContext *cx, Handle global)
-{
- RootedObject funcProto(cx, global->getOrCreateFunctionPrototype(cx));
- if (!funcProto)
- return nullptr;
-
- // Create type representation
-
- RootedObject typeReprObj(cx);
- typeReprObj = X4TypeRepresentation::Create(cx, T::type);
- if (!typeReprObj)
- return nullptr;
-
- // Create prototype property, which inherits from Object.prototype
-
- RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
- if (!objProto)
- return nullptr;
- RootedObject proto(cx);
- proto = NewObjectWithGivenProto(cx, &JSObject::class_, objProto, global, SingletonObject);
- if (!proto)
- return nullptr;
-
- // Create type constructor itself
-
- RootedObject x4(cx);
- x4 = NewObjectWithClassProto(cx, &X4Type::class_, funcProto, global);
- if (!x4 ||
- !InitializeCommonTypeDescriptorProperties(cx, x4, typeReprObj) ||
- !DefinePropertiesAndBrand(cx, proto, nullptr, nullptr))
- {
- return nullptr;
- }
-
- // Link type constructor to the type representation
-
- x4->initReservedSlot(JS_TYPEOBJ_SLOT_TYPE_REPR, ObjectValue(*typeReprObj));
-
- // Link constructor to prototype and install properties
-
- if (!JS_DefineFunctions(cx, x4, T::TypeDescriptorMethods))
- return nullptr;
-
- if (!LinkConstructorAndPrototype(cx, x4, proto) ||
- !DefinePropertiesAndBrand(cx, proto, T::TypedObjectProperties,
- T::TypedObjectMethods))
- {
- return nullptr;
- }
-
- return x4;
-}
-
-bool
-X4Type::call(JSContext *cx, unsigned argc, Value *vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
- const uint32_t LANES = 4;
-
- if (args.length() < LANES) {
- JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
- args.callee().getClass()->name, "3", "s");
- return false;
- }
-
- double values[LANES];
- for (uint32_t i = 0; i < LANES; i++) {
- if (!ToNumber(cx, args[i], &values[i]))
- return false;
- }
-
- RootedObject typeObj(cx, &args.callee());
- RootedObject result(cx, TypedObject::createZeroed(cx, typeObj, 0));
- if (!result)
- return false;
-
- X4TypeRepresentation *typeRepr = typeRepresentation(*typeObj)->asX4();
- switch (typeRepr->type()) {
-#define STORE_LANES(_constant, _type, _name) \
- case _constant: \
- { \
- _type *mem = (_type*) TypedMem(*result); \
- for (uint32_t i = 0; i < LANES; i++) { \
- mem[i] = values[i]; \
- } \
- break; \
- }
- JS_FOR_EACH_X4_TYPE_REPR(STORE_LANES)
-#undef STORE_LANES
- }
- args.rval().setObject(*result);
- return true;
-}
-
///////////////////////////////////////////////////////////////////////////
template
@@ -1417,6 +1210,12 @@ DefineMetaTypeObject(JSContext *cx,
return ctor;
}
+/* The initialization strategy for TypedObjects is mildly unusual
+ * compared to other classes. Because all of the types are members
+ * of a single global, `TypedObject`, we basically make the
+ * initializer for the `TypedObject` class populate the
+ * `TypedObject` global (which is referred to as "module" herein).
+ */
bool
GlobalObject::initTypedObjectModule(JSContext *cx, Handle global)
{
@@ -1432,34 +1231,6 @@ GlobalObject::initTypedObjectModule(JSContext *cx, Handle global)
if (!JS_DefineFunctions(cx, module, TypedObjectMethods))
return false;
- RootedValue moduleValue(cx, ObjectValue(*module));
-
- global->setConstructor(JSProto_TypedObject, moduleValue);
- return true;
-}
-
-JSObject *
-js_InitTypedObjectModuleObject(JSContext *cx, HandleObject obj)
-{
- /*
- * The initialization strategy for TypedObjects is mildly unusual
- * compared to other classes. Because all of the types are members
- * of a single global, `TypedObject`, we basically make the
- * initialized for the `TypedObject` class populate the
- * `TypedObject` global (which is referred to as "module" herein).
- */
-
- JS_ASSERT(obj->is());
- Rooted global(cx, &obj->as());
-
- RootedObject module(cx, global->getOrCreateTypedObjectModule(cx));
- if (!module)
- return nullptr;
-
- // Define TypedObject global.
-
- RootedValue moduleValue(cx, ObjectValue(*module));
-
// uint8, uint16, any, etc
#define BINARYDATA_SCALAR_DEFINE(constant_, type_, name_) \
@@ -1476,38 +1247,6 @@ js_InitTypedObjectModuleObject(JSContext *cx, HandleObject obj)
JS_FOR_EACH_REFERENCE_TYPE_REPR(BINARYDATA_REFERENCE_DEFINE)
#undef BINARYDATA_REFERENCE_DEFINE
- // float32x4
-
- RootedObject float32x4Object(cx);
- float32x4Object = CreateX4Class(cx, global);
- if (!float32x4Object)
- return nullptr;
-
- RootedValue float32x4Value(cx, ObjectValue(*float32x4Object));
- if (!JSObject::defineProperty(cx, module, cx->names().float32x4,
- float32x4Value,
- nullptr, nullptr,
- JSPROP_READONLY | JSPROP_PERMANENT))
- {
- return nullptr;
- }
-
- // int32x4
-
- RootedObject int32x4Object(cx);
- int32x4Object = CreateX4Class(cx, global);
- if (!int32x4Object)
- return nullptr;
-
- RootedValue int32x4Value(cx, ObjectValue(*int32x4Object));
- if (!JSObject::defineProperty(cx, module, cx->names().int32x4,
- int32x4Value,
- nullptr, nullptr,
- JSPROP_READONLY | JSPROP_PERMANENT))
- {
- return nullptr;
- }
-
// ArrayType.
RootedObject arrayType(cx);
@@ -1557,15 +1296,27 @@ js_InitTypedObjectModuleObject(JSContext *cx, HandleObject obj)
}
// Everything is setup, install module on the global object:
+ RootedValue moduleValue(cx, ObjectValue(*module));
+ global->setConstructor(JSProto_TypedObject, moduleValue);
if (!JSObject::defineProperty(cx, global, cx->names().TypedObject,
moduleValue,
nullptr, nullptr,
0))
+ {
return nullptr;
+ }
return module;
}
+JSObject *
+js_InitTypedObjectModuleObject(JSContext *cx, HandleObject obj)
+{
+ JS_ASSERT(obj->is());
+ Rooted global(cx, &obj->as());
+ return global->getOrCreateTypedObjectModule(cx);
+}
+
JSObject *
js_InitTypedObjectDummy(JSContext *cx, HandleObject obj)
{
@@ -1578,41 +1329,56 @@ js_InitTypedObjectDummy(JSContext *cx, HandleObject obj)
MOZ_ASSUME_UNREACHABLE("shouldn't be initializing TypedObject via the JSProtoKey initializer mechanism");
}
-bool
+/*
+ * Each type repr has an associated TI type object (these will
+ * eventually be used as the TI type objects for type objects, though
+ * they are not now). To create these TI type objects, we need to know
+ * the clasp/proto of the type object for a particular kind. This
+ * accessor function returns those. In the case of the predefined type
+ * objects, like scalars/references/x4s, this is invoked while
+ * creating the typed object module, and thus does not require that
+ * the typed object module is fully initialized. For array types and
+ * struct types, it is invoked when the user creates an instance of
+ * those types (and hence requires that the typed object module is
+ * already initialized).
+ */
+/*static*/ bool
TypedObjectModuleObject::getSuitableClaspAndProto(JSContext *cx,
TypeRepresentation::Kind kind,
const Class **clasp,
MutableHandleObject proto)
{
+ Rooted global(cx, cx->global());
+ JS_ASSERT(global);
switch (kind) {
case TypeRepresentation::Scalar:
*clasp = &ScalarType::class_;
- proto.set(global().getOrCreateFunctionPrototype(cx));
+ proto.set(global->getOrCreateFunctionPrototype(cx));
break;
case TypeRepresentation::Reference:
*clasp = &ReferenceType::class_;
- proto.set(global().getOrCreateFunctionPrototype(cx));
+ proto.set(global->getOrCreateFunctionPrototype(cx));
break;
case TypeRepresentation::X4:
*clasp = &X4Type::class_;
- proto.set(global().getOrCreateFunctionPrototype(cx));
+ proto.set(global->getOrCreateFunctionPrototype(cx));
break;
case TypeRepresentation::Struct:
*clasp = &StructType::class_;
- proto.set(&getSlot(StructTypePrototype).toObject());
+ proto.set(&global->getTypedObjectModule().getSlot(StructTypePrototype).toObject());
break;
case TypeRepresentation::SizedArray:
*clasp = &ArrayType::class_;
- proto.set(&getSlot(ArrayTypePrototype).toObject());
+ proto.set(&global->getTypedObjectModule().getSlot(ArrayTypePrototype).toObject());
break;
case TypeRepresentation::UnsizedArray:
*clasp = &ArrayType::class_;
- proto.set(&getSlot(ArrayTypePrototype).toObject());
+ proto.set(&global->getTypedObjectModule().getSlot(ArrayTypePrototype).toObject());
break;
}
@@ -2454,6 +2220,18 @@ TypedDatum::dataOffset()
return JSObject::getPrivateDataOffset(JS_DATUM_SLOTS);
}
+TypeRepresentation *
+TypedDatum::datumTypeRepresentation() const
+{
+ return typeRepresentation(*GetType(*this));
+}
+
+uint8_t *
+TypedDatum::typedMem() const
+{
+ return TypedMem(*this);
+}
+
/******************************************************************************
* Typed Objects
*/
@@ -2854,10 +2632,31 @@ js::GetTypedObjectModule(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
Rooted global(cx, cx->global());
+ JS_ASSERT(global);
args.rval().setObject(global->getTypedObjectModule());
return true;
}
+bool
+js::GetFloat32x4TypeObject(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+ Rooted global(cx, cx->global());
+ JS_ASSERT(global);
+ args.rval().setObject(global->float32x4TypeObject());
+ return true;
+}
+
+bool
+js::GetInt32x4TypeObject(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+ Rooted global(cx, cx->global());
+ JS_ASSERT(global);
+ args.rval().setObject(global->int32x4TypeObject());
+ 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 8fd511c9eff..8812cc4faf8 100644
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -111,12 +111,52 @@ class TypedObjectModuleObject : public JSObject {
static const Class class_;
- bool getSuitableClaspAndProto(JSContext *cx,
- TypeRepresentation::Kind kind,
- const Class **clasp,
- MutableHandleObject proto);
+ static bool getSuitableClaspAndProto(JSContext *cx,
+ TypeRepresentation::Kind kind,
+ const Class **clasp,
+ MutableHandleObject proto);
};
+/*
+ * Helper method for converting a double into other scalar
+ * types in the same way that JavaScript would. In particular,
+ * simple C casting from double to int32_t gets things wrong
+ * for values like 0xF0000000.
+ */
+template
+static T ConvertScalar(double d)
+{
+ if (TypeIsFloatingPoint()) {
+ return T(d);
+ } else if (TypeIsUnsigned()) {
+ uint32_t n = ToUint32(d);
+ return T(n);
+ } else {
+ int32_t n = ToInt32(d);
+ return T(n);
+ }
+}
+
+/*
+ * Given a user-visible type descriptor object, returns the
+ * owner object for the TypeRepresentation* that we use internally.
+ */
+JSObject *typeRepresentationOwnerObj(const JSObject &typeObj);
+
+/*
+ * Given a user-visible type descriptor object, returns the
+ * TypeRepresentation* that we use internally.
+ *
+ * Note: this pointer is valid only so long as `typeObj` remains rooted.
+ */
+TypeRepresentation *typeRepresentation(const JSObject &typeObj);
+
+bool TypeObjectToSource(JSContext *cx, unsigned int argc, Value *vp);
+
+bool InitializeCommonTypeDescriptorProperties(JSContext *cx,
+ HandleObject obj,
+ HandleObject typeReprOwnerObj);
+
// Type for scalar type constructors like `uint8`. All such type
// constructors share a common js::Class and JSFunctionSpec. Scalar
// types are non-opaque (their storage is visible unless combined with
@@ -154,6 +194,7 @@ class X4Type : public JSObject
static const Class class_;
static bool call(JSContext *cx, unsigned argc, Value *vp);
+ static bool is(const Value &v);
};
/*
@@ -356,6 +397,9 @@ class TypedDatum : public JSObject
// Otherwise, use this to attach to memory referenced by another datum.
void attach(JSObject &datum, uint32_t offset);
+
+ TypeRepresentation *datumTypeRepresentation() const;
+ uint8_t *typedMem() const;
};
class TypedObject : public TypedDatum
@@ -381,6 +425,21 @@ class TypedHandle : public TypedDatum
static const JSFunctionSpec handleStaticMethods[];
};
+/*
+ * Because TypedDatum is a supertype of two concrete
+ * classes, we can't use JSObject.is() and JSObject.as(),
+ * so create two concrete casting operations.
+ */
+
+inline bool IsTypedDatum(const JSObject &obj) {
+ return obj.is() || obj.is();
+}
+
+inline TypedDatum &AsTypedDatum(JSObject &obj) {
+ JS_ASSERT(IsTypedDatum(obj));
+ return *static_cast(&obj);
+}
+
/*
* Usage: NewTypedHandle(typeObj)
*
@@ -485,6 +544,22 @@ extern const JSJitInfo MemcpyJitInfo;
*/
bool GetTypedObjectModule(JSContext *cx, unsigned argc, Value *vp);
+/*
+ * Usage: GetFloat32x4TypeObject()
+ *
+ * Returns the float32x4 type object. SIMD pseudo-module must have
+ * been initialized for this to be safe.
+ */
+bool GetFloat32x4TypeObject(JSContext *cx, unsigned argc, Value *vp);
+
+/*
+ * Usage: GetInt32x4TypeObject()
+ *
+ * Returns the int32x4 type object. SIMD pseudo-module must have
+ * been initialized for this to be safe.
+ */
+bool GetInt32x4TypeObject(JSContext *cx, unsigned argc, Value *vp);
+
/*
* Usage: Store_int8(targetDatum, targetOffset, value)
* ...
@@ -573,5 +648,8 @@ JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_LOAD_REFERENCE_CLASS_DEFN)
} // namespace js
+JSObject *
+js_InitTypedObjectModuleObject(JSContext *cx, JS::HandleObject obj);
+
#endif /* builtin_TypedObject_h */
diff --git a/js/src/builtin/TypedObject.js b/js/src/builtin/TypedObject.js
index 82d353ca3f6..c58531a29eb 100644
--- a/js/src/builtin/TypedObject.js
+++ b/js/src/builtin/TypedObject.js
@@ -282,21 +282,20 @@ TypedObjectPointer.prototype.getReference = function() {
TypedObjectPointer.prototype.getX4 = function() {
var type = REPR_TYPE(this.typeRepr);
- var T = GetTypedObjectModule();
switch (type) {
case JS_X4TYPEREPR_FLOAT32:
var x = Load_float32(this.datum, this.offset + 0);
var y = Load_float32(this.datum, this.offset + 4);
var z = Load_float32(this.datum, this.offset + 8);
var w = Load_float32(this.datum, this.offset + 12);
- return T.float32x4(x, y, z, w);
+ return GetFloat32x4TypeObject()(x, y, z, w);
case JS_X4TYPEREPR_INT32:
var x = Load_int32(this.datum, this.offset + 0);
var y = Load_int32(this.datum, this.offset + 4);
var z = Load_int32(this.datum, this.offset + 8);
var w = Load_int32(this.datum, this.offset + 12);
- return T.int32x4(x, y, z, w);
+ return GetInt32x4TypeObject()(x, y, z, w);
}
assert(false, "Unhandled x4 type: " + type);
@@ -721,42 +720,6 @@ function X4ProtoString(type) {
return undefined;
}
-var X4LaneStrings = ["x", "y", "z", "w"];
-
-// Generalized handler for the various properties for accessing a
-// single lane of an X4 vector value. Note that this is the slow path;
-// the fast path will be inlined into ion code.
-function X4GetLane(datum, type, lane) {
- if (!IsObject(datum) || !ObjectIsTypedDatum(datum))
- ThrowError(JSMSG_INCOMPATIBLE_PROTO, X4ProtoString(type),
- X4LaneStrings[lane], typeof this);
-
- var repr = DATUM_TYPE_REPR(datum);
- if (REPR_KIND(repr) != JS_TYPEREPR_X4_KIND || REPR_TYPE(repr) != type)
- ThrowError(JSMSG_INCOMPATIBLE_PROTO, X4ProtoString(type),
- X4LaneStrings[lane], typeof this);
-
- switch (type) {
- case JS_X4TYPEREPR_INT32:
- return Load_int32(datum, lane * 4);
- case JS_X4TYPEREPR_FLOAT32:
- return Load_float32(datum, lane * 4);
- }
-
- assert(false, "Unhandled type constant");
- return undefined;
-}
-
-function Float32x4Lane0() { return X4GetLane(this, JS_X4TYPEREPR_FLOAT32, 0); }
-function Float32x4Lane1() { return X4GetLane(this, JS_X4TYPEREPR_FLOAT32, 1); }
-function Float32x4Lane2() { return X4GetLane(this, JS_X4TYPEREPR_FLOAT32, 2); }
-function Float32x4Lane3() { return X4GetLane(this, JS_X4TYPEREPR_FLOAT32, 3); }
-
-function Int32x4Lane0() { return X4GetLane(this, JS_X4TYPEREPR_INT32, 0); }
-function Int32x4Lane1() { return X4GetLane(this, JS_X4TYPEREPR_INT32, 1); }
-function Int32x4Lane2() { return X4GetLane(this, JS_X4TYPEREPR_INT32, 2); }
-function Int32x4Lane3() { return X4GetLane(this, JS_X4TYPEREPR_INT32, 3); }
-
function X4ToSource() {
if (!IsObject(this) || !ObjectIsTypedDatum(this))
ThrowError(JSMSG_INCOMPATIBLE_PROTO, "X4", "toSource", typeof this);
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index ecca10928b9..8be17d4ca34 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -53,7 +53,10 @@
#include "builtin/Intl.h"
#include "builtin/MapObject.h"
#include "builtin/RegExp.h"
+#ifdef ENABLE_BINARYDATA
+#include "builtin/SIMD.h"
#include "builtin/TypedObject.h"
+#endif
#include "frontend/BytecodeCompiler.h"
#include "frontend/FullParseHandler.h" // for JS_BufferIsCompileableUnit
#include "frontend/Parser.h" // for JS_BufferIsCompileableUnit
@@ -1219,6 +1222,10 @@ static const JSStdName builtin_property_names[] = {
#if JS_HAS_UNEVAL
{js_InitStringClass, EAGER_ATOM(uneval), OCLASP(String)},
#endif
+#ifdef ENABLE_BINARYDATA
+ {js_InitSIMDClass, EAGER_ATOM(SIMD), OCLASP(SIMD)},
+ {js_InitTypedObjectModuleObject, EAGER_ATOM(TypedObject), OCLASP(TypedObjectModule)},
+#endif
{nullptr, 0, nullptr}
};
diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
index 9756702a520..2087b4d39da 100644
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -5561,12 +5561,19 @@ JS::GetGCNumber()
}
JS::AutoAssertNoGC::AutoAssertNoGC()
- : runtime(nullptr)
+ : runtime(nullptr), gcNumber(0)
{
js::PerThreadData *data = js::TlsPerThreadData.get();
if (data) {
- runtime = data->runtimeFromMainThread();
- gcNumber = runtime->gcNumber;
+ /*
+ * GC's from off-thread will always assert, so off-thread is implicitly
+ * AutoAssertNoGC. We still need to allow AutoAssertNoGC to be used in
+ * code that works from both threads, however. We also use this to
+ * annotate the off thread run loops.
+ */
+ runtime = data->runtimeIfOnOwnerThread();
+ if (runtime)
+ gcNumber = runtime->gcNumber;
}
}
@@ -5579,7 +5586,5 @@ JS::AutoAssertNoGC::~AutoAssertNoGC()
{
if (runtime)
MOZ_ASSERT(gcNumber == runtime->gcNumber, "GC ran inside an AutoAssertNoGC scope.");
- else
- MOZ_ASSERT(!js::TlsPerThreadData.get(), "Runtime created within AutoAssertNoGC scope?");
}
#endif
diff --git a/js/src/jsprototypes.h b/js/src/jsprototypes.h
index 447e080ca5f..91fdffc7a81 100644
--- a/js/src/jsprototypes.h
+++ b/js/src/jsprototypes.h
@@ -94,6 +94,7 @@
IF_INTL(real,imaginary) (Intl, 36, js_InitIntlClass, CLASP(Intl)) \
IF_BDATA(real,imaginary)(TypedObject, 37, js_InitTypedObjectModuleObject, OCLASP(TypedObjectModule)) \
imaginary(GeneratorFunction, 38, js_InitIteratorClasses, dummy) \
+IF_BDATA(real,imaginary)(SIMD, 39, js_InitSIMDClass, OCLASP(SIMD)) \
#define JS_FOR_EACH_PROTOTYPE(macro) JS_FOR_PROTOTYPES(macro,macro)
diff --git a/js/src/jsworkers.cpp b/js/src/jsworkers.cpp
index d1769e335d5..d7ddb1dde67 100644
--- a/js/src/jsworkers.cpp
+++ b/js/src/jsworkers.cpp
@@ -982,6 +982,7 @@ ScriptSource::getOffThreadCompressionChars(ExclusiveContext *cx)
void
WorkerThread::threadLoop()
{
+ JS::AutoAssertNoGC nogc;
WorkerThreadState &state = *runtime->workerThreadState;
AutoLockWorkerThreadState lock(state);
diff --git a/js/src/moz.build b/js/src/moz.build
index 40abf7cd92c..8c20db5dc8e 100644
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -97,6 +97,7 @@ UNIFIED_SOURCES += [
'builtin/MapObject.cpp',
'builtin/Object.cpp',
'builtin/Profilers.cpp',
+ 'builtin/SIMD.cpp',
'builtin/TestingFunctions.cpp',
'builtin/TypedObject.cpp',
'builtin/TypeRepresentation.cpp',
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4abs.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4abs.js
new file mode 100644
index 00000000000..3cf0e6ec4ee
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4abs.js
@@ -0,0 +1,24 @@
+//) |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 abs';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(-1, 2, -3, 4);
+ var c = SIMD.float32x4.abs(a);
+ assertEq(c.x, 1);
+ assertEq(c.y, 2);
+ assertEq(c.z, 3);
+ assertEq(c.w, 4);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4add.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4add.js
new file mode 100644
index 00000000000..11611caa788
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4add.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 add';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 2, 3, 4);
+ var b = float32x4(10, 20, 30, 40);
+ var c = SIMD.float32x4.add(a, b);
+ assertEq(c.x, 11);
+ assertEq(c.y, 22);
+ assertEq(c.z, 33);
+ assertEq(c.w, 44);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4alignment.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4alignment.js
index 6fa650e57f8..2af6d153a56 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/float32x4alignment.js
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4alignment.js
@@ -1,5 +1,7 @@
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
var BUGNUMBER = 938728;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
var summary = 'float32x4 alignment';
/*
@@ -9,7 +11,6 @@ var summary = 'float32x4 alignment';
var StructType = TypedObject.StructType;
var uint8 = TypedObject.uint8;
-var float32x4 = TypedObject.float32x4;
function test() {
print(BUGNUMBER + ": " + summary);
@@ -24,7 +25,6 @@ function test() {
if (typeof reportCompare === "function")
reportCompare(true, true);
- print("Tests complete");
}
test();
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4bitstoint32x4.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4bitstoint32x4.js
new file mode 100644
index 00000000000..00c815dc9d5
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4bitstoint32x4.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 bitsToInt32x4';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 2, 3, 4);
+ var c = SIMD.float32x4.bitsToInt32x4(a);
+ assertEq(c.x, 1065353216);
+ assertEq(c.y, 1073741824);
+ assertEq(c.z, 1077936128);
+ assertEq(c.w, 1082130432);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4clamp.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4clamp.js
new file mode 100644
index 00000000000..f74022fa4e7
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4clamp.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 add';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 2, 3, 4);
+ var b = float32x4(10, 20, 30, 40);
+ var c = SIMD.float32x4.add(a, b);
+ assertEq(c.x, 11);
+ assertEq(c.y, 22);
+ assertEq(c.z, 33);
+ assertEq(c.w, 44);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4div.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4div.js
new file mode 100644
index 00000000000..1841a779d2d
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4div.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 div';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 2, 3, 4);
+ var b = float32x4(10, 20, 30, 40);
+ var c = SIMD.float32x4.div(b,a);
+ assertEq(c.x, 10);
+ assertEq(c.y, 10);
+ assertEq(c.z, 10);
+ assertEq(c.w, 10);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4equal.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4equal.js
new file mode 100644
index 00000000000..96f3e0ce720
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4equal.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 equal';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 20, 30, 40);
+ var b = float32x4(10, 20, 30, 4);
+ var c = SIMD.float32x4.equal(a, b);
+ assertEq(c.x, 0);
+ assertEq(c.y, -1);
+ assertEq(c.z, -1);
+ assertEq(c.w, 0);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4getters.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4getters.js
index 51b69837465..ca157ab25ee 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/float32x4getters.js
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4getters.js
@@ -1,5 +1,7 @@
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
var BUGNUMBER = 938728;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
var summary = 'float32x4 getters';
/*
@@ -7,8 +9,6 @@ var summary = 'float32x4 getters';
* http://creativecommons.org/licenses/publicdomain/
*/
-var float32x4 = TypedObject.float32x4;
-
function test() {
print(BUGNUMBER + ": " + summary);
@@ -39,13 +39,12 @@ function test() {
g.call(v)
}, TypeError, "Getter applicable to structs");
assertThrowsInstanceOf(function() {
- var t = new TypedObject.int32x4(1, 2, 3, 4);
+ var t = new int32x4(1, 2, 3, 4);
g.call(t)
}, TypeError, "Getter applicable to int32x4");
if (typeof reportCompare === "function")
reportCompare(true, true);
- print("Tests complete");
}
test();
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4greaterthan.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4greaterthan.js
new file mode 100644
index 00000000000..e62f7bd9321
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4greaterthan.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 greaterThan';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 20, 3, 40);
+ var b = float32x4(10, 2, 30, 4);
+ var c = SIMD.float32x4.greaterThan(b,a);
+ assertEq(c.x, -1);
+ assertEq(c.y, 0);
+ assertEq(c.z, -1);
+ assertEq(c.w, 0);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4greaterthanorequal.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4greaterthanorequal.js
new file mode 100644
index 00000000000..bd0095371a7
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4greaterthanorequal.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 greaterThanOrEqual';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 20, 30, 40);
+ var b = float32x4(10, 20, 30, 4);
+ var c = SIMD.float32x4.greaterThanOrEqual(b,a);
+ assertEq(c.x, -1);
+ assertEq(c.y, -1);
+ assertEq(c.z, -1);
+ assertEq(c.w, 0);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4handle.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4handle.js
index efdd1b74771..36ca9a6215d 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/float32x4handle.js
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4handle.js
@@ -1,5 +1,7 @@
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
var BUGNUMBER = 938728;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
var summary = 'float32x4 handles';
/*
@@ -8,7 +10,7 @@ var summary = 'float32x4 handles';
*/
var ArrayType = TypedObject.ArrayType;
-var float32x4 = TypedObject.float32x4;
+
var float32 = TypedObject.float32;
var Handle = TypedObject.Handle;
@@ -43,7 +45,6 @@ function test() {
if (typeof reportCompare === "function")
reportCompare(true, true);
- print("Tests complete");
}
test();
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4lessthan.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4lessthan.js
new file mode 100644
index 00000000000..ddd18cb3f62
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4lessthan.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 lessThan';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 20, 3, 40);
+ var b = float32x4(10, 2, 30, 4);
+ var c = SIMD.float32x4.lessThan(a, b);
+ assertEq(c.x, -1);
+ assertEq(c.y, 0);
+ assertEq(c.z, -1);
+ assertEq(c.w, 0);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4lessthanorequal.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4lessthanorequal.js
new file mode 100644
index 00000000000..30e7834e653
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4lessthanorequal.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 lessThanOrEqual';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 20, 30, 40);
+ var b = float32x4(10, 20, 30, 4);
+ var c = SIMD.float32x4.lessThanOrEqual(a, b);
+ assertEq(c.x, -1);
+ assertEq(c.y, -1);
+ assertEq(c.z, -1);
+ assertEq(c.w, 0);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4max.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4max.js
new file mode 100644
index 00000000000..ffb1a91107f
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4max.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 max';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 20, 30, 4);
+ var b = float32x4(10, 2, 3, 40);
+ var c = SIMD.float32x4.max(a, b);
+ assertEq(c.x, 10);
+ assertEq(c.y, 20);
+ assertEq(c.z, 30);
+ assertEq(c.w, 40);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4min.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4min.js
new file mode 100644
index 00000000000..07c0b06afc7
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4min.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 min';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 20, 3, 40);
+ var b = float32x4(10, 2, 30, 4);
+ var c = SIMD.float32x4.min(a, b);
+ assertEq(c.x, 1);
+ assertEq(c.y, 2);
+ assertEq(c.z, 3);
+ assertEq(c.w, 4);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4mul.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4mul.js
new file mode 100644
index 00000000000..e2fd9bf8cf6
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4mul.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 add';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 2, 3, 4);
+ var b = float32x4(10, 20, 30, 40);
+ var c = SIMD.float32x4.mul(a, b);
+ assertEq(c.x, 10);
+ assertEq(c.y, 40);
+ assertEq(c.z, 90);
+ assertEq(c.w, 160);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4neg.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4neg.js
new file mode 100644
index 00000000000..3d92343fc8b
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4neg.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 neg';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 2, 3, 4);
+ var c = SIMD.float32x4.neg(a);
+ assertEq(c.x, -1);
+ assertEq(c.y, -2);
+ assertEq(c.z, -3);
+ assertEq(c.w, -4);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4notequal.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4notequal.js
new file mode 100644
index 00000000000..04b4187f8c7
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4notequal.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 notEqual';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 20, 30, 40);
+ var b = float32x4(10, 20, 30, 4);
+ var c = SIMD.float32x4.notEqual(a, b);
+ assertEq(c.x, -1);
+ assertEq(c.y, 0);
+ assertEq(c.z, 0);
+ assertEq(c.w, -1);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4reciprocal.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4reciprocal.js
new file mode 100644
index 00000000000..fb896fae96c
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4reciprocal.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 reciprocal';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 0.5, 0.25, 0.125);
+ var c = SIMD.float32x4.reciprocal(a);
+ assertEq(c.x, 1);
+ assertEq(c.y, 2);
+ assertEq(c.z, 4);
+ assertEq(c.w, 8);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4reciprocalsqrt.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4reciprocalsqrt.js
new file mode 100644
index 00000000000..9eb5712e3bf
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4reciprocalsqrt.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 reciprocalSqrt';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 1, 0.25, 0.25);
+ var c = SIMD.float32x4.reciprocalSqrt(a);
+ assertEq(c.x, 1);
+ assertEq(c.y, 1);
+ assertEq(c.z, 2);
+ assertEq(c.w, 2);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4reify.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4reify.js
index b51f1020e90..35e0afe6715 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/float32x4reify.js
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4reify.js
@@ -1,5 +1,7 @@
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
var BUGNUMBER = 938728;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
var summary = 'float32x4 reify';
/*
@@ -8,7 +10,6 @@ var summary = 'float32x4 reify';
*/
var ArrayType = TypedObject.ArrayType;
-var float32x4 = TypedObject.float32x4;
function test() {
print(BUGNUMBER + ": " + summary);
@@ -30,7 +31,6 @@ function test() {
if (typeof reportCompare === "function")
reportCompare(true, true);
- print("Tests complete");
}
test();
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4scale.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4scale.js
new file mode 100644
index 00000000000..bb9542a1f53
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4scale.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 scale';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 2, 3, 4);
+ var c = SIMD.float32x4.scale(a, 2);
+ assertEq(c.x, 2);
+ assertEq(c.y, 4);
+ assertEq(c.z, 6);
+ assertEq(c.w, 8);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4setter.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4setter.js
index b9b1f881a49..6879eb5616c 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/float32x4setter.js
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4setter.js
@@ -1,5 +1,7 @@
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
var BUGNUMBER = 938728;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
var summary = 'float32x4 setting';
/*
@@ -8,7 +10,6 @@ var summary = 'float32x4 setting';
*/
var ArrayType = TypedObject.ArrayType;
-var float32x4 = TypedObject.float32x4;
function test() {
print(BUGNUMBER + ": " + summary);
@@ -39,7 +40,6 @@ function test() {
if (typeof reportCompare === "function")
reportCompare(true, true);
- print("Tests complete");
}
test();
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4shuffle.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4shuffle.js
new file mode 100644
index 00000000000..4df7b9aa7ca
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4shuffle.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 shuffle';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 2, 3, 4);
+ var c = SIMD.float32x4.shuffle(a, 0x1B);
+ assertEq(c.x, 4);
+ assertEq(c.y, 3);
+ assertEq(c.z, 2);
+ assertEq(c.w, 1);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4shufflemix.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4shufflemix.js
new file mode 100644
index 00000000000..c81c547ad32
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4shufflemix.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 shuffleMix';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 2, 3, 4);
+ var b = float32x4(10, 20, 30, 40);
+ var c = SIMD.float32x4.shuffleMix(a,b, 0x1B);
+ assertEq(c.x, 4);
+ assertEq(c.y, 3);
+ assertEq(c.z, 20);
+ assertEq(c.w, 10);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4sqrt.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4sqrt.js
new file mode 100644
index 00000000000..833c2407a7a
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4sqrt.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 sqrt';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 4, 9, 16);
+ var c = SIMD.float32x4.sqrt(a);
+ assertEq(c.x, 1);
+ assertEq(c.y, 2);
+ assertEq(c.z, 3);
+ assertEq(c.w, 4);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4sub.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4sub.js
new file mode 100644
index 00000000000..4a56fcf28cb
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4sub.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 sub';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 2, 3, 4);
+ var b = float32x4(10, 20, 30, 40);
+ var c = SIMD.float32x4.sub(b,a);
+ assertEq(c.x, 9);
+ assertEq(c.y, 18);
+ assertEq(c.z, 27);
+ assertEq(c.w, 36);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4toint32x4.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4toint32x4.js
new file mode 100644
index 00000000000..e3d38455151
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4toint32x4.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 toInt32x4';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1.1, 2.2, 3.3, 4.6);
+ var c = SIMD.float32x4.toInt32x4(a);
+ assertEq(c.x, 1);
+ assertEq(c.y, 2);
+ assertEq(c.z, 3);
+ assertEq(c.w, 4);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/float32x4with.js b/js/src/tests/ecma_6/TypedObject/simd/float32x4with.js
new file mode 100644
index 00000000000..6bc19f16a2f
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4with.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 with';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(1, 2, 3, 4);
+ var x = SIMD.float32x4.withX(a, 5);
+ var y = SIMD.float32x4.withY(a, 5);
+ var z = SIMD.float32x4.withZ(a, 5);
+ var w = SIMD.float32x4.withW(a, 5);
+ assertEq(x.x, 5);
+ assertEq(y.y, 5);
+ assertEq(z.z, 5);
+ assertEq(w.w, 5);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4add.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4add.js
new file mode 100644
index 00000000000..1ae2cde801c
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4add.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 add';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var b = int32x4(10, 20, 30, 40);
+ var c = SIMD.int32x4.add(a, b);
+ assertEq(c.x, 11);
+ assertEq(c.y, 22);
+ assertEq(c.z, 33);
+ assertEq(c.w, 44);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4alignment.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4alignment.js
index 7a427cf10d7..cda4fa3e44e 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/int32x4alignment.js
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4alignment.js
@@ -1,5 +1,7 @@
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
var BUGNUMBER = 938728;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
var summary = 'int32x4 alignment';
/*
@@ -9,7 +11,6 @@ var summary = 'int32x4 alignment';
var StructType = TypedObject.StructType;
var uint8 = TypedObject.uint8;
-var int32x4 = TypedObject.int32x4;
function test() {
print(BUGNUMBER + ": " + summary);
@@ -24,7 +25,6 @@ function test() {
if (typeof reportCompare === "function")
reportCompare(true, true);
- print("Tests complete");
}
test();
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4and.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4and.js
new file mode 100644
index 00000000000..35b7aa000d1
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4and.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 and';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var b = int32x4(10, 20, 30, 40);
+ var c = SIMD.int32x4.and(a, b);
+ assertEq(c.x, 0);
+ assertEq(c.y, 0);
+ assertEq(c.z, 2);
+ assertEq(c.w, 0);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4bitstofloat32x4.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4bitstofloat32x4.js
new file mode 100644
index 00000000000..23f23d394e9
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4bitstofloat32x4.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 bitsToFloat32x4';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(100, 200, 300, 400);
+ var c = SIMD.int32x4.bitsToFloat32x4(a);
+ assertEq(c.x, 1.401298464324817e-43);
+ assertEq(c.y, 2.802596928649634e-43);
+ assertEq(c.z, 4.203895392974451e-43);
+ assertEq(c.w, 5.605193857299268e-43);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4getters.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4getters.js
index 4b99f13761a..3a83b7079aa 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/int32x4getters.js
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4getters.js
@@ -1,5 +1,8 @@
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
var BUGNUMBER = 938728;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+var {StructType, int32} = TypedObject;
var summary = 'int32x4 getters';
/*
@@ -7,8 +10,6 @@ var summary = 'int32x4 getters';
* http://creativecommons.org/licenses/publicdomain/
*/
-var int32x4 = TypedObject.int32x4;
-
function test() {
print(BUGNUMBER + ": " + summary);
@@ -31,21 +32,17 @@ function test() {
g.call(0xDEADBEEF)
}, TypeError, "Getter applicable to integers");
assertThrowsInstanceOf(function() {
- var T = new TypedObject.StructType({x: TypedObject.int32,
- y: TypedObject.int32,
- z: TypedObject.int32,
- w: TypedObject.int32});
+ var T = new StructType({x: int32, y: int32, z: int32, w: int32});
var v = new T({x: 11, y: 22, z: 33, w: 44});
g.call(v)
}, TypeError, "Getter applicable to structs");
assertThrowsInstanceOf(function() {
- var t = new TypedObject.float32x4(1, 2, 3, 4);
+ var t = new float32x4(1, 2, 3, 4);
g.call(t)
}, TypeError, "Getter applicable to float32x4");
if (typeof reportCompare === "function")
reportCompare(true, true);
- print("Tests complete");
}
test();
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4handle.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4handle.js
index 42de939c6c4..99a6cdbe51c 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/int32x4handle.js
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4handle.js
@@ -1,5 +1,7 @@
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
var BUGNUMBER = 938728;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
var summary = 'int32x4 handles';
/*
@@ -8,7 +10,6 @@ var summary = 'int32x4 handles';
*/
var ArrayType = TypedObject.ArrayType;
-var int32x4 = TypedObject.int32x4;
var int32 = TypedObject.int32;
var Handle = TypedObject.Handle;
@@ -43,7 +44,6 @@ function test() {
if (typeof reportCompare === "function")
reportCompare(true, true);
- print("Tests complete");
}
test();
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4mul.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4mul.js
new file mode 100644
index 00000000000..90f20ff6f87
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4mul.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 mul';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var b = int32x4(10, 20, 30, 40);
+ var c = SIMD.int32x4.mul(a, b);
+ assertEq(c.x, 10);
+ assertEq(c.y, 40);
+ assertEq(c.z, 90);
+ assertEq(c.w, 160);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4neg.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4neg.js
new file mode 100644
index 00000000000..831f6a8edc4
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4neg.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 neg';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var c = SIMD.int32x4.neg(a);
+ assertEq(c.x, -1);
+ assertEq(c.y, -2);
+ assertEq(c.z, -3);
+ assertEq(c.w, -4);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4not.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4not.js
new file mode 100644
index 00000000000..b4108f12a84
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4not.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 not';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var c = SIMD.int32x4.not(a);
+ assertEq(c.x, -2);
+ assertEq(c.y, -3);
+ assertEq(c.z, -4);
+ assertEq(c.w, -5);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4or.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4or.js
new file mode 100644
index 00000000000..5449f3ce990
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4or.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 or';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var b = int32x4(10, 20, 30, 40);
+ var c = SIMD.int32x4.or(a, b);
+ assertEq(c.x, 11);
+ assertEq(c.y, 22);
+ assertEq(c.z, 31);
+ assertEq(c.w, 44);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4reify.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4reify.js
index e7775d6701f..3b09d785a0d 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/int32x4reify.js
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4reify.js
@@ -1,5 +1,7 @@
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
var BUGNUMBER = 938728;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
var summary = 'int32x4 reify';
/*
@@ -8,7 +10,6 @@ var summary = 'int32x4 reify';
*/
var ArrayType = TypedObject.ArrayType;
-var int32x4 = TypedObject.int32x4;
function test() {
print(BUGNUMBER + ": " + summary);
@@ -30,7 +31,6 @@ function test() {
if (typeof reportCompare === "function")
reportCompare(true, true);
- print("Tests complete");
}
test();
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4select.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4select.js
new file mode 100644
index 00000000000..d3d6ee7da2b
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4select.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 select';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = float32x4(0.0,4.0,9.0,16.0)
+ var b = float32x4(1.0,2.0,3.0,4.0)
+ var sel_ttff = int32x4.bool(true, true, false, false);
+ var c = SIMD.int32x4.select(sel_ttff,a,b);
+ assertEq(c.x, 0);
+ assertEq(c.y, 4);
+ assertEq(c.z, 3);
+ assertEq(c.w, 4);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4setter.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4setter.js
index 9e4d7347f40..5e24fd23cd1 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/int32x4setter.js
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4setter.js
@@ -1,5 +1,7 @@
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
var BUGNUMBER = 938728;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
var summary = 'int32x4 setting';
/*
@@ -8,7 +10,6 @@ var summary = 'int32x4 setting';
*/
var ArrayType = TypedObject.ArrayType;
-var int32x4 = TypedObject.int32x4;
function test() {
print(BUGNUMBER + ": " + summary);
@@ -39,7 +40,6 @@ function test() {
if (typeof reportCompare === "function")
reportCompare(true, true);
- print("Tests complete");
}
test();
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4shuffle.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4shuffle.js
new file mode 100644
index 00000000000..bbd7312e6f4
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4shuffle.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 shuffle';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var c = SIMD.int32x4.shuffle(a, 0x1B);
+ assertEq(c.x, 4);
+ assertEq(c.y, 3);
+ assertEq(c.z, 2);
+ assertEq(c.w, 1);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4shufflemix.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4shufflemix.js
new file mode 100644
index 00000000000..21f9c91a235
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4shufflemix.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 shuffleMix';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var b = int32x4(10, 20, 30, 40);
+ var c = SIMD.int32x4.shuffleMix(a,b, 0x1B);
+ assertEq(c.x, 4);
+ assertEq(c.y, 3);
+ assertEq(c.z, 20);
+ assertEq(c.w, 10);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4sub.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4sub.js
new file mode 100644
index 00000000000..a427e714082
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4sub.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 sub';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var b = int32x4(10, 20, 30, 40);
+ var c = SIMD.int32x4.sub(b,a);
+ assertEq(c.x, 9);
+ assertEq(c.y, 18);
+ assertEq(c.z, 27);
+ assertEq(c.w, 36);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4tofloat32x4.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4tofloat32x4.js
new file mode 100644
index 00000000000..4999b17bfe2
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4tofloat32x4.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 toFloat32x4';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var c = SIMD.int32x4.toFloat32x4(a);
+ assertEq(c.x, 1);
+ assertEq(c.y, 2);
+ assertEq(c.z, 3);
+ assertEq(c.w, 4);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4with.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4with.js
new file mode 100644
index 00000000000..bb60a3170f7
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4with.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 with';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var x = SIMD.int32x4.withX(a, 5);
+ var y = SIMD.int32x4.withY(a, 5);
+ var z = SIMD.int32x4.withZ(a, 5);
+ var w = SIMD.int32x4.withW(a, 5);
+ assertEq(x.x, 5);
+ assertEq(y.y, 5);
+ assertEq(z.z, 5);
+ assertEq(w.w, 5);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4withflag.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4withflag.js
new file mode 100644
index 00000000000..3cb43b52441
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4withflag.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 with';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var x = SIMD.int32x4.withFlagX(a, true);
+ var y = SIMD.int32x4.withFlagY(a, false);
+ var z = SIMD.int32x4.withFlagZ(a, false);
+ var w = SIMD.int32x4.withFlagW(a, true);
+ assertEq(x.x, -1);
+ assertEq(y.y, 0);
+ assertEq(z.z, 0);
+ assertEq(w.w, -1);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/tests/ecma_6/TypedObject/simd/int32x4xor.js b/js/src/tests/ecma_6/TypedObject/simd/int32x4xor.js
new file mode 100644
index 00000000000..b6e7c1bdeb7
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/int32x4xor.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+var BUGNUMBER = 946042;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'int32x4 xor';
+
+function test() {
+ print(BUGNUMBER + ": " + summary);
+
+ // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+ var a = int32x4(1, 2, 3, 4);
+ var b = int32x4(10, 20, 30, 40);
+ var c = SIMD.int32x4.xor(a, b);
+ assertEq(c.x, 11);
+ assertEq(c.y, 22);
+ assertEq(c.z, 29);
+ assertEq(c.w, 44);
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+}
+
+test();
+
diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h
index 4d469eac385..18feb5d1d1e 100644
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -26,9 +26,6 @@ js_InitFunctionClass(JSContext *cx, js::HandleObject obj);
extern JSObject *
js_InitTypedArrayClasses(JSContext *cx, js::HandleObject obj);
-extern JSObject *
-js_InitTypedObjectModuleObject(JSContext *cx, js::HandleObject obj);
-
namespace js {
class Debugger;
@@ -111,9 +108,11 @@ class GlobalObject : public JSObject
static const unsigned RUNTIME_CODEGEN_ENABLED = WARNED_WATCH_DEPRECATED + 1;
static const unsigned DEBUGGERS = RUNTIME_CODEGEN_ENABLED + 1;
static const unsigned INTRINSICS = DEBUGGERS + 1;
+ static const unsigned FLOAT32X4_TYPE_OBJECT = INTRINSICS + 1;
+ static const unsigned INT32X4_TYPE_OBJECT = FLOAT32X4_TYPE_OBJECT + 1;
/* Total reserved-slot count for global objects. */
- static const unsigned RESERVED_SLOTS = INTRINSICS + 1;
+ static const unsigned RESERVED_SLOTS = INT32X4_TYPE_OBJECT + 1;
/*
* The slot count must be in the public API for JSCLASS_GLOBAL_FLAGS, and
@@ -416,6 +415,26 @@ class GlobalObject : public JSObject
return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_TypedObject, initTypedObjectModule);
}
+ void setFloat32x4TypeObject(JSObject &obj) {
+ JS_ASSERT(getSlotRef(FLOAT32X4_TYPE_OBJECT).isUndefined());
+ setSlot(FLOAT32X4_TYPE_OBJECT, ObjectValue(obj));
+ }
+
+ JSObject &float32x4TypeObject() {
+ JS_ASSERT(getSlotRef(FLOAT32X4_TYPE_OBJECT).isObject());
+ return getSlotRef(FLOAT32X4_TYPE_OBJECT).toObject();
+ }
+
+ void setInt32x4TypeObject(JSObject &obj) {
+ JS_ASSERT(getSlotRef(INT32X4_TYPE_OBJECT).isUndefined());
+ setSlot(INT32X4_TYPE_OBJECT, ObjectValue(obj));
+ }
+
+ JSObject &int32x4TypeObject() {
+ JS_ASSERT(getSlotRef(INT32X4_TYPE_OBJECT).isObject());
+ return getSlotRef(INT32X4_TYPE_OBJECT).toObject();
+ }
+
TypedObjectModuleObject &getTypedObjectModule() const;
JSObject *getIteratorPrototype() {
diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp
index 5b0eeb327f5..eb0b713edd9 100644
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -657,6 +657,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
JSNativeThreadSafeWrapper,
&js::MemcpyJitInfo, 5, 0),
JS_FN("GetTypedObjectModule", js::GetTypedObjectModule, 0, 0),
+ JS_FN("GetFloat32x4TypeObject", js::GetFloat32x4TypeObject, 0, 0),
+ JS_FN("GetInt32x4TypeObject", js::GetInt32x4TypeObject, 0, 0),
#define LOAD_AND_STORE_SCALAR_FN_DECLS(_constant, _type, _name) \
JS_FNINFO("Store_" #_name, \
diff --git a/js/xpconnect/idl/xpccomponents.idl b/js/xpconnect/idl/xpccomponents.idl
index 4f8679e2b2a..755c13e24d9 100644
--- a/js/xpconnect/idl/xpccomponents.idl
+++ b/js/xpconnect/idl/xpccomponents.idl
@@ -120,7 +120,7 @@ interface ScheduledGCCallback : nsISupports
/**
* interface of Components.utils
*/
-[scriptable, uuid(e14f588b-63aa-4091-be82-a459a52f8ca6)]
+[scriptable, uuid(ae292d08-cfb0-4862-a2b6-4779e5ef7e72)]
interface nsIXPCComponents_Utils : nsISupports
{
@@ -519,6 +519,17 @@ interface nsIXPCComponents_Utils : nsISupports
[implicit_jscontext]
jsval getIncumbentGlobal([optional] in jsval callback);
+ /**
+ * Forces the generation of an XPCWrappedJS for a given object. For internal
+ * and testing use only. This is only useful to set up wrapper map conditions
+ * for a testcase. The return value is not an XPCWrappedJS itself, but an
+ * opaque nsISupports holder that keeps the underlying XPCWrappedJS alive.
+ *
+ * if |scope| is passed, the XPCWrappedJS is generated in the scope of that object.
+ */
+ [implicit_jscontext]
+ nsISupports generateXPCWrappedJS(in jsval obj, [optional] in jsval scope);
+
/**
* Retrieve the last time, in microseconds since epoch, that a given
* watchdog-related event occured.
diff --git a/js/xpconnect/src/Sandbox.cpp b/js/xpconnect/src/Sandbox.cpp
index 098833cae34..2a1b9e5993e 100644
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1053,6 +1053,9 @@ xpc::CreateSandboxObject(JSContext *cx, MutableHandleValue vp, nsISupports *prin
compartmentOptions.setSameZoneAs(js::UncheckedUnwrap(options.sameZoneAs));
else
compartmentOptions.setZone(JS::SystemZone);
+
+ compartmentOptions.setInvisibleToDebugger(options.invisibleToDebugger);
+
RootedObject sandbox(cx, xpc::CreateGlobalObject(cx, &SandboxClass,
principal, compartmentOptions));
if (!sandbox)
@@ -1486,6 +1489,7 @@ SandboxOptions::Parse()
ParseBoolean("wantExportHelpers", &wantExportHelpers) &&
ParseString("sandboxName", sandboxName) &&
ParseObject("sameZoneAs", &sameZoneAs) &&
+ ParseBoolean("invisibleToDebugger", &invisibleToDebugger) &&
ParseGlobalProperties() &&
ParseValue("metadata", &metadata);
}
diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp
index 9f021cd3c78..155e7256095 100644
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3514,6 +3514,46 @@ nsXPCComponents_Utils::GetIncumbentGlobal(const Value &aCallback,
return NS_OK;
}
+/*
+ * Below is a bunch of awkward junk to allow JS test code to trigger the
+ * creation of an XPCWrappedJS, such that it ends up in the map. We need to
+ * hand the caller some sort of reference to hold onto (to prevent the
+ * refcount from dropping to zero as soon as the function returns), but trying
+ * to return a bonafide XPCWrappedJS to script causes all sorts of trouble. So
+ * we create a benign holder class instead, which acts as an opaque reference
+ * that script can use to keep the XPCWrappedJS alive and in the map.
+ */
+
+class WrappedJSHolder : public nsISupports
+{
+ NS_DECL_ISUPPORTS
+ WrappedJSHolder() {}
+ virtual ~WrappedJSHolder() {}
+
+ nsRefPtr mWrappedJS;
+};
+NS_IMPL_ISUPPORTS0(WrappedJSHolder);
+
+NS_IMETHODIMP
+nsXPCComponents_Utils::GenerateXPCWrappedJS(const Value &aObj, const Value &aScope,
+ JSContext *aCx, nsISupports **aOut)
+{
+ if (!aObj.isObject())
+ return NS_ERROR_INVALID_ARG;
+ RootedObject obj(aCx, &aObj.toObject());
+ RootedObject scope(aCx, aScope.isObject() ? js::UncheckedUnwrap(&aScope.toObject())
+ : CurrentGlobalOrNull(aCx));
+ JSAutoCompartment ac(aCx, scope);
+ if (!JS_WrapObject(aCx, &obj))
+ return NS_ERROR_FAILURE;
+
+ nsRefPtr holder = new WrappedJSHolder();
+ nsresult rv = nsXPCWrappedJS::GetNewOrUsed(obj, NS_GET_IID(nsISupports),
+ getter_AddRefs(holder->mWrappedJS));
+ holder.forget(aOut);
+ return rv;
+}
+
NS_IMETHODIMP
nsXPCComponents_Utils::GetWatchdogTimestamp(const nsAString& aCategory, PRTime *aOut)
{
diff --git a/js/xpconnect/src/XPCConvert.cpp b/js/xpconnect/src/XPCConvert.cpp
index 036a4295187..a0e6b707dda 100644
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -1028,10 +1028,16 @@ XPCConvert::JSObject2NativeInterface(void** dest, HandleObject src,
// else...
nsXPCWrappedJS* wrapper;
- nsresult rv = nsXPCWrappedJS::GetNewOrUsed(src, *iid, aOuter, &wrapper);
+ nsresult rv = nsXPCWrappedJS::GetNewOrUsed(src, *iid, &wrapper);
if (pErr)
*pErr = rv;
if (NS_SUCCEEDED(rv) && wrapper) {
+ // If the caller wanted to aggregate this JS object to a native,
+ // attach it to the wrapper. Note that we allow a maximum of one
+ // aggregated native for a given XPCWrappedJS.
+ if (aOuter)
+ wrapper->SetAggregatedNativeObject(aOuter);
+
// We need to go through the QueryInterface logic to make this return
// the right thing for the various 'special' interfaces; e.g.
// nsIPropertyBag. We must use AggregatedQueryInterface in cases where
@@ -1184,8 +1190,7 @@ XPCConvert::JSValToXPCException(MutableHandleValue s,
// lets try to build a wrapper around the JSObject
nsXPCWrappedJS* jswrapper;
nsresult rv =
- nsXPCWrappedJS::GetNewOrUsed(obj, NS_GET_IID(nsIException),
- nullptr, &jswrapper);
+ nsXPCWrappedJS::GetNewOrUsed(obj, NS_GET_IID(nsIException), &jswrapper);
if (NS_FAILED(rv))
return rv;
diff --git a/js/xpconnect/src/XPCJSWeakReference.cpp b/js/xpconnect/src/XPCJSWeakReference.cpp
index fecc8684872..49b97284b3d 100644
--- a/js/xpconnect/src/XPCJSWeakReference.cpp
+++ b/js/xpconnect/src/XPCJSWeakReference.cpp
@@ -43,7 +43,6 @@ nsresult xpcJSWeakReference::Init(JSContext* cx, const JS::Value& object)
nsRefPtr wrapped;
nsresult rv = nsXPCWrappedJS::GetNewOrUsed(obj,
NS_GET_IID(nsISupports),
- nullptr,
getter_AddRefs(wrapped));
if (!wrapped) {
NS_ERROR("can't get nsISupportsWeakReference wrapper for obj");
diff --git a/js/xpconnect/src/XPCQuickStubs.cpp b/js/xpconnect/src/XPCQuickStubs.cpp
index 67aa18a22b5..d1c3481991b 100644
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -735,8 +735,7 @@ xpc_qsUnwrapArgImpl(JSContext *cx,
}
nsRefPtr wrappedJS;
- rv = nsXPCWrappedJS::GetNewOrUsed(src, iid, nullptr,
- getter_AddRefs(wrappedJS));
+ rv = nsXPCWrappedJS::GetNewOrUsed(src, iid, getter_AddRefs(wrappedJS));
if (NS_FAILED(rv) || !wrappedJS) {
*ppArgRef = nullptr;
return rv;
diff --git a/js/xpconnect/src/XPCWrappedJS.cpp b/js/xpconnect/src/XPCWrappedJS.cpp
index 19e76142dd1..b6005e1a264 100644
--- a/js/xpconnect/src/XPCWrappedJS.cpp
+++ b/js/xpconnect/src/XPCWrappedJS.cpp
@@ -320,7 +320,6 @@ nsXPCWrappedJS::GetJSObject()
nsresult
nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj,
REFNSIID aIID,
- nsISupports* aOuter,
nsXPCWrappedJS** wrapperResult)
{
// Do a release-mode assert against accessing nsXPCWrappedJS off-main-thread.
@@ -364,8 +363,7 @@ nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj,
// build the root wrapper
if (rootJSObj == jsObj) {
// the root will do double duty as the interface wrapper
- wrapper = root = new nsXPCWrappedJS(cx, jsObj, clazz, nullptr,
- aOuter);
+ wrapper = root = new nsXPCWrappedJS(cx, jsObj, clazz, nullptr);
if (!root)
goto return_wrapper;
@@ -380,7 +378,7 @@ nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj,
if (!rootClazz)
goto return_wrapper;
- root = new nsXPCWrappedJS(cx, rootJSObj, rootClazz, nullptr, aOuter);
+ root = new nsXPCWrappedJS(cx, rootJSObj, rootClazz, nullptr);
NS_RELEASE(rootClazz);
if (!root)
@@ -397,7 +395,7 @@ nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj,
MOZ_ASSERT(clazz,"bad clazz");
if (!wrapper) {
- wrapper = new nsXPCWrappedJS(cx, jsObj, clazz, root, aOuter);
+ wrapper = new nsXPCWrappedJS(cx, jsObj, clazz, root);
if (!wrapper)
goto return_wrapper;
}
@@ -422,13 +420,12 @@ return_wrapper:
nsXPCWrappedJS::nsXPCWrappedJS(JSContext* cx,
JSObject* aJSObj,
nsXPCWrappedJSClass* aClass,
- nsXPCWrappedJS* root,
- nsISupports* aOuter)
+ nsXPCWrappedJS* root)
: mJSObj(aJSObj),
mClass(aClass),
mRoot(root ? root : MOZ_THIS_IN_INITIALIZER_LIST()),
mNext(nullptr),
- mOuter(root ? nullptr : aOuter)
+ mOuter(nullptr)
{
InitStub(GetClass()->GetIID());
@@ -439,7 +436,6 @@ nsXPCWrappedJS::nsXPCWrappedJS(JSContext* cx,
NS_ADDREF_THIS();
NS_ADDREF(aClass);
- NS_IF_ADDREF(mOuter);
if (!IsRootWrapper())
NS_ADDREF(mRoot);
diff --git a/js/xpconnect/src/XPCWrappedJSClass.cpp b/js/xpconnect/src/XPCWrappedJSClass.cpp
index 7be5a01d1e7..1bcb13e6f0c 100644
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -700,8 +700,7 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self,
// XPConvert::JSObject2NativeInterface() here to make sure we
// get a new (or used) nsXPCWrappedJS.
nsXPCWrappedJS* wrapper;
- nsresult rv = nsXPCWrappedJS::GetNewOrUsed(jsobj, aIID, nullptr,
- &wrapper);
+ nsresult rv = nsXPCWrappedJS::GetNewOrUsed(jsobj, aIID, &wrapper);
if (NS_SUCCEEDED(rv) && wrapper) {
// We need to go through the QueryInterface logic to make
// this return the right thing for the various 'special'
diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h
index fc8264b2fd3..3f40e2e8bcf 100644
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2474,7 +2474,6 @@ public:
static nsresult
GetNewOrUsed(JS::HandleObject aJSObj,
REFNSIID aIID,
- nsISupports* aOuter,
nsXPCWrappedJS** wrapper);
nsISomeInterface* GetXPTCStub() { return mXPTCStub; }
@@ -2509,6 +2508,15 @@ public:
bool IsAggregatedToNative() const {return mRoot->mOuter != nullptr;}
nsISupports* GetAggregatedNativeObject() const {return mRoot->mOuter;}
+ void SetAggregatedNativeObject(nsISupports *aNative) {
+ MOZ_ASSERT(aNative);
+ if (mRoot->mOuter) {
+ MOZ_ASSERT(mRoot->mOuter == aNative,
+ "Only one aggregated native can be set");
+ return;
+ }
+ NS_ADDREF(mRoot->mOuter = aNative);
+ }
void TraceJS(JSTracer* trc);
static void GetTraceName(JSTracer* trc, char *buf, size_t bufsize);
@@ -2519,8 +2527,7 @@ protected:
nsXPCWrappedJS(JSContext* cx,
JSObject* aJSObj,
nsXPCWrappedJSClass* aClass,
- nsXPCWrappedJS* root,
- nsISupports* aOuter);
+ nsXPCWrappedJS* root);
bool CanSkip();
void Destroy();
@@ -3425,6 +3432,7 @@ public:
, wantExportHelpers(false)
, proto(cx)
, sameZoneAs(cx)
+ , invisibleToDebugger(false)
, metadata(cx)
{ }
@@ -3436,6 +3444,7 @@ public:
JS::RootedObject proto;
nsCString sandboxName;
JS::RootedObject sameZoneAs;
+ bool invisibleToDebugger;
GlobalProperties globalProperties;
JS::RootedValue metadata;
diff --git a/js/xpconnect/tests/chrome/test_evalInSandbox.xul b/js/xpconnect/tests/chrome/test_evalInSandbox.xul
index 65c5651466c..75607cabce1 100644
--- a/js/xpconnect/tests/chrome/test_evalInSandbox.xul
+++ b/js/xpconnect/tests/chrome/test_evalInSandbox.xul
@@ -150,5 +150,26 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=533596
catch (e) {
ok(false, "sameZoneAs works");
}
+
+ Cu.import("resource://gre/modules/jsdebugger.jsm");
+ addDebuggerToGlobal(this);
+
+ try {
+ let dbg = new Debugger();
+ let sandbox = new Cu.Sandbox(this, { invisibleToDebugger: false });
+ dbg.addDebuggee(sandbox);
+ ok(true, "debugger added visible value");
+ } catch(e) {
+ ok(false, "debugger could not add visible value");
+ }
+
+ try {
+ let dbg = new Debugger();
+ let sandbox = new Cu.Sandbox(this, { invisibleToDebugger: true });
+ dbg.addDebuggee(sandbox);
+ ok(false, "debugger added invisible value");
+ } catch(e) {
+ ok(true, "debugger did not add invisible value");
+ }
]]>
diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp
index 885c8444d2d..ee428a0919f 100644
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -2700,6 +2700,17 @@ struct LineBoxInfo
nscoord mMaxLineBoxWidth;
};
+static void
+ChangeChildPaintingEnabled(nsIMarkupDocumentViewer* aChild, void* aClosure)
+{
+ bool* enablePainting = (bool*) aClosure;
+ if (*enablePainting) {
+ aChild->ResumePainting();
+ } else {
+ aChild->PausePainting();
+ }
+}
+
static void
ChangeChildMaxLineBoxWidth(nsIMarkupDocumentViewer* aChild, void* aClosure)
{
@@ -3126,7 +3137,36 @@ NS_IMETHODIMP nsDocumentViewer::AppendSubtree(nsTArrayPausePainting();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocumentViewer::ResumePainting()
+{
+ bool enablePaint = true;
+ CallChildren(ChangeChildPaintingEnabled, &enablePaint);
+
+ nsIPresShell* presShell = GetPresShell();
+ if (presShell) {
+ presShell->ResumePainting();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocumentViewer::ChangeMaxLineBoxWidth(int32_t aMaxLineBoxWidth)
{
// Change the max line box width for all children.
struct LineBoxInfo lbi = { aMaxLineBoxWidth };
diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h
index 30d4f602516..db9470f7b92 100644
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -129,10 +129,10 @@ typedef struct CapturingContentInfo {
} CapturingContentInfo;
-// f5b542a9-eaf0-4560-a656-37a9d379864c
+// 0e4f2b36-7ab8-43c5-b912-5c311566297c
#define NS_IPRESSHELL_IID \
-{ 0xf5b542a9, 0xeaf0, 0x4560, \
- { 0x37, 0xa9, 0xd3, 0x79, 0x86, 0x4c } }
+{ 0xde498c49, 0xf83f, 0x47bf, \
+ {0x8c, 0xc6, 0x8f, 0xf8, 0x74, 0x62, 0x22, 0x23 } }
// debug VerifyReflow flags
#define VERIFY_REFLOW_ON 0x01
@@ -836,6 +836,20 @@ public:
*/
bool IsPaintingSuppressed() const { return mPaintingSuppressed; }
+ /**
+ * Pause painting by freezing the refresh driver of this and all parent
+ * presentations. This may not have the desired effect if this pres shell
+ * has its own refresh driver.
+ */
+ virtual void PausePainting() = 0;
+
+ /**
+ * Resume painting by thawing the refresh driver of this and all parent
+ * presentations. This may not have the desired effect if this pres shell
+ * has its own refresh driver.
+ */
+ virtual void ResumePainting() = 0;
+
/**
* Unsuppress painting.
*/
@@ -1601,6 +1615,7 @@ protected:
bool mFontSizeInflationForceEnabled;
bool mFontSizeInflationDisabledInMasterProcess;
bool mFontSizeInflationEnabled;
+ bool mPaintingIsFrozen;
// Dirty bit indicating that mFontSizeInflationEnabled needs to be recomputed.
bool mFontSizeInflationEnabledIsDirty;
diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp
index a600299c2b9..b578f6d1670 100644
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -724,6 +724,8 @@ PresShell::PresShell()
"layout.reflow.synthMouseMove", true);
addedSynthMouseMove = true;
}
+
+ mPaintingIsFrozen = false;
}
NS_IMPL_ISUPPORTS7(PresShell, nsIPresShell, nsIDocumentObserver,
@@ -744,6 +746,13 @@ PresShell::~PresShell()
mLastCallbackEventRequest == nullptr,
"post-reflow queues not empty. This means we're leaking");
+ // Verify that if painting was frozen, but we're being removed from the tree,
+ // that we now re-enable painting on our refresh driver, since it may need to
+ // be re-used by another presentation.
+ if (mPaintingIsFrozen) {
+ mPresContext->RefreshDriver()->Thaw();
+ }
+
#ifdef DEBUG
MOZ_ASSERT(mPresArenaAllocCount == 0,
"Some pres arena objects were not freed");
@@ -9931,3 +9940,23 @@ nsIPresShell::SetMaxLineBoxWidth(nscoord aMaxLineBoxWidth)
FrameNeedsReflow(GetRootFrame(), eResize, NS_FRAME_HAS_DIRTY_CHILDREN);
}
}
+
+void
+PresShell::PausePainting()
+{
+ if (GetPresContext()->RefreshDriver()->PresContext() != GetPresContext())
+ return;
+
+ mPaintingIsFrozen = true;
+ GetPresContext()->RefreshDriver()->Freeze();
+}
+
+void
+PresShell::ResumePainting()
+{
+ if (GetPresContext()->RefreshDriver()->PresContext() != GetPresContext())
+ return;
+
+ mPaintingIsFrozen = false;
+ GetPresContext()->RefreshDriver()->Thaw();
+}
diff --git a/layout/base/nsPresShell.h b/layout/base/nsPresShell.h
index 8e14e4d8eef..932f9662bb7 100644
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -689,6 +689,9 @@ protected:
virtual void ThemeChanged() MOZ_OVERRIDE { mPresContext->ThemeChanged(); }
virtual void BackingScaleFactorChanged() MOZ_OVERRIDE { mPresContext->UIResolutionChanged(); }
+ virtual void PausePainting() MOZ_OVERRIDE;
+ virtual void ResumePainting() MOZ_OVERRIDE;
+
void UpdateImageVisibility();
nsRevocableEventPtr > mUpdateImageVisibilityEvent;
diff --git a/layout/reftests/flexbox/flexbox-box-sizing-on-container-horiz-1-ref.html b/layout/reftests/flexbox/flexbox-box-sizing-on-container-horiz-1-ref.html
new file mode 100644
index 00000000000..14359e5949e
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-box-sizing-on-container-horiz-1-ref.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/flexbox/flexbox-box-sizing-on-container-horiz-1.html b/layout/reftests/flexbox/flexbox-box-sizing-on-container-horiz-1.html
new file mode 100644
index 00000000000..5577d3efeb4
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-box-sizing-on-container-horiz-1.html
@@ -0,0 +1,37 @@
+
+
+
+
+ CSS Test: Testing a horizontal flex container with box-sizing:border-box
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/flexbox/flexbox-box-sizing-on-container-vert-1-ref.html b/layout/reftests/flexbox/flexbox-box-sizing-on-container-vert-1-ref.html
new file mode 100644
index 00000000000..f02e22d957d
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-box-sizing-on-container-vert-1-ref.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/flexbox/flexbox-box-sizing-on-container-vert-1.html b/layout/reftests/flexbox/flexbox-box-sizing-on-container-vert-1.html
new file mode 100644
index 00000000000..4eebed074a2
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-box-sizing-on-container-vert-1.html
@@ -0,0 +1,38 @@
+
+
+
+
+ CSS Test: Testing a horizontal flex container with box-sizing:border-box
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/flexbox/flexbox-box-sizing-on-items-horiz-1-ref.html b/layout/reftests/flexbox/flexbox-box-sizing-on-items-horiz-1-ref.html
new file mode 100644
index 00000000000..e4126b17c4d
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-box-sizing-on-items-horiz-1-ref.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/flexbox/flexbox-box-sizing-on-items-horiz-1a.html b/layout/reftests/flexbox/flexbox-box-sizing-on-items-horiz-1a.html
new file mode 100644
index 00000000000..491d1655759
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-box-sizing-on-items-horiz-1a.html
@@ -0,0 +1,60 @@
+
+
+
+
+ CSS Test: Testing a horizontal flex container with box-sizing:border-box on its flex items
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/flexbox/flexbox-box-sizing-on-items-horiz-1b.html b/layout/reftests/flexbox/flexbox-box-sizing-on-items-horiz-1b.html
new file mode 100644
index 00000000000..ee84b0d2427
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-box-sizing-on-items-horiz-1b.html
@@ -0,0 +1,60 @@
+
+
+
+
+ CSS Test: Testing a horizontal flex container with box-sizing:border-box on its flex items
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/flexbox/flexbox-box-sizing-on-items-vert-1-ref.html b/layout/reftests/flexbox/flexbox-box-sizing-on-items-vert-1-ref.html
new file mode 100644
index 00000000000..5d1f50af25a
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-box-sizing-on-items-vert-1-ref.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/flexbox/flexbox-box-sizing-on-items-vert-1a.html b/layout/reftests/flexbox/flexbox-box-sizing-on-items-vert-1a.html
new file mode 100644
index 00000000000..db263ed02b3
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-box-sizing-on-items-vert-1a.html
@@ -0,0 +1,61 @@
+
+
+
+
+ CSS Test: Testing a vertical flex container with box-sizing:border-box on its flex items
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/flexbox/flexbox-box-sizing-on-items-vert-1b.html b/layout/reftests/flexbox/flexbox-box-sizing-on-items-vert-1b.html
new file mode 100644
index 00000000000..a972959e75b
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-box-sizing-on-items-vert-1b.html
@@ -0,0 +1,61 @@
+
+
+
+
+ CSS Test: Testing a vertical flex container with box-sizing:border-box on its flex items
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/flexbox/reftest.list b/layout/reftests/flexbox/reftest.list
index 62a5fd053c8..3d07c2949de 100644
--- a/layout/reftests/flexbox/reftest.list
+++ b/layout/reftests/flexbox/reftest.list
@@ -47,6 +47,14 @@ fuzzy-if(B2G,10,3) random-if(winWidget) == flexbox-align-self-baseline-horiz-3.x
# fail until bug 794660 is fixed:
== flexbox-basic-video-vert-2.xhtml flexbox-basic-video-vert-2-ref.xhtml
+# Tests for box-sizing on flex containers and flex items.
+== flexbox-box-sizing-on-container-horiz-1.html flexbox-box-sizing-on-container-horiz-1-ref.html
+== flexbox-box-sizing-on-container-vert-1.html flexbox-box-sizing-on-container-vert-1-ref.html
+== flexbox-box-sizing-on-items-horiz-1a.html flexbox-box-sizing-on-items-horiz-1-ref.html
+== flexbox-box-sizing-on-items-horiz-1b.html flexbox-box-sizing-on-items-horiz-1-ref.html
+== flexbox-box-sizing-on-items-vert-1a.html flexbox-box-sizing-on-items-vert-1-ref.html
+== flexbox-box-sizing-on-items-vert-1b.html flexbox-box-sizing-on-items-vert-1-ref.html
+
# Tests for dynamic modifications of content inside/around a flex container
== flexbox-dyn-changeFrameWidth-1.xhtml flexbox-dyn-changeFrameWidth-1-ref.xhtml
== flexbox-dyn-changeFrameWidth-2.xhtml flexbox-dyn-changeFrameWidth-2-ref.xhtml
diff --git a/layout/svg/crashtests/952270-1.svg b/layout/svg/crashtests/952270-1.svg
new file mode 100644
index 00000000000..69bac47d42d
--- /dev/null
+++ b/layout/svg/crashtests/952270-1.svg
@@ -0,0 +1,9 @@
+
diff --git a/layout/svg/crashtests/crashtests.list b/layout/svg/crashtests/crashtests.list
index 1d8ac4167d7..644fe074f4c 100644
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -177,3 +177,4 @@ load 897342-1.svg
load 898909-1.svg
load 898951-1.svg
load 919371-1.xhtml
+load 952270-1.svg
diff --git a/layout/svg/nsSVGTextFrame2.cpp b/layout/svg/nsSVGTextFrame2.cpp
index 446f445ccc0..61f97c57dfa 100644
--- a/layout/svg/nsSVGTextFrame2.cpp
+++ b/layout/svg/nsSVGTextFrame2.cpp
@@ -4719,22 +4719,26 @@ nsSVGTextFrame2::GetTextPath(nsIFrame* aTextPathFrame)
{
nsIFrame *pathFrame = GetTextPathPathFrame(aTextPathFrame);
- if (pathFrame) {
- nsSVGPathGeometryElement *element =
- static_cast(pathFrame->GetContent());
-
- RefPtr path = element->GetPathForLengthOrPositionMeasuring();
-
- gfxMatrix matrix = element->PrependLocalTransformsTo(gfxMatrix());
- if (!matrix.IsIdentity()) {
- RefPtr builder =
- path->TransformedCopyToBuilder(ToMatrix(matrix));
- path = builder->Finish();
- }
-
- return path.forget();
+ if (!pathFrame) {
+ return nullptr;
}
- return nullptr;
+
+ nsSVGPathGeometryElement *element =
+ static_cast(pathFrame->GetContent());
+
+ RefPtr path = element->GetPathForLengthOrPositionMeasuring();
+ if (!path) {
+ return nullptr;
+ }
+
+ gfxMatrix matrix = element->PrependLocalTransformsTo(gfxMatrix());
+ if (!matrix.IsIdentity()) {
+ RefPtr builder =
+ path->TransformedCopyToBuilder(ToMatrix(matrix));
+ path = builder->Finish();
+ }
+
+ return path.forget();
}
gfxFloat
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c
index e654887e146..5cfc2fa2e20 100644
--- a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c
@@ -754,9 +754,6 @@ static void nr_ice_turn_allocated_cb(NR_SOCKET s, int how, void *cb_arg)
cand->label=label;
cand->state=NR_ICE_CAND_STATE_INITIALIZED;
- /* Execute the ready callback */
- cand->done_cb(0,0,cand->cb_arg);
-
/* We also need to activate the associated STUN candidate */
if(cand->u.relayed.srvflx_candidate){
nr_ice_candidate *cand2=cand->u.relayed.srvflx_candidate;
@@ -768,6 +765,10 @@ static void nr_ice_turn_allocated_cb(NR_SOCKET s, int how, void *cb_arg)
cand2->done_cb(0,0,cand2->cb_arg);
}
+ /* Execute the ready callback */
+ cand->done_cb(0,0,cand->cb_arg);
+ cand = 0;
+
break;
case NR_TURN_CLIENT_STATE_FAILED:
@@ -786,16 +787,18 @@ static void nr_ice_turn_allocated_cb(NR_SOCKET s, int how, void *cb_arg)
_status=0;
abort:
if(_status){
- r_log(NR_LOG_TURN, LOG_WARNING,
- "ICE-CANDIDATE(%s): nr_turn_allocated_cb failed", cand->label);
- cand->state=NR_ICE_CAND_STATE_FAILED;
- cand->done_cb(0,0,cand->cb_arg);
+ if (cand) {
+ r_log(NR_LOG_TURN, LOG_WARNING,
+ "ICE-CANDIDATE(%s): nr_turn_allocated_cb failed", cand->label);
+ cand->state=NR_ICE_CAND_STATE_FAILED;
+ cand->done_cb(0,0,cand->cb_arg);
- if(cand->u.relayed.srvflx_candidate){
- nr_ice_candidate *cand2=cand->u.relayed.srvflx_candidate;
+ if(cand->u.relayed.srvflx_candidate){
+ nr_ice_candidate *cand2=cand->u.relayed.srvflx_candidate;
- cand2->state=NR_ICE_CAND_STATE_FAILED;
- cand2->done_cb(0,0,cand2->cb_arg);
+ cand2->state=NR_ICE_CAND_STATE_FAILED;
+ cand2->done_cb(0,0,cand2->cb_arg);
+ }
}
}
}
diff --git a/mobile/android/base/gfx/JavaPanZoomController.java b/mobile/android/base/gfx/JavaPanZoomController.java
index f233516034e..95673aee07c 100644
--- a/mobile/android/base/gfx/JavaPanZoomController.java
+++ b/mobile/android/base/gfx/JavaPanZoomController.java
@@ -245,12 +245,16 @@ class JavaPanZoomController
final RectF zoomRect = new RectF(x, y,
x + (float)message.getDouble("w"),
y + (float)message.getDouble("h"));
- mTarget.post(new Runnable() {
- @Override
- public void run() {
- animatedZoomTo(zoomRect);
- }
- });
+ if (message.optBoolean("animate", true)) {
+ mTarget.post(new Runnable() {
+ @Override
+ public void run() {
+ animatedZoomTo(zoomRect);
+ }
+ });
+ } else {
+ mTarget.setViewportMetrics(getMetricsToZoomTo(zoomRect));
+ }
} else if (MESSAGE_ZOOM_PAGE.equals(event)) {
ImmutableViewportMetrics metrics = getMetrics();
RectF cssPageRect = metrics.getCssPageRect();
@@ -264,12 +268,16 @@ class JavaPanZoomController
y + dh/2,
cssPageRect.width(),
y + dh/2 + newHeight);
- mTarget.post(new Runnable() {
- @Override
- public void run() {
- animatedZoomTo(r);
- }
- });
+ if (message.optBoolean("animate", true)) {
+ mTarget.post(new Runnable() {
+ @Override
+ public void run() {
+ animatedZoomTo(r);
+ }
+ });
+ } else {
+ mTarget.setViewportMetrics(getMetricsToZoomTo(r));
+ }
} else if (MESSAGE_TOUCH_LISTENER.equals(event)) {
int tabId = message.getInt("tabID");
final Tab tab = Tabs.getInstance().getTab(tabId);
@@ -1399,7 +1407,7 @@ class JavaPanZoomController
* While we usually use device pixels, @zoomToRect must be specified in CSS
* pixels.
*/
- private boolean animatedZoomTo(RectF zoomToRect) {
+ private ImmutableViewportMetrics getMetricsToZoomTo(RectF zoomToRect) {
final float startZoom = getMetrics().zoomFactor;
RectF viewport = getMetrics().getViewport();
@@ -1434,8 +1442,11 @@ class JavaPanZoomController
// 2. now run getValidViewportMetrics on it, so that the target viewport is
// clamped down to prevent overscroll, over-zoom, and other bad conditions.
finalMetrics = getValidViewportMetrics(finalMetrics);
+ return finalMetrics;
+ }
- bounce(finalMetrics, PanZoomState.ANIMATED_ZOOM);
+ private boolean animatedZoomTo(RectF zoomToRect) {
+ bounce(getMetricsToZoomTo(zoomToRect), PanZoomState.ANIMATED_ZOOM);
return true;
}
diff --git a/mobile/android/base/tests/helpers/WaitHelper.java b/mobile/android/base/tests/helpers/WaitHelper.java
index 41ef3498913..ad7967a05ca 100644
--- a/mobile/android/base/tests/helpers/WaitHelper.java
+++ b/mobile/android/base/tests/helpers/WaitHelper.java
@@ -15,6 +15,8 @@ import org.mozilla.gecko.tests.UITestContext.ComponentType;
import com.jayway.android.robotium.solo.Condition;
import com.jayway.android.robotium.solo.Solo;
+import java.util.regex.Pattern;
+
/**
* Provides functionality related to waiting on certain events to happen.
*/
@@ -131,7 +133,7 @@ public final class WaitHelper {
ToolbarTitleTextChangeVerifier.class.getSimpleName() + ": ";
// A regex that matches the page title that shows up while the page is loading.
- private static final String LOADING_REGEX = "^[A-Za-z]{3,9}://";
+ private static final Pattern LOADING_PREFIX = Pattern.compile("[A-Za-z]{3,9}://");
private CharSequence mOldTitleText;
@@ -157,7 +159,7 @@ public final class WaitHelper {
// (e.g. the page title). However, the title is set to the URL before the title is
// loaded from the server and set as the final page title; we ignore the
// intermediate URL loading state here.
- final boolean isLoading = title.toString().matches(LOADING_REGEX);
+ final boolean isLoading = LOADING_PREFIX.matcher(title).lookingAt();
final boolean hasStateChanged = !isLoading && !mOldTitleText.equals(title);
if (hasStateChanged) {
diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js
index 6e6b640b19a..e9c897a8d39 100644
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -178,10 +178,20 @@ function doChangeMaxLineBoxWidth(aWidth) {
range = BrowserApp.selectedTab._mReflozPoint.range;
}
- docViewer.changeMaxLineBoxWidth(aWidth);
+ try {
+ docViewer.pausePainting();
+ docViewer.changeMaxLineBoxWidth(aWidth);
- if (range) {
- BrowserEventHandler._zoomInAndSnapToRange(range);
+ if (range) {
+ BrowserEventHandler._zoomInAndSnapToRange(range);
+ } else {
+ // In this case, we actually didn't zoom into a specific range. It
+ // probably happened from a page load reflow-on-zoom event, so we
+ // need to make sure painting is re-enabled.
+ BrowserApp.selectedTab.clearReflowOnZoomPendingActions();
+ }
+ } finally {
+ docViewer.resumePainting();
}
}
@@ -2744,6 +2754,7 @@ Tab.prototype = {
this.browser.addEventListener("MozApplicationManifest", this, true);
Services.obs.addObserver(this, "before-first-paint", false);
+ Services.obs.addObserver(this, "after-viewport-change", false);
Services.prefs.addObserver("browser.ui.zoom.force-user-scalable", this, false);
if (aParams.delayLoad) {
@@ -2803,21 +2814,58 @@ Tab.prototype = {
return minFontSize / this.getInflatedFontSizeFor(aElement);
},
+ clearReflowOnZoomPendingActions: function() {
+ // Reflow was completed, so now re-enable painting.
+ let webNav = BrowserApp.selectedTab.window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation);
+ let docShell = webNav.QueryInterface(Ci.nsIDocShell);
+ let docViewer = docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer);
+ docViewer.resumePainting();
+
+ BrowserApp.selectedTab._mReflozPositioned = false;
+ },
+
+ /**
+ * Reflow on zoom consists of a few different sub-operations:
+ *
+ * 1. When a double-tap event is seen, we verify that the correct preferences
+ * are enabled and perform the pre-position handling calculation. We also
+ * signal that reflow-on-zoom should be performed at this time, and pause
+ * painting.
+ * 2. During the next call to setViewport(), which is in the Tab prototype,
+ * we detect that a call to changeMaxLineBoxWidth should be performed. If
+ * we're zooming out, then the max line box width should be reset at this
+ * time. Otherwise, we call performReflowOnZoom.
+ * 2a. PerformReflowOnZoom() and resetMaxLineBoxWidth() schedule a call to
+ * doChangeMaxLineBoxWidth, based on a timeout specified in preferences.
+ * 3. doChangeMaxLineBoxWidth changes the line box width (which also
+ * schedules a reflow event), and then calls _zoomInAndSnapToRange.
+ * 4. _zoomInAndSnapToRange performs the positioning of reflow-on-zoom and
+ * then re-enables painting.
+ *
+ * Some of the events happen synchronously, while others happen asynchronously.
+ * The following is a rough sketch of the progression of events:
+ *
+ * double tap event seen -> onDoubleTap() -> ... asynchronous ...
+ * -> setViewport() -> performReflowOnZoom() -> ... asynchronous ...
+ * -> doChangeMaxLineBoxWidth() -> _zoomInAndSnapToRange()
+ * -> ... asynchronous ... -> setViewport() -> Observe('after-viewport-change')
+ * -> resumePainting()
+ */
performReflowOnZoom: function(aViewport) {
- let zoom = this._drawZoom ? this._drawZoom : aViewport.zoom;
+ let zoom = this._drawZoom ? this._drawZoom : aViewport.zoom;
- let viewportWidth = gScreenWidth / zoom;
- let reflozTimeout = Services.prefs.getIntPref("browser.zoom.reflowZoom.reflowTimeout");
+ let viewportWidth = gScreenWidth / zoom;
+ let reflozTimeout = Services.prefs.getIntPref("browser.zoom.reflowZoom.reflowTimeout");
- if (gReflowPending) {
- clearTimeout(gReflowPending);
- }
+ if (gReflowPending) {
+ clearTimeout(gReflowPending);
+ }
- // We add in a bit of fudge just so that the end characters
- // don't accidentally get clipped. 15px is an arbitrary choice.
- gReflowPending = setTimeout(doChangeMaxLineBoxWidth,
- reflozTimeout,
- viewportWidth - 15);
+ // We add in a bit of fudge just so that the end characters
+ // don't accidentally get clipped. 15px is an arbitrary choice.
+ gReflowPending = setTimeout(doChangeMaxLineBoxWidth,
+ reflozTimeout,
+ viewportWidth - 15);
},
/**
@@ -2889,6 +2937,7 @@ Tab.prototype = {
this.browser.removeEventListener("MozApplicationManifest", this, true);
Services.obs.removeObserver(this, "before-first-paint");
+ Services.obs.removeObserver(this, "after-viewport-change");
Services.prefs.removeObserver("browser.ui.zoom.force-user-scalable", this);
// Make sure the previously selected panel remains selected. The selected panel of a deck is
@@ -3175,13 +3224,21 @@ Tab.prototype = {
// In this case, the user pinch-zoomed in, so we don't want to
// preserve position as we would with reflow-on-zoom.
BrowserApp.selectedTab.probablyNeedRefloz = false;
+ BrowserApp.selectedTab.clearReflowOnZoomPendingActions();
BrowserApp.selectedTab._mReflozPoint = null;
}
+ let docViewer = null;
+
if (isZooming &&
BrowserEventHandler.mReflozPref &&
BrowserApp.selectedTab._mReflozPoint &&
BrowserApp.selectedTab.probablyNeedRefloz) {
+ let webNav = BrowserApp.selectedTab.window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation);
+ let docShell = webNav.QueryInterface(Ci.nsIDocShell);
+ docViewer = docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer);
+ docViewer.pausePainting();
+
BrowserApp.selectedTab.performReflowOnZoom(aViewport);
BrowserApp.selectedTab.probablyNeedRefloz = false;
}
@@ -3210,6 +3267,9 @@ Tab.prototype = {
aViewport.fixedMarginLeft / aViewport.zoom);
Services.obs.notifyObservers(null, "after-viewport-change", "");
+ if (docViewer) {
+ docViewer.resumePainting();
+ }
},
setResolution: function(aZoom, aForce) {
@@ -4166,6 +4226,11 @@ Tab.prototype = {
BrowserApp.selectedTab.performReflowOnZoom(vp);
}
break;
+ case "after-viewport-change":
+ if (BrowserApp.selectedTab._mReflozPositioned) {
+ BrowserApp.selectedTab.clearReflowOnZoomPendingActions();
+ }
+ break;
case "nsPref:changed":
if (aData == "browser.ui.zoom.force-user-scalable")
ViewportHandler.updateMetadata(this, false);
@@ -4484,13 +4549,23 @@ var BrowserEventHandler = {
if (BrowserEventHandler.mReflozPref &&
!BrowserApp.selectedTab._mReflozPoint &&
!this._shouldSuppressReflowOnZoom(element)) {
- let data = JSON.parse(aData);
- let zoomPointX = data.x;
- let zoomPointY = data.y;
- BrowserApp.selectedTab._mReflozPoint = { x: zoomPointX, y: zoomPointY,
- range: BrowserApp.selectedBrowser.contentDocument.caretPositionFromPoint(zoomPointX, zoomPointY) };
- BrowserApp.selectedTab.probablyNeedRefloz = true;
+ // See comment above performReflowOnZoom() for a detailed description of
+ // the events happening in the reflow-on-zoom operation.
+ let data = JSON.parse(aData);
+ let zoomPointX = data.x;
+ let zoomPointY = data.y;
+
+ BrowserApp.selectedTab._mReflozPoint = { x: zoomPointX, y: zoomPointY,
+ range: BrowserApp.selectedBrowser.contentDocument.caretPositionFromPoint(zoomPointX, zoomPointY) };
+
+ // Before we perform a reflow on zoom, let's disable painting.
+ let webNav = BrowserApp.selectedTab.window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation);
+ let docShell = webNav.QueryInterface(Ci.nsIDocShell);
+ let docViewer = docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer);
+ docViewer.pausePainting();
+
+ BrowserApp.selectedTab.probablyNeedRefloz = true;
}
if (!element) {
@@ -4590,11 +4665,7 @@ var BrowserEventHandler = {
},
_zoomInAndSnapToRange: function(aRange) {
- if (!aRange) {
- Cu.reportError("aRange is null in zoomInAndSnapToRange. Unable to maintain position.");
- return;
- }
-
+ // aRange is always non-null here, since a check happened previously.
let viewport = BrowserApp.selectedTab.getViewport();
let fudge = 15; // Add a bit of fudge.
let boundingElement = aRange.offsetNode;
@@ -4617,30 +4688,33 @@ var BrowserEventHandler = {
let leftAdjustment = parseInt(boundingStyle.paddingLeft) +
parseInt(boundingStyle.borderLeftWidth);
+ BrowserApp.selectedTab._mReflozPositioned = true;
+
rect.type = "Browser:ZoomToRect";
rect.x = Math.max(viewport.cssPageLeft, rect.x - fudge + leftAdjustment);
rect.y = Math.max(topPos, viewport.cssPageTop);
rect.w = viewport.cssWidth;
rect.h = viewport.cssHeight;
+ rect.animate = false;
sendMessageToJava(rect);
BrowserApp.selectedTab._mReflozPoint = null;
- },
+ },
- onPinchFinish: function(aData) {
- let data = {};
- try {
- data = JSON.parse(aData);
- } catch(ex) {
- console.log(ex);
- return;
- }
+ onPinchFinish: function(aData) {
+ let data = {};
+ try {
+ data = JSON.parse(aData);
+ } catch(ex) {
+ console.log(ex);
+ return;
+ }
- if (BrowserEventHandler.mReflozPref &&
- data.zoomDelta < 0.0) {
- BrowserEventHandler.resetMaxLineBoxWidth();
- }
- },
+ if (BrowserEventHandler.mReflozPref &&
+ data.zoomDelta < 0.0) {
+ BrowserEventHandler.resetMaxLineBoxWidth();
+ }
+ },
_shouldZoomToElement: function(aElement) {
let win = aElement.ownerDocument.defaultView;