summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/ctypes
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/ctypes')
-rw-r--r--js/src/jit-test/tests/ctypes/AddressOfField.js12
-rw-r--r--js/src/jit-test/tests/ctypes/argument-length-abi.js11
-rw-r--r--js/src/jit-test/tests/ctypes/argument-length-array.js15
-rw-r--r--js/src/jit-test/tests/ctypes/argument-length-cdata.js18
-rw-r--r--js/src/jit-test/tests/ctypes/argument-length-ctypes.js11
-rw-r--r--js/src/jit-test/tests/ctypes/argument-length-finalizer.js16
-rw-r--r--js/src/jit-test/tests/ctypes/argument-length-function.js11
-rw-r--r--js/src/jit-test/tests/ctypes/argument-length-int64.js40
-rw-r--r--js/src/jit-test/tests/ctypes/argument-length-pointer.js11
-rw-r--r--js/src/jit-test/tests/ctypes/argument-length-primitive.js11
-rw-r--r--js/src/jit-test/tests/ctypes/argument-length-struct.js17
-rw-r--r--js/src/jit-test/tests/ctypes/argument-type-array.js17
-rw-r--r--js/src/jit-test/tests/ctypes/argument-type-ctypes.js13
-rw-r--r--js/src/jit-test/tests/ctypes/argument-type-function.js9
-rw-r--r--js/src/jit-test/tests/ctypes/argument-type-int64.js28
-rw-r--r--js/src/jit-test/tests/ctypes/argument-type-pointer.js9
-rw-r--r--js/src/jit-test/tests/ctypes/argument-type-struct.js17
-rw-r--r--js/src/jit-test/tests/ctypes/array-index.js29
-rw-r--r--js/src/jit-test/tests/ctypes/bug1155985.js14
-rw-r--r--js/src/jit-test/tests/ctypes/cast.js12
-rw-r--r--js/src/jit-test/tests/ctypes/construct.js11
-rw-r--r--js/src/jit-test/tests/ctypes/conversion-array.js36
-rw-r--r--js/src/jit-test/tests/ctypes/conversion-error.js14
-rw-r--r--js/src/jit-test/tests/ctypes/conversion-finalizer.js63
-rw-r--r--js/src/jit-test/tests/ctypes/conversion-function.js33
-rw-r--r--js/src/jit-test/tests/ctypes/conversion-int64.js20
-rw-r--r--js/src/jit-test/tests/ctypes/conversion-native-function.js37
-rw-r--r--js/src/jit-test/tests/ctypes/conversion-pointer.js29
-rw-r--r--js/src/jit-test/tests/ctypes/conversion-primitive.js44
-rw-r--r--js/src/jit-test/tests/ctypes/conversion-struct.js36
-rw-r--r--js/src/jit-test/tests/ctypes/conversion-to-number.js98
-rw-r--r--js/src/jit-test/tests/ctypes/conversion-to-primitive.js20
-rw-r--r--js/src/jit-test/tests/ctypes/function-definition.js47
-rw-r--r--js/src/jit-test/tests/ctypes/incompatible-abi.js11
-rw-r--r--js/src/jit-test/tests/ctypes/incompatible-array.js13
-rw-r--r--js/src/jit-test/tests/ctypes/incompatible-cdata.js27
-rw-r--r--js/src/jit-test/tests/ctypes/incompatible-ctype.js13
-rw-r--r--js/src/jit-test/tests/ctypes/incompatible-finalizer.js26
-rw-r--r--js/src/jit-test/tests/ctypes/incompatible-function.js13
-rw-r--r--js/src/jit-test/tests/ctypes/incompatible-int64.js28
-rw-r--r--js/src/jit-test/tests/ctypes/incompatible-pointer.js19
-rw-r--r--js/src/jit-test/tests/ctypes/incompatible-struct.js31
-rw-r--r--js/src/jit-test/tests/ctypes/pointer.js31
-rw-r--r--js/src/jit-test/tests/ctypes/size-overflow-array.js18
-rw-r--r--js/src/jit-test/tests/ctypes/size-overflow-struct.js24
-rw-r--r--js/src/jit-test/tests/ctypes/struct-field.js21
-rw-r--r--js/src/jit-test/tests/ctypes/typedarrays.js102
47 files changed, 1186 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/ctypes/AddressOfField.js b/js/src/jit-test/tests/ctypes/AddressOfField.js
new file mode 100644
index 0000000000..52f4d1cd17
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/AddressOfField.js
@@ -0,0 +1,12 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ let strcut = ctypes.StructType("a", [ { "x": ctypes.int32_t, } ])();
+ for (let arg of [1, undefined, null, false, {}, [], Symbol("foo")]) {
+ assertThrowsInstanceOf(() => { struct.addressOfField(arg); },
+ Error);
+ }
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-length-abi.js b/js/src/jit-test/tests/ctypes/argument-length-abi.js
new file mode 100644
index 0000000000..16179765ce
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-abi.js
@@ -0,0 +1,11 @@
+// |jit-test| skip-if: !this.ctypes || !ctypes.default_abi.toSource
+
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.default_abi.toSource(1); },
+ "ABI.prototype.toSource takes no arguments");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-length-array.js b/js/src/jit-test/tests/ctypes/argument-length-array.js
new file mode 100644
index 0000000000..5afbcc46eb
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-array.js
@@ -0,0 +1,15 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.ArrayType(); },
+ "ArrayType takes one or two arguments");
+ assertTypeErrorMessage(() => { ctypes.int32_t.array(10)(1, 2); },
+ "size defined ArrayType constructor takes at most one argument");
+ assertTypeErrorMessage(() => { ctypes.int32_t.array()(1, 2); },
+ "size undefined ArrayType constructor takes one argument");
+ assertTypeErrorMessage(() => { ctypes.int32_t.array(10)().addressOfElement(); },
+ "ArrayType.prototype.addressOfElement takes one argument");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-length-cdata.js b/js/src/jit-test/tests/ctypes/argument-length-cdata.js
new file mode 100644
index 0000000000..2dc6ff8cd0
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-cdata.js
@@ -0,0 +1,18 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.int32_t(0).address(1); },
+ "CData.prototype.address takes no arguments");
+ assertTypeErrorMessage(() => { ctypes.char.array(10)().readString(1); },
+ "CData.prototype.readString takes no arguments");
+ assertTypeErrorMessage(() => { ctypes.char.array(10)().readStringReplaceMalformed(1); },
+ "CData.prototype.readStringReplaceMalformed takes no arguments");
+
+ if (ctypes.int32_t.prototype.toSource) {
+ assertTypeErrorMessage(() => { ctypes.int32_t(0).toSource(1); },
+ "CData.prototype.toSource takes no arguments");
+ }
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-length-ctypes.js b/js/src/jit-test/tests/ctypes/argument-length-ctypes.js
new file mode 100644
index 0000000000..84b0b9ea54
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-ctypes.js
@@ -0,0 +1,11 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.cast(); },
+ "ctypes.cast takes two arguments");
+ assertTypeErrorMessage(() => { ctypes.getRuntime(); },
+ "ctypes.getRuntime takes one argument");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-length-finalizer.js b/js/src/jit-test/tests/ctypes/argument-length-finalizer.js
new file mode 100644
index 0000000000..70e15bf8f0
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-finalizer.js
@@ -0,0 +1,16 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.CDataFinalizer(1); },
+ "CDataFinalizer constructor takes two arguments");
+
+ let fin = ctypes.CDataFinalizer(ctypes.int32_t(0), ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.int32_t]).ptr(x => x));
+ assertTypeErrorMessage(() => { fin.forget(1); },
+ "CDataFinalizer.prototype.forget takes no arguments");
+ assertTypeErrorMessage(() => { fin.dispose(1); },
+ "CDataFinalizer.prototype.dispose takes no arguments");
+ fin.forget();
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-length-function.js b/js/src/jit-test/tests/ctypes/argument-length-function.js
new file mode 100644
index 0000000000..2d26596620
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-function.js
@@ -0,0 +1,11 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.FunctionType(); },
+ "FunctionType takes two or three arguments");
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, []).ptr({}, 1); },
+ "FunctionType constructor takes one argument");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-length-int64.js b/js/src/jit-test/tests/ctypes/argument-length-int64.js
new file mode 100644
index 0000000000..7e2efe839f
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-int64.js
@@ -0,0 +1,40 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.Int64(1).toString(1, 2); },
+ "Int64.prototype.toString takes at most one argument");
+ if (ctypes.Int64.prototype.toSource) {
+ assertTypeErrorMessage(() => { ctypes.Int64(1).toSource(1); },
+ "Int64.prototype.toSource takes no arguments");
+ }
+ assertTypeErrorMessage(() => { ctypes.Int64(); },
+ "Int64 constructor takes one argument");
+ assertTypeErrorMessage(() => { ctypes.Int64.compare(); },
+ "Int64.compare takes two arguments");
+ assertTypeErrorMessage(() => { ctypes.Int64.lo(); },
+ "Int64.lo takes one argument");
+ assertTypeErrorMessage(() => { ctypes.Int64.hi(); },
+ "Int64.hi takes one argument");
+ assertTypeErrorMessage(() => { ctypes.Int64.join(); },
+ "Int64.join takes two arguments");
+
+ assertTypeErrorMessage(() => { ctypes.UInt64(1).toString(1, 2); },
+ "UInt64.prototype.toString takes at most one argument");
+ if (ctypes.UInt64.prototype.toSource) {
+ assertTypeErrorMessage(() => { ctypes.UInt64(1).toSource(1); },
+ "UInt64.prototype.toSource takes no arguments");
+ }
+ assertTypeErrorMessage(() => { ctypes.UInt64(); },
+ "UInt64 constructor takes one argument");
+ assertTypeErrorMessage(() => { ctypes.UInt64.compare(); },
+ "UInt64.compare takes two arguments");
+ assertTypeErrorMessage(() => { ctypes.UInt64.lo(); },
+ "UInt64.lo takes one argument");
+ assertTypeErrorMessage(() => { ctypes.UInt64.hi(); },
+ "UInt64.hi takes one argument");
+ assertTypeErrorMessage(() => { ctypes.UInt64.join(); },
+ "UInt64.join takes two arguments");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-length-pointer.js b/js/src/jit-test/tests/ctypes/argument-length-pointer.js
new file mode 100644
index 0000000000..8ac404aaf7
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-pointer.js
@@ -0,0 +1,11 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.PointerType(); },
+ "PointerType takes one argument");
+ assertTypeErrorMessage(() => { ctypes.int32_t.ptr(1, 2, 3, 4); },
+ "PointerType constructor takes 0, 1, 2, or 3 arguments");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-length-primitive.js b/js/src/jit-test/tests/ctypes/argument-length-primitive.js
new file mode 100644
index 0000000000..161ebd880c
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-primitive.js
@@ -0,0 +1,11 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.int32_t(1, 2, 3); },
+ "CType constructor takes at most one argument");
+ assertTypeErrorMessage(() => { ctypes.int32_t.array(1, 2); },
+ "CType.prototype.array takes at most one argument");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-length-struct.js b/js/src/jit-test/tests/ctypes/argument-length-struct.js
new file mode 100644
index 0000000000..0e8efbb6ab
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-struct.js
@@ -0,0 +1,17 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.StructType(); },
+ "StructType takes one or two arguments");
+ assertTypeErrorMessage(() => { ctypes.StructType("a").define(); },
+ "StructType.prototype.define takes one argument");
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [])(1, 2, 3); },
+ "StructType constructor takes at most one argument");
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [ {"x": ctypes.int32_t }, {"y": ctypes.int32_t }, {"z": ctypes.int32_t }])(1, 2); },
+ "StructType constructor takes 0, 1, or 3 arguments");
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [ {"x": ctypes.int32_t } ])().addressOfField(); },
+ "StructType.prototype.addressOfField takes one argument");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-type-array.js b/js/src/jit-test/tests/ctypes/argument-type-array.js
new file mode 100644
index 0000000000..e78578d86b
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-type-array.js
@@ -0,0 +1,17 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.int32_t.array({}); },
+ "argument of CType.prototype.array must be a nonnegative integer");
+ assertTypeErrorMessage(() => { ctypes.ArrayType(1); },
+ "first argument of ArrayType must be a CType");
+ assertTypeErrorMessage(() => { ctypes.ArrayType(ctypes.int32_t, {}); },
+ "second argument of ArrayType must be a nonnegative integer");
+ assertTypeErrorMessage(() => { ctypes.char.array()({}); },
+ "argument of size undefined ArrayType constructor must be an array object or integer");
+ assertTypeErrorMessage(() => { ctypes.char.array()(false); },
+ "argument of size undefined ArrayType constructor must be an array object or integer");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-type-ctypes.js b/js/src/jit-test/tests/ctypes/argument-type-ctypes.js
new file mode 100644
index 0000000000..168c8fb746
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-type-ctypes.js
@@ -0,0 +1,13 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.cast(1, 2); },
+ "first argument of ctypes.cast must be a CData");
+ assertTypeErrorMessage(() => { ctypes.cast(ctypes.int32_t(0), 2); },
+ "second argument of ctypes.cast must be a CType");
+ assertTypeErrorMessage(() => { ctypes.getRuntime(1); },
+ "argument of ctypes.getRuntime must be a CType");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-type-function.js b/js/src/jit-test/tests/ctypes/argument-type-function.js
new file mode 100644
index 0000000000..a341415f1d
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-type-function.js
@@ -0,0 +1,9 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, 1); },
+ "third argument of FunctionType must be an array");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-type-int64.js b/js/src/jit-test/tests/ctypes/argument-type-int64.js
new file mode 100644
index 0000000000..e147b98a48
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-type-int64.js
@@ -0,0 +1,28 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertRangeErrorMessage(() => { ctypes.Int64(0).toString("a"); },
+ "argument of Int64.prototype.toString must be an integer at least 2 and no greater than 36");
+ assertTypeErrorMessage(() => { ctypes.Int64.compare(1, 2); },
+ "first argument of Int64.compare must be a Int64");
+ assertTypeErrorMessage(() => { ctypes.Int64.compare(ctypes.Int64(0), 2); },
+ "second argument of Int64.compare must be a Int64");
+ assertTypeErrorMessage(() => { ctypes.Int64.lo(1); },
+ "argument of Int64.lo must be a Int64");
+ assertTypeErrorMessage(() => { ctypes.Int64.hi(1); },
+ "argument of Int64.hi must be a Int64");
+
+ assertRangeErrorMessage(() => { ctypes.UInt64(0).toString("a"); },
+ "argument of UInt64.prototype.toString must be an integer at least 2 and no greater than 36");
+ assertTypeErrorMessage(() => { ctypes.UInt64.compare(1, 2); },
+ "first argument of UInt64.compare must be a UInt64");
+ assertTypeErrorMessage(() => { ctypes.UInt64.compare(ctypes.UInt64(0), 2); },
+ "second argument of UInt64.compare must be a UInt64");
+ assertTypeErrorMessage(() => { ctypes.UInt64.lo(1); },
+ "argument of UInt64.lo must be a UInt64");
+ assertTypeErrorMessage(() => { ctypes.UInt64.hi(1); },
+ "argument of UInt64.hi must be a UInt64");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-type-pointer.js b/js/src/jit-test/tests/ctypes/argument-type-pointer.js
new file mode 100644
index 0000000000..80f96ad905
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-type-pointer.js
@@ -0,0 +1,9 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.PointerType({}); },
+ "argument of PointerType must be a CType");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/argument-type-struct.js b/js/src/jit-test/tests/ctypes/argument-type-struct.js
new file mode 100644
index 0000000000..703c0f059f
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-type-struct.js
@@ -0,0 +1,17 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.StructType(1); },
+ "first argument of StructType must be a string");
+ assertTypeErrorMessage(() => { ctypes.StructType("a", 1); },
+ "second argument of StructType must be an array");
+ assertTypeErrorMessage(() => { ctypes.StructType("a").define(1); },
+ "argument of StructType.prototype.define must be an array");
+ assertTypeErrorMessage(() => { ctypes.StructType("a").define({}); },
+ "argument of StructType.prototype.define must be an array");
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [{x:ctypes.int32_t}])().addressOfField(1); },
+ "argument of StructType.prototype.addressOfField must be a string");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/array-index.js b/js/src/jit-test/tests/ctypes/array-index.js
new file mode 100644
index 0000000000..e70add1a06
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/array-index.js
@@ -0,0 +1,29 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ let a = ctypes.int32_t.array(10)();
+ assertTypeErrorMessage(() => { let x = a[-1]; },
+ "the string \"-1\" is not a valid array index");
+ assertTypeErrorMessage(() => { a[-1] = 1; },
+ "the string \"-1\" is not a valid array index");
+ assertTypeErrorMessage(() => { a.addressOfElement(-1); },
+ "the number -1 is not a valid array index");
+
+ assertRangeErrorMessage(() => { let x = a[10]; },
+ "array index 10 is out of bounds for array of length 10");
+ assertRangeErrorMessage(() => { a[10] = 1; },
+ "array index 10 is out of bounds for array of length 10");
+ assertRangeErrorMessage(() => { a.addressOfElement(10); },
+ "array index 10 is out of bounds for array of length 10");
+
+ let obj = {
+ toSource() {
+ throw 1;
+ }
+ };
+ assertTypeErrorMessage(() => { a.addressOfElement(obj); },
+ "<<error converting value to string>> is not a valid array index");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/bug1155985.js b/js/src/jit-test/tests/ctypes/bug1155985.js
new file mode 100644
index 0000000000..54c24d4bad
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/bug1155985.js
@@ -0,0 +1,14 @@
+function test() {
+ for (let i = 0; i < 100; i++) {
+ let test_struct = ctypes.StructType("test_struct", [{ "x": ctypes.int32_t },
+ { "bar": ctypes.uint32_t }]);
+
+ try {
+ new test_struct("foo", "x");
+ } catch (e) {
+ }
+ }
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/cast.js b/js/src/jit-test/tests/ctypes/cast.js
new file mode 100644
index 0000000000..c483d3793f
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/cast.js
@@ -0,0 +1,12 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.cast(ctypes.int32_t(0), ctypes.StructType("foo")); },
+ "target type foo has undefined size");
+
+ assertTypeErrorMessage(() => { ctypes.cast(ctypes.int32_t(0), ctypes.StructType("foo", [ { x: ctypes.int32_t }, { y: ctypes.int32_t } ])); },
+ "target type foo has larger size than source type ctypes.int32_t (8 > 4)");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/construct.js b/js/src/jit-test/tests/ctypes/construct.js
new file mode 100644
index 0000000000..cfabdf24dc
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/construct.js
@@ -0,0 +1,11 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.void_t(); },
+ "cannot construct from void_t");
+ assertTypeErrorMessage(() => { ctypes.CType(); },
+ "cannot construct from abstract type");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/conversion-array.js b/js/src/jit-test/tests/ctypes/conversion-array.js
new file mode 100644
index 0000000000..cb6e2ce0b8
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/conversion-array.js
@@ -0,0 +1,36 @@
+// Type conversion error should report its type.
+
+load(libdir + 'asserts.js');
+
+function test() {
+ // constructor
+ assertTypeErrorMessage(() => { ctypes.int32_t.array()("foo"); },
+ "can't convert the string \"foo\" to the type ctypes.int32_t.array()");
+ assertTypeErrorMessage(() => { ctypes.int32_t.array(10)("foo"); },
+ "can't convert the string \"foo\" to the type ctypes.int32_t.array(10)");
+ assertTypeErrorMessage(() => { ctypes.char.array(2)("foo"); },
+ "length of the string \"foo\" does not fit in the length of the type ctypes.char.array(2) (expected 2 or lower, got 3)");
+ assertTypeErrorMessage(() => { ctypes.char16_t.array(2)("foo"); },
+ "length of the string \"foo\" does not fit in the length of the type ctypes.char16_t.array(2) (expected 2 or lower, got 3)");
+ assertTypeErrorMessage(() => { ctypes.int8_t.array(2)(new ArrayBuffer(8)); },
+ "length of the array buffer ({}) does not match to the length of the type ctypes.int8_t.array(2) (expected 2, got 8)");
+ assertTypeErrorMessage(() => { ctypes.int8_t.array(2)(new Int8Array(8)); },
+ "length of the typed array ({0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0}) does not match to the length of the type ctypes.int8_t.array(2) (expected 2, got 8)");
+
+ // elem setter
+ assertTypeErrorMessage(() => { ctypes.int32_t.array(10)()[0] = "foo"; },
+ "can't convert the string \"foo\" to element 0 of the type ctypes.int32_t.array(10)");
+ assertTypeErrorMessage(() => { ctypes.int32_t.array(10)()[1] = "foo"; },
+ "can't convert the string \"foo\" to element 1 of the type ctypes.int32_t.array(10)");
+
+ // value setter
+ assertTypeErrorMessage(() => { ctypes.int32_t.array(1)().value = ["foo"]; },
+ "can't convert the string \"foo\" to element 0 of the type ctypes.int32_t.array(1)");
+ assertTypeErrorMessage(() => { ctypes.int32_t.array(1)().value = [2, "foo"]; },
+ "length of the array [2, \"foo\"] does not match to the length of the type ctypes.int32_t.array(1) (expected 1, got 2)");
+ assertTypeErrorMessage(() => { ctypes.int32_t.array(2)().value = [2, "foo"]; },
+ "can't convert the string \"foo\" to element 1 of the type ctypes.int32_t.array(2)");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/conversion-error.js b/js/src/jit-test/tests/ctypes/conversion-error.js
new file mode 100644
index 0000000000..a6823fe5ce
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/conversion-error.js
@@ -0,0 +1,14 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ let obj = {
+ toSource() {
+ throw 1;
+ }
+ };
+ assertTypeErrorMessage(() => { ctypes.double().value = obj; },
+ "can't convert <<error converting value to string>> to the type double");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/conversion-finalizer.js b/js/src/jit-test/tests/ctypes/conversion-finalizer.js
new file mode 100644
index 0000000000..c54ef15423
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/conversion-finalizer.js
@@ -0,0 +1,63 @@
+// |jit-test| skip-if: getBuildConfiguration()['arm'] || getBuildConfiguration()['arm64']
+// skip on arm, arm64 due to bug 1511615
+load(libdir + 'asserts.js');
+
+function test() {
+ // non object
+ assertTypeErrorMessage(() => { ctypes.CDataFinalizer(0, "foo"); },
+ "expected _a CData object_ of a function pointer type, got the string \"foo\"");
+ // non CData object
+ assertTypeErrorMessage(() => { ctypes.CDataFinalizer(0, ["foo"]); },
+ "expected a _CData_ object of a function pointer type, got the array [\"foo\"]");
+
+ // a CData which is not a pointer
+ assertTypeErrorMessage(() => { ctypes.CDataFinalizer(0, ctypes.int32_t(0)); },
+ "expected a CData object of a function _pointer_ type, got ctypes.int32_t(0)");
+ // a pointer CData which is not a function
+ assertTypeErrorMessage(() => { ctypes.CDataFinalizer(0, ctypes.int32_t.ptr(0)); },
+ "expected a CData object of a _function_ pointer type, got ctypes.int32_t.ptr(ctypes.UInt64(\"0x0\"))");
+
+ // null function
+ let func_type = ctypes.FunctionType(ctypes.default_abi, ctypes.voidptr_t,
+ [ctypes.int32_t, ctypes.int32_t]).ptr;
+ let f0 = func_type(0);
+ assertTypeErrorMessage(() => { ctypes.CDataFinalizer(0, f0); },
+ "expected a CData object of a _non-NULL_ function pointer type, got ctypes.FunctionType(ctypes.default_abi, ctypes.voidptr_t, [ctypes.int32_t, ctypes.int32_t]).ptr(ctypes.UInt64(\"0x0\"))");
+
+ // a function with 2 arguments
+ let f1 = func_type(x => x);
+ assertTypeErrorMessage(() => { ctypes.CDataFinalizer(0, f1); },
+ "expected a function accepting exactly one argument, got ctypes.FunctionType(ctypes.default_abi, ctypes.voidptr_t, [ctypes.int32_t, ctypes.int32_t])");
+
+ // non CData in argument 1
+ let func_type2 = ctypes.FunctionType(ctypes.default_abi, ctypes.voidptr_t,
+ [ctypes.int32_t.ptr]).ptr;
+ let f2 = func_type2(x => x);
+ assertTypeErrorMessage(() => { ctypes.CDataFinalizer(0, f2); },
+ "can't convert the number 0 to the type of argument 1 of ctypes.FunctionType(ctypes.default_abi, ctypes.voidptr_t, [ctypes.int32_t.ptr]).ptr");
+
+ // wrong struct in argument 1
+ let test_struct = ctypes.StructType("test_struct", [{ "x": ctypes.int32_t }]);
+ let func_type3 = ctypes.FunctionType(ctypes.default_abi, ctypes.voidptr_t,
+ [test_struct]).ptr;
+ let f3 = func_type3(x => x);
+ assertTypeErrorMessage(() => { ctypes.CDataFinalizer({ "x": "foo" }, f3); },
+ "can't convert the string \"foo\" to the 'x' field (int32_t) of test_struct at argument 1 of ctypes.FunctionType(ctypes.default_abi, ctypes.voidptr_t, [test_struct]).ptr");
+
+ // different size in argument 1
+ let func_type4 = ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t,
+ [ctypes.int32_t]).ptr;
+ let f4 = func_type4(x => x);
+ assertTypeErrorMessage(() => { ctypes.CDataFinalizer(ctypes.int16_t(0), f4); },
+ "expected an object with the same size as argument 1 of ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.int32_t]).ptr, got ctypes.int16_t(0)");
+
+ let fin = ctypes.CDataFinalizer(ctypes.int32_t(0), f4);
+ fin.dispose();
+ assertTypeErrorMessage(() => { ctypes.int32_t(0).value = fin; },
+ "attempting to convert an empty CDataFinalizer");
+ assertTypeErrorMessage(() => { f4(fin); },
+ /attempting to convert an empty CDataFinalizer at argument 1 of ctypes\.FunctionType\(ctypes\.default_abi, ctypes\.int32_t, \[ctypes\.int32_t\]\)\.ptr\(ctypes\.UInt64\(\"[x0-9A-Fa-f]+\"\)\)/);
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/conversion-function.js b/js/src/jit-test/tests/ctypes/conversion-function.js
new file mode 100644
index 0000000000..cd90f1b606
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/conversion-function.js
@@ -0,0 +1,33 @@
+// Type conversion error should report its type.
+
+load(libdir + 'asserts.js');
+
+function test() {
+ // Note: js shell cannot handle the exception in return value.
+
+ // primitive
+ let func_type = ctypes.FunctionType(ctypes.default_abi, ctypes.voidptr_t,
+ [ctypes.int32_t]).ptr;
+ let f1 = func_type(function() {});
+ assertTypeErrorMessage(() => { f1("foo"); },
+ /can't pass the string "foo" to argument 1 of ctypes\.FunctionType\(ctypes\.default_abi, ctypes\.voidptr_t, \[ctypes\.int32_t\]\)\.ptr\(ctypes\.UInt64\("[x0-9A-Fa-f]+"\)\)/);
+
+ // struct
+ let test_struct = ctypes.StructType("test_struct", [{ "x": ctypes.int32_t }]);
+ let func_type2 = ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t,
+ [test_struct]).ptr;
+ let f2 = func_type2(function() {});
+ assertTypeErrorMessage(() => { f2({ "x": "foo" }); },
+ /can't convert the string \"foo\" to the 'x' field \(int32_t\) of test_struct at argument 1 of ctypes\.FunctionType\(ctypes\.default_abi, ctypes.int32_t, \[test_struct\]\)\.ptr\(ctypes\.UInt64\(\"[x0-9A-Fa-f]+\"\)\)/);
+ assertTypeErrorMessage(() => { f2({ "x": "foo", "y": "bar" }); },
+ /property count of the object \(\{x:\"foo\", y:\"bar\"\}\) does not match to field count of the type test_struct \(expected 1, got 2\) at argument 1 of ctypes\.FunctionType\(ctypes\.default_abi, ctypes\.int32_t, \[test_struct\]\)\.ptr\(ctypes\.UInt64\(\"[x0-9A-Fa-f]+\"\)\)/);
+ assertTypeErrorMessage(() => { f2({ 0: "foo" }); },
+ /property name the number 0 of the object \(\{0:\"foo\"\}\) is not a string at argument 1 of ctypes\.FunctionType\(ctypes\.default_abi, ctypes\.int32_t, \[test_struct\]\)\.ptr\(ctypes\.UInt64\(\"[x0-9A-Fa-f]+\"\)\)/);
+
+ // error sentinel
+ assertTypeErrorMessage(() => { func_type(function() {}, null, "foo"); },
+ "can't convert the string \"foo\" to the return type of ctypes.FunctionType(ctypes.default_abi, ctypes.voidptr_t, [ctypes.int32_t])");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/conversion-int64.js b/js/src/jit-test/tests/ctypes/conversion-int64.js
new file mode 100644
index 0000000000..89a14fef9e
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/conversion-int64.js
@@ -0,0 +1,20 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertRangeErrorMessage(() => { ctypes.Int64("0xfffffffffffffffffffffff"); },
+ "the string \"0xfffffffffffffffffffffff\" does not fit in the type int64");
+ assertTypeErrorMessage(() => { ctypes.Int64.join("foo", 0); },
+ "can't pass the string \"foo\" to argument 1 of Int64.join");
+ assertTypeErrorMessage(() => { ctypes.Int64.join(0, "foo"); },
+ "can't pass the string \"foo\" to argument 2 of Int64.join");
+
+ assertRangeErrorMessage(() => { ctypes.UInt64("0xfffffffffffffffffffffff"); },
+ "the string \"0xfffffffffffffffffffffff\" does not fit in the type uint64");
+ assertTypeErrorMessage(() => { ctypes.UInt64.join("foo", 0); },
+ "can't pass the string \"foo\" to argument 1 of UInt64.join");
+ assertTypeErrorMessage(() => { ctypes.UInt64.join(0, "foo"); },
+ "can't pass the string \"foo\" to argument 2 of UInt64.join");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/conversion-native-function.js b/js/src/jit-test/tests/ctypes/conversion-native-function.js
new file mode 100644
index 0000000000..b005596c2c
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/conversion-native-function.js
@@ -0,0 +1,37 @@
+// Type conversion error for native function should report its name and type
+// in C style.
+
+load(libdir + 'asserts.js');
+
+function test() {
+ let lib;
+ try {
+ lib = ctypes.open(ctypes.libraryName("m"));
+ } catch (e) {
+ }
+ if (!lib)
+ return;
+
+ let func = lib.declare("hypot",
+ ctypes.default_abi,
+ ctypes.double,
+ ctypes.double, ctypes.double);
+ assertTypeErrorMessage(() => { func(1, "xyzzy"); },
+ "can't pass the string \"xyzzy\" to argument 2 of double hypot(double, double)");
+
+ // test C style source for various types
+ let test_struct = ctypes.StructType("test_struct", [{ "x": ctypes.int32_t }]);
+ let test_func = ctypes.FunctionType(ctypes.default_abi, ctypes.voidptr_t,
+ [ctypes.int32_t]).ptr;
+ func = lib.declare("hypot",
+ ctypes.default_abi,
+ ctypes.double,
+ ctypes.double, ctypes.int32_t.ptr.ptr.ptr.array(),
+ test_struct, test_struct.ptr.ptr,
+ test_func, test_func.ptr.ptr.ptr, "...");
+ assertTypeErrorMessage(() => { func("xyzzy", 1, 2, 3, 4, 5); },
+ "can't pass the string \"xyzzy\" to argument 1 of double hypot(double, int32_t****, struct test_struct, struct test_struct**, void* (*)(int32_t), void* (****)(int32_t), ...)");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/conversion-pointer.js b/js/src/jit-test/tests/ctypes/conversion-pointer.js
new file mode 100644
index 0000000000..d2583b8789
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/conversion-pointer.js
@@ -0,0 +1,29 @@
+// Type conversion error should report its type.
+
+load(libdir + 'asserts.js');
+
+function test() {
+ let test_struct = ctypes.StructType("test_struct", [{ "x": ctypes.int32_t }]);
+ let struct_val = test_struct();
+
+ // constructor
+ assertTypeErrorMessage(() => { ctypes.int32_t.ptr("foo"); },
+ "can't convert the string \"foo\" to the type ctypes.int32_t.ptr");
+
+ // value setter
+ assertTypeErrorMessage(() => { test_struct.ptr().value = "foo"; },
+ "can't convert the string \"foo\" to the type test_struct.ptr");
+ assertTypeErrorMessage(() => { test_struct.ptr().value = {}; },
+ "can't convert the object ({}) to the type test_struct.ptr");
+ assertTypeErrorMessage(() => { test_struct.ptr().value = [1, 2]; },
+ "can't convert the array [1, 2] to the type test_struct.ptr");
+ assertTypeErrorMessage(() => { test_struct.ptr().value = new Int8Array([1, 2]); },
+ "can't convert the typed array ({0:1, 1:2}) to the type test_struct.ptr");
+
+ // contents setter
+ assertTypeErrorMessage(() => { ctypes.int32_t().address().contents = {}; },
+ "can't convert the object ({}) to the type int32_t");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/conversion-primitive.js b/js/src/jit-test/tests/ctypes/conversion-primitive.js
new file mode 100644
index 0000000000..38512f9c45
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/conversion-primitive.js
@@ -0,0 +1,44 @@
+// Type conversion error should report its type.
+
+load(libdir + 'asserts.js');
+
+function test() {
+ // constructor
+ assertTypeErrorMessage(() => { ctypes.int32_t("foo"); },
+ "can't convert the string \"foo\" to the type int32_t");
+ assertTypeErrorMessage(() => { ctypes.int32_t(null); },
+ "can't convert null to the type int32_t");
+ assertTypeErrorMessage(() => { ctypes.int32_t(undefined); },
+ "can't convert undefined to the type int32_t");
+ assertTypeErrorMessage(() => { ctypes.int32_t({}); },
+ "can't convert the object ({}) to the type int32_t");
+ assertTypeErrorMessage(() => { ctypes.int32_t([]); },
+ "can't convert the array [] to the type int32_t");
+ assertTypeErrorMessage(() => { ctypes.int32_t(new Int8Array([])); },
+ "can't convert the typed array ({}) to the type int32_t");
+ assertTypeErrorMessage(() => { ctypes.int32_t(ctypes.int32_t); },
+ "can't convert ctypes.int32_t to the type int32_t");
+ assertRangeErrorMessage(() => { ctypes.int32_t("0xfffffffffffffffffffffff"); },
+ "the string \"0xfffffffffffffffffffffff\" does not fit in the type int32_t");
+ if (typeof Symbol === "function") {
+ assertTypeErrorMessage(() => { ctypes.int32_t(Symbol.iterator); },
+ "can't convert Symbol.iterator to the type int32_t");
+ assertTypeErrorMessage(() => { ctypes.int32_t(Symbol("foo")); },
+ "can't convert Symbol(\"foo\") to the type int32_t");
+ }
+
+ // value setter
+ let test_struct = ctypes.StructType("test_struct", [{ "x": ctypes.int32_t }]);
+ let struct_val = test_struct();
+ assertTypeErrorMessage(() => { ctypes.bool().value = struct_val; },
+ "can't convert test_struct(0) to the type boolean");
+ assertTypeErrorMessage(() => { ctypes.char16_t().value = struct_val; },
+ "can't convert test_struct(0) to the type char16_t");
+ assertTypeErrorMessage(() => { ctypes.int8_t().value = struct_val; },
+ "can't convert test_struct(0) to the type int8_t");
+ assertTypeErrorMessage(() => { ctypes.double().value = struct_val; },
+ "can't convert test_struct(0) to the type double");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/conversion-struct.js b/js/src/jit-test/tests/ctypes/conversion-struct.js
new file mode 100644
index 0000000000..f5e43ffa56
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/conversion-struct.js
@@ -0,0 +1,36 @@
+// Type conversion error should report its type.
+
+load(libdir + 'asserts.js');
+
+function test() {
+ let test_struct = ctypes.StructType("test_struct", [{ "x": ctypes.int32_t },
+ { "bar": ctypes.int32_t }]);
+
+ // constructor
+ assertTypeErrorMessage(() => { new test_struct("foo"); },
+ "can't convert the string \"foo\" to the type test_struct");
+ assertTypeErrorMessage(() => { new test_struct("foo", "x"); },
+ "can't convert the string \"foo\" to the 'x' field (int32_t) of test_struct");
+ assertTypeErrorMessage(() => { new test_struct({ "x": "foo", "bar": 1 }); },
+ "can't convert the string \"foo\" to the 'x' field (int32_t) of test_struct");
+ assertTypeErrorMessage(() => { new test_struct({ 0: 1, "bar": 1 }); },
+ "property name the number 0 of the object ({0:1, bar:1}) is not a string");
+
+ // field setter
+ let struct_val = test_struct();
+ assertTypeErrorMessage(() => { struct_val.x = "foo"; },
+ "can't convert the string \"foo\" to the 'x' field (int32_t) of test_struct");
+ assertTypeErrorMessage(() => { struct_val.bar = "foo"; },
+ "can't convert the string \"foo\" to the 'bar' field (int32_t) of test_struct");
+
+ // value setter
+ assertTypeErrorMessage(() => { struct_val.value = { "x": "foo" }; },
+ "property count of the object ({x:\"foo\"}) does not match to field count of the type test_struct (expected 2, got 1)");
+ assertTypeErrorMessage(() => { struct_val.value = { "x": "foo", "bar": 1 }; },
+ "can't convert the string \"foo\" to the 'x' field (int32_t) of test_struct");
+ assertTypeErrorMessage(() => { struct_val.value = "foo"; },
+ "can't convert the string \"foo\" to the type test_struct");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/conversion-to-number.js b/js/src/jit-test/tests/ctypes/conversion-to-number.js
new file mode 100644
index 0000000000..6a334ecf3a
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/conversion-to-number.js
@@ -0,0 +1,98 @@
+// Type conversion to number should use ECMA-style semantics.
+
+load(libdir + 'asserts.js');
+
+function test() {
+ function checkValue(type, provided, expected) {
+ assertEq(ctypes[type](provided).value, expected,
+ `ctypes.${type}(${provided}) contains unexpected value`);
+ }
+
+ function checkCantConvert(type, value) {
+ var ctor = ctypes[type];
+ assertTypeErrorMessage(() => ctor(value),
+ /can't convert the number/);
+ }
+
+ let testInt8 = checkValue.bind(undefined, "int8_t");
+ let testInt8Throws = checkCantConvert.bind(undefined, "int8_t");
+ testInt8(1e100, 0);
+ testInt8Throws(-129);
+ testInt8(-128, -128);
+ testInt8(-1, -1);
+ testInt8(0, 0);
+ testInt8(1, 1);
+ testInt8(127, 127);
+ testInt8Throws(128);
+
+ let testUint8 = checkValue.bind(undefined, "uint8_t");
+ let testUint8Throws = checkCantConvert.bind(undefined, "uint8_t");
+ testUint8(1e100, 0);
+ testUint8Throws(-1);
+ testUint8(0, 0);
+ testUint8(1, 1);
+ testUint8(127, 127);
+ testUint8(128, 128);
+ testUint8(255, 255);
+ testUint8Throws(256);
+
+ let testInt16 = checkValue.bind(undefined, "int16_t");
+ let testInt16Throws = checkCantConvert.bind(undefined, "int16_t");
+ testInt16(1e100, 0);
+ testInt16Throws(-32769);
+ testInt16(-32768, -32768);
+ testInt16(-1, -1);
+ testInt16(0, 0);
+ testInt16(1, 1);
+ testInt16(32767, 32767);
+ testInt16Throws(32768);
+
+ let testUint16 = checkValue.bind(undefined, "uint16_t");
+ let testUint16Throws = checkCantConvert.bind(undefined, "uint16_t");
+ testUint16(1e100, 0);
+ testUint16Throws(-1);
+ testUint16(0, 0);
+ testUint16(1, 1);
+ testUint16(32767, 32767);
+ testUint16(32768, 32768);
+ testUint16(65535, 65535);
+ testUint16Throws(65536);
+
+ let testInt32 = checkValue.bind(undefined, "int32_t");
+ let testInt32Throws = checkCantConvert.bind(undefined, "int32_t");
+ testInt32(1e100, 0);
+ // This probably should pass, but right now doubles fall into a different
+ // code path where no error occurs. ctypes is probably/hopefully declining in
+ // use now, so just don't bother with this test.
+ //testInt32Throws(-2147483649);
+ testInt32(-2147483648, -2147483648);
+ testInt32(-1, -1);
+ testInt32(0, 0);
+ testInt32(1, 1);
+ testInt32(2147483647, 2147483647);
+ // This probably should pass, but right now doubles fall into a different
+ // code path where no error occurs. ctypes is probably/hopefully declining in
+ // use now, so just don't bother with this test.
+ //testInt32Throws(2147483648);
+
+ let testUint32 = checkValue.bind(undefined, "uint32_t");
+ let testUint32Throws = checkCantConvert.bind(undefined, "uint32_t");
+ testUint32(1e100, 0);
+ testUint32Throws(-1);
+ // This probably should pass, but right now doubles fall into a different
+ // code path where no error occurs. ctypes is probably/hopefully declining in
+ // use now, so just don't bother with this test.
+ //testUint32Throws(-1 * Math.cos(Math.PI)); // -1.0 encoded as a double
+ testUint32(0, 0);
+ testUint32(1, 1);
+ testUint32(2147483647, 2147483647);
+ testUint32(2147483648, 2147483648);
+ testUint32(4294967295, 4294967295);
+ // This probably should pass, but right now doubles fall into a different
+ // code path where no error occurs. ctypes is probably/hopefully declining in
+ // use now, so just don't bother with this test.
+ //testUint32Throws(4294967296);
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/conversion-to-primitive.js b/js/src/jit-test/tests/ctypes/conversion-to-primitive.js
new file mode 100644
index 0000000000..cdb9a4a051
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/conversion-to-primitive.js
@@ -0,0 +1,20 @@
+// Accessing `value` property of non primitive type should report its type.
+
+load(libdir + 'asserts.js');
+
+function test() {
+ let test_struct = ctypes.StructType("test_struct", [{ "x": ctypes.voidptr_t }]);
+ assertTypeErrorMessage(() => test_struct().value,
+ ".value only works on character and numeric types, not `test_struct`");
+
+ let test_array = ctypes.ArrayType(test_struct);
+ assertTypeErrorMessage(() => test_array(10).value,
+ ".value only works on character and numeric types, not `test_struct.array(10)`");
+
+ let test_pointer = ctypes.PointerType(test_struct);
+ assertTypeErrorMessage(() => test_pointer(10).value,
+ ".value only works on character and numeric types, not `test_struct.ptr`");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/function-definition.js b/js/src/jit-test/tests/ctypes/function-definition.js
new file mode 100644
index 0000000000..5882ba8891
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/function-definition.js
@@ -0,0 +1,47 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertRangeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, []).ptr(x=>1)(1); },
+ "number of arguments does not match declaration of ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t) (expected 0, got 1)");
+
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [1]); },
+ "the type of argument 1 is not a ctypes type (got the number 1)");
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.void_t]); },
+ "the type of argument 1 cannot be void or function (got ctypes.void)");
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [])]); },
+ "the type of argument 1 cannot be void or function (got ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t))");
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.StructType("a")]); },
+ "the type of argument 1 must have defined size (got ctypes.StructType(\"a\"))");
+
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [])(); },
+ "cannot construct from FunctionType; use FunctionType.ptr instead");
+
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, 1, []); },
+ "return type is not a ctypes type (got the number 1)");
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t.array(), []); },
+ "return type cannot be an array or function (got ctypes.int32_t.array())");
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, []), []); },
+ "return type cannot be an array or function (got ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t))");
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.StructType("a"), []); },
+ "return type must have defined size (got ctypes.StructType(\"a\"))");
+
+ let lib;
+ try {
+ lib = ctypes.open(ctypes.libraryName("m"));
+ } catch (e) {
+ }
+ if (!lib)
+ return;
+
+ let func = lib.declare("hypot",
+ ctypes.default_abi,
+ ctypes.double,
+ ctypes.double, "...");
+ assertRangeErrorMessage(() => { func(); },
+ "number of arguments does not match declaration of double hypot(double, ...) (expected 1 or more, got 0)");
+ assertTypeErrorMessage(() => { func(1, 2); },
+ "variadic argument 2 must be a CData object (got the number 2)");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/incompatible-abi.js b/js/src/jit-test/tests/ctypes/incompatible-abi.js
new file mode 100644
index 0000000000..9b7f6569b7
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/incompatible-abi.js
@@ -0,0 +1,11 @@
+// |jit-test| skip-if: !this.ctypes || !ctypes.default_abi.toSource
+
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.default_abi.toSource.call(1); },
+ "ABI.prototype.toSource called on incompatible object, got the number 1");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/incompatible-array.js b/js/src/jit-test/tests/ctypes/incompatible-array.js
new file mode 100644
index 0000000000..968da01098
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/incompatible-array.js
@@ -0,0 +1,13 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.int32_t.array.call(1); },
+ "CType.prototype.array called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { ctypes.int32_t.array(10)().addressOfElement.call(1); },
+ "ArrayType.prototype.addressOfElement called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { ctypes.int32_t.array(10)().addressOfElement.call(ctypes.int32_t(0)); },
+ "ArrayType.prototype.addressOfElement called on non-ArrayType CData, got ctypes.int32_t(0)");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/incompatible-cdata.js b/js/src/jit-test/tests/ctypes/incompatible-cdata.js
new file mode 100644
index 0000000000..e0349be673
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/incompatible-cdata.js
@@ -0,0 +1,27 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.int32_t(0).address.call(1); },
+ "CData.prototype.address called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { ctypes.char.array(10)("abc").readString.call(1); },
+ "CData.prototype.readString called on incompatible object, got the number 1");
+
+ assertTypeErrorMessage(() => { ctypes.char.array(10)("abc").readStringReplaceMalformed.call(1); },
+ "CData.prototype.readStringReplaceMalformed called on incompatible object, got the number 1");
+
+ if (ctypes.int32_t.prototype.toSource) {
+ assertTypeErrorMessage(() => { ctypes.int32_t(0).toSource.call(1); },
+ "CData.prototype.toSource called on incompatible object, got the number 1");
+ }
+
+ let p = Object.getPrototypeOf(ctypes.int32_t());
+ let o = {};
+ Object.setPrototypeOf(o, p);
+ assertTypeErrorMessage(() => { o.readString(); },
+ "CData.prototype.readString called on incompatible object, got <<error converting value to string>>");
+ assertTypeErrorMessage(() => { o.readStringReplaceMalformed(); },
+ "CData.prototype.readStringReplaceMalformed called on incompatible object, got <<error converting value to string>>");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/incompatible-ctype.js b/js/src/jit-test/tests/ctypes/incompatible-ctype.js
new file mode 100644
index 0000000000..7e14c1d615
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/incompatible-ctype.js
@@ -0,0 +1,13 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.int32_t.toString.call(1); },
+ "CType.prototype.toString called on incompatible object, got the number 1");
+ if (ctypes.int32_t.prototype.toSource) {
+ assertTypeErrorMessage(() => { ctypes.int32_t.toSource.call(1); },
+ "CType.prototype.toSource called on incompatible object, got the number 1");
+ }
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/incompatible-finalizer.js b/js/src/jit-test/tests/ctypes/incompatible-finalizer.js
new file mode 100644
index 0000000000..b4b0dab7f4
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/incompatible-finalizer.js
@@ -0,0 +1,26 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ let fin = ctypes.CDataFinalizer(ctypes.int32_t(0), ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.int32_t]).ptr(x => x));
+ if (fin.toSource) {
+ assertTypeErrorMessage(() => { fin.toSource.call(1); },
+ "CDataFinalizer.prototype.toSource called on incompatible object, got the number 1");
+ }
+ assertTypeErrorMessage(() => { fin.toString.call(1); },
+ "CDataFinalizer.prototype.toString called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { fin.forget.call(1); },
+ "CDataFinalizer.prototype.forget called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { fin.dispose.call(1); },
+ "CDataFinalizer.prototype.dispose called on incompatible object, got the number 1");
+ fin.forget();
+
+ assertTypeErrorMessage(() => { fin.readString(); },
+ "CDataFinalizer.prototype.readString called on empty CDataFinalizer");
+ assertTypeErrorMessage(() => { fin.dispose(); },
+ "CDataFinalizer.prototype.dispose called on empty CDataFinalizer");
+ assertTypeErrorMessage(() => { fin.forget(); },
+ "CDataFinalizer.prototype.forget called on empty CDataFinalizer");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/incompatible-function.js b/js/src/jit-test/tests/ctypes/incompatible-function.js
new file mode 100644
index 0000000000..cd31cc5e70
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/incompatible-function.js
@@ -0,0 +1,13 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.void_t).call.call(1); },
+ "Function.prototype.call called on incompatible number");
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.void_t).call.call(ctypes.int32_t(0)); },
+ "FunctionType.prototype.call called on non-PointerType CData, got ctypes.int32_t(0)");
+ assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.void_t).call.call(ctypes.int32_t.ptr(0)); },
+ "FunctionType.prototype.call called on non-FunctionType pointer, got ctypes.int32_t.ptr(ctypes.UInt64(\"0x0\"))");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/incompatible-int64.js b/js/src/jit-test/tests/ctypes/incompatible-int64.js
new file mode 100644
index 0000000000..b2f7a3889c
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/incompatible-int64.js
@@ -0,0 +1,28 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.Int64(0).toString.call(1); },
+ "Int64.prototype.toString called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { ctypes.Int64(0).toString.call(ctypes.int32_t(0)); },
+ "Int64.prototype.toString called on non-Int64 CData");
+ if (ctypes.Int64.prototype.toSource) {
+ assertTypeErrorMessage(() => { ctypes.Int64(0).toSource.call(1); },
+ "Int64.prototype.toSource called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { ctypes.Int64(0).toSource.call(ctypes.int32_t(0)); },
+ "Int64.prototype.toSource called on non-Int64 CData");
+ }
+
+ assertTypeErrorMessage(() => { ctypes.UInt64(0).toString.call(1); },
+ "UInt64.prototype.toString called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { ctypes.UInt64(0).toString.call(ctypes.int32_t(0)); },
+ "UInt64.prototype.toString called on non-UInt64 CData");
+ if (ctypes.UInt64.prototype.toSource) {
+ assertTypeErrorMessage(() => { ctypes.UInt64(0).toSource.call(1); },
+ "UInt64.prototype.toSource called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { ctypes.UInt64(0).toSource.call(ctypes.int32_t(0)); },
+ "UInt64.prototype.toSource called on non-UInt64 CData");
+ }
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/incompatible-pointer.js b/js/src/jit-test/tests/ctypes/incompatible-pointer.js
new file mode 100644
index 0000000000..414974dd89
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/incompatible-pointer.js
@@ -0,0 +1,19 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.int32_t.ptr(0).isNull.call(1); },
+ "PointerType.prototype.isNull called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { ctypes.int32_t.ptr(0).isNull.call({}); },
+ "PointerType.prototype.isNull called on incompatible object, got the object ({})");
+ assertTypeErrorMessage(() => { ctypes.int32_t.ptr(0).increment.call(1); },
+ "PointerType.prototype.increment called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { ctypes.int32_t.ptr(0).increment.call(ctypes.int32_t(0)); },
+ "PointerType.prototype.increment called on non-PointerType CData, got ctypes.int32_t(0)");
+ assertTypeErrorMessage(() => { ctypes.int32_t.ptr(0).decrement.call(1); },
+ "PointerType.prototype.decrement called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { ctypes.int32_t.ptr(0).decrement.call(ctypes.int32_t(0)); },
+ "PointerType.prototype.decrement called on non-PointerType CData, got ctypes.int32_t(0)");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/incompatible-struct.js b/js/src/jit-test/tests/ctypes/incompatible-struct.js
new file mode 100644
index 0000000000..ccd212978a
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/incompatible-struct.js
@@ -0,0 +1,31 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.StructType("a").define.call(1); },
+ "StructType.prototype.define called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { ctypes.StructType("a").define.call(ctypes.int32_t); },
+ "StructType.prototype.define called on non-StructType, got ctypes.int32_t");
+
+ let p = Object.getPrototypeOf(ctypes.StructType("a", [ { "x": ctypes.int32_t, } ])());
+ let o = {};
+ Object.setPrototypeOf(o, p);
+ assertTypeErrorMessage(() => { let a = o.x; },
+ "StructType property getter called on incompatible object, got <<error converting value to string>>");
+ assertTypeErrorMessage(() => { o.x = 1; },
+ "StructType property setter called on incompatible object, got <<error converting value to string>>");
+
+ o = ctypes.int32_t(0);
+ Object.setPrototypeOf(o, p);
+ assertTypeErrorMessage(() => { let a = o.x; },
+ "StructType property getter called on non-StructType CData, got ctypes.int32_t(0)");
+ assertTypeErrorMessage(() => { o.x = 1; },
+ "StructType property setter called on non-StructType CData, got ctypes.int32_t(0)");
+
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [])().addressOfField.call(1); },
+ "StructType.prototype.addressOfField called on incompatible object, got the number 1");
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [])().addressOfField.call(ctypes.int32_t(0)); },
+ "StructType.prototype.addressOfField called on non-StructType CData, got ctypes.int32_t(0)");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/pointer.js b/js/src/jit-test/tests/ctypes/pointer.js
new file mode 100644
index 0000000000..da0685f07b
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/pointer.js
@@ -0,0 +1,31 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ let p = ctypes.StructType("foo").ptr(0);
+
+ assertTypeErrorMessage(() => { p.increment(); },
+ "cannot modify pointer of undefined size foo.ptr(ctypes.UInt64(\"0x0\"))");
+ assertTypeErrorMessage(() => { p.decrement(); },
+ "cannot modify pointer of undefined size foo.ptr(ctypes.UInt64(\"0x0\"))");
+
+ assertTypeErrorMessage(() => { let a = p.contents; },
+ "cannot get contents of pointer of undefined size foo.ptr(ctypes.UInt64(\"0x0\"))");
+ assertTypeErrorMessage(() => { p.contents = 1; },
+ "cannot set contents of pointer of undefined size foo.ptr(ctypes.UInt64(\"0x0\"))");
+
+ let p2 = ctypes.int32_t.ptr(0);
+ assertTypeErrorMessage(() => { let a = p2.contents; },
+ "cannot read contents of null pointer ctypes.int32_t.ptr(ctypes.UInt64(\"0x0\"))");
+ assertTypeErrorMessage(() => { p2.contents = 1; },
+ "cannot write contents to null pointer ctypes.int32_t.ptr(ctypes.UInt64(\"0x0\"))");
+ assertTypeErrorMessage(() => { p2.readString(); },
+ "cannot read contents of null pointer ctypes.int32_t.ptr(ctypes.UInt64(\"0x0\"))");
+
+ assertTypeErrorMessage(() => { ctypes.int32_t(0).readString(); },
+ "expected PointerType or ArrayType, got ctypes.int32_t(0)");
+ assertTypeErrorMessage(() => { ctypes.int32_t(0).address().readString(); },
+ /base type ctypes\.int32_t\.ptr\(ctypes\.UInt64\(\"[x0-9A-Fa-f]+\"\)\) is not an 8-bit or 16-bit integer or character type/);
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/size-overflow-array.js b/js/src/jit-test/tests/ctypes/size-overflow-array.js
new file mode 100644
index 0000000000..290046a6e8
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/size-overflow-array.js
@@ -0,0 +1,18 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ if (getBuildConfiguration()["pointer-byte-size"] == 4) {
+ let big_array = ctypes.int32_t.array(0xfffffff);
+ assertRangeErrorMessage(() => { big_array.array(0xfffffff); },
+ "array size does not fit in size_t");
+ } else if (getBuildConfiguration()["pointer-byte-size"] == 8) {
+ let big_array = ctypes.int32_t.array(0xfffffff);
+ assertRangeErrorMessage(() => { big_array.array(0xfffffff); },
+ "array size does not fit in JavaScript number");
+ assertRangeErrorMessage(() => { big_array.array(0xfffffffff); },
+ "array size does not fit in size_t");
+ }
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/size-overflow-struct.js b/js/src/jit-test/tests/ctypes/size-overflow-struct.js
new file mode 100644
index 0000000000..a40f925a75
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/size-overflow-struct.js
@@ -0,0 +1,24 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ if (getBuildConfiguration()["pointer-byte-size"] == 4) {
+ let big_array = ctypes.int32_t.array(0xfffffff);
+ assertRangeErrorMessage(() => { ctypes.StructType("x", [{a: big_array},
+ {b: big_array},
+ {c: big_array},
+ {d: big_array},
+ {e: big_array}]); },
+ "struct size does not fit in size_t");
+ } else if (getBuildConfiguration()["pointer-byte-size"] == 8) {
+ let big_array = ctypes.int32_t.array(0xfffffffffffffff);
+ assertRangeErrorMessage(() => { ctypes.StructType("x", [{a: big_array},
+ {b: big_array},
+ {c: big_array},
+ {d: big_array},
+ {e: big_array}]); },
+ "struct size does not fit in size_t");
+ }
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/struct-field.js b/js/src/jit-test/tests/ctypes/struct-field.js
new file mode 100644
index 0000000000..2b2089e430
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/struct-field.js
@@ -0,0 +1,21 @@
+load(libdir + 'asserts.js');
+
+function test() {
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [ 1 ]); },
+ "struct field descriptors require a valid name and type (got the number 1)");
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [ { x: 1, y: 2 } ]); },
+ "struct field descriptors must contain one property (got the object ({x:1, y:2}) with 2 properties)");
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [ { 1: 1 } ]); },
+ "the number 1 is not a valid name of struct field descriptors");
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [ { "x": 1 } ]); },
+ "the number 1 is not a valid type of struct field descriptors for 'x' field");
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [ { "x": ctypes.StructType("b") } ]); },
+ "struct field type must have defined and nonzero size (got ctypes.StructType(\"b\") for 'x' field)");
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [ { "x": ctypes.int32_t, }, { "x": ctypes.int32_t } ]); },
+ "struct fields must have unique names, 'x' field appears twice");
+ assertTypeErrorMessage(() => { ctypes.StructType("a", [ { "x": ctypes.int32_t, } ])().addressOfField("z"); },
+ "ctypes.StructType(\"a\", [{ \"x\": ctypes.int32_t }]) does not have a field named 'z'");
+}
+
+if (typeof ctypes === "object")
+ test();
diff --git a/js/src/jit-test/tests/ctypes/typedarrays.js b/js/src/jit-test/tests/ctypes/typedarrays.js
new file mode 100644
index 0000000000..4595e8fe1f
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/typedarrays.js
@@ -0,0 +1,102 @@
+load(libdir + 'asserts.js');
+
+function typedArrayMatchesString(ta, str, uptoStringLength = false) {
+ if (ta.length != str.length && !uptoStringLength)
+ return false;
+ for (let i = 0; i < str.length; i++) {
+ if (ta[i] != str.charCodeAt(i))
+ return false;
+ }
+ return true;
+}
+
+function test() {
+
+ // Check that {signed,unsigned} -> {Int*Array, Uint*Array} for string types.
+
+ const shortU8 = ctypes.unsigned_char.array(10)("abc\0\0\0\0\0\0\0").readTypedArray();
+ assertEq(shortU8 instanceof Uint8Array, true);
+ assertEq(typedArrayMatchesString(shortU8, "abc\0\0\0\0\0\0\0"), true);
+
+ const shortI8 = ctypes.signed_char.array(10)("abc\0\0\0\0\0\0\0").readTypedArray();
+ assertEq(shortI8 instanceof Int8Array, true);
+ assertEq(typedArrayMatchesString(shortI8, "abc\0\0\0\0\0\0\0"), true);
+
+ const shortU16 = ctypes.char16_t.array(10)("千").readTypedArray();
+ assertEq(shortU16 instanceof Uint16Array, true);
+ assertEq(typedArrayMatchesString(shortU16, "千", 'ignore zero-padding, please'), true);
+
+ // ...and for (other) numeric types.
+
+ const I16 = ctypes.int16_t.array(10)().readTypedArray();
+ assertEq(I16 instanceof Int16Array, true);
+
+ const U32 = ctypes.uint32_t.array(10)().readTypedArray();
+ assertEq(U32 instanceof Uint32Array, true);
+
+ const I32 = ctypes.int32_t.array(10)().readTypedArray();
+ assertEq(I32 instanceof Int32Array, true);
+
+ // Check that pointers without associated length get truncated to strlen().
+
+ const unsignedCharArray = ctypes.unsigned_char.array(10)("abc\0\0\0");
+ const shortU8cs = unsignedCharArray.addressOfElement(0).readTypedArray();
+ assertEq(shortU8cs instanceof Uint8Array, true);
+ assertEq(shortU8cs.length, 3);
+ assertEq(typedArrayMatchesString(shortU8cs, "abc", 'stop at NUL, please'), true);
+
+ const signedCharArray = ctypes.signed_char.array(10)("abc\0\0\0");
+ const shortI8cs = signedCharArray.addressOfElement(0).readTypedArray();
+ assertEq(shortI8cs instanceof Int8Array, true);
+ assertEq(shortI8cs.length, 3);
+ assertEq(typedArrayMatchesString(shortI8cs, "abc", 'stop at NUL, please'), true);
+
+ const char16Array = ctypes.char16_t.array(10)("千\0");
+ const shortU16cs = char16Array.addressOfElement(0).readTypedArray();
+ assertEq(shortU16cs instanceof Uint16Array, true);
+ assertEq(shortU16cs.length, 1);
+ assertEq(typedArrayMatchesString(shortU16cs, "千", 'ignore zero-padding, please'), true);
+
+ // Other types should just fail if the length is not known.
+
+ assertTypeErrorMessage(() => { ctypes.int32_t.array(3)().addressOfElement(0).readTypedArray(); },
+ /base type .* is not an 8-bit or 16-bit integer or character type/);
+ assertTypeErrorMessage(() => { ctypes.float.array(3)().addressOfElement(0).readTypedArray(); },
+ /base type .* is not an 8-bit or 16-bit integer or character type/);
+ assertTypeErrorMessage(() => { ctypes.double.array(3)().addressOfElement(0).readTypedArray(); },
+ /base type .* is not an 8-bit or 16-bit integer or character type/);
+ // char16_t is unsigned, so this is not a string type.
+ assertTypeErrorMessage(() => { ctypes.int16_t.array(3)().addressOfElement(0).readTypedArray(); },
+ /base type .* is not an 8-bit or 16-bit integer or character type/);
+
+ // Wide string -> bytes -> UTF-8 encoded string in typed array
+
+ const input2 = "千千千千千千千千千千千千千千千千千千千千千千千千千";
+ const encoded = ctypes.char.array(input2.length * 3)(input2).readTypedArray();
+ // Each 千 character is encoded as 3 bytes.
+ assertEq(encoded.length, input2.length * 3);
+
+ // Wide string -> char16_t -> 16-bit encoded string in typed array
+
+ const encoded16 = ctypes.char16_t.array(input2.length)(input2).readTypedArray();
+ assertEq(encoded16.length, input2.length);
+
+ // Floats
+
+ const floats = ctypes.float.array(3)([10, 20, 30]).readTypedArray();
+ assertEq(floats instanceof Float32Array, true);
+ assertEq(floats.toString(), "10,20,30");
+
+ const doubles = ctypes.double.array(3)([10, 20, 30]).readTypedArray();
+ assertEq(doubles instanceof Float64Array, true);
+ assertEq(doubles.toString(), "10,20,30");
+
+ // Invalid
+
+ assertTypeErrorMessage(() => { ctypes.int64_t.array(3)([10, 20, 30]).readTypedArray() },
+ /base type ctypes.int64_t.array.*is not compatible with a typed array element type/);
+
+}
+
+if (typeof ctypes === "object")
+ test();