From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- js/src/jit-test/tests/ctypes/AddressOfField.js | 12 +++ .../jit-test/tests/ctypes/argument-length-abi.js | 11 +++ .../jit-test/tests/ctypes/argument-length-array.js | 15 +++ .../jit-test/tests/ctypes/argument-length-cdata.js | 18 ++++ .../tests/ctypes/argument-length-ctypes.js | 11 +++ .../tests/ctypes/argument-length-finalizer.js | 16 ++++ .../tests/ctypes/argument-length-function.js | 11 +++ .../jit-test/tests/ctypes/argument-length-int64.js | 40 ++++++++ .../tests/ctypes/argument-length-pointer.js | 11 +++ .../tests/ctypes/argument-length-primitive.js | 11 +++ .../tests/ctypes/argument-length-struct.js | 17 ++++ .../jit-test/tests/ctypes/argument-type-array.js | 17 ++++ .../jit-test/tests/ctypes/argument-type-ctypes.js | 13 +++ .../tests/ctypes/argument-type-function.js | 9 ++ .../jit-test/tests/ctypes/argument-type-int64.js | 28 ++++++ .../jit-test/tests/ctypes/argument-type-pointer.js | 9 ++ .../jit-test/tests/ctypes/argument-type-struct.js | 17 ++++ js/src/jit-test/tests/ctypes/array-index.js | 29 ++++++ js/src/jit-test/tests/ctypes/bug1155985.js | 14 +++ js/src/jit-test/tests/ctypes/cast.js | 12 +++ js/src/jit-test/tests/ctypes/construct.js | 11 +++ js/src/jit-test/tests/ctypes/conversion-array.js | 36 ++++++++ js/src/jit-test/tests/ctypes/conversion-error.js | 14 +++ .../jit-test/tests/ctypes/conversion-finalizer.js | 63 +++++++++++++ .../jit-test/tests/ctypes/conversion-function.js | 33 +++++++ js/src/jit-test/tests/ctypes/conversion-int64.js | 20 ++++ .../tests/ctypes/conversion-native-function.js | 37 ++++++++ js/src/jit-test/tests/ctypes/conversion-pointer.js | 29 ++++++ .../jit-test/tests/ctypes/conversion-primitive.js | 44 +++++++++ js/src/jit-test/tests/ctypes/conversion-struct.js | 36 ++++++++ .../jit-test/tests/ctypes/conversion-to-number.js | 98 ++++++++++++++++++++ .../tests/ctypes/conversion-to-primitive.js | 20 ++++ .../jit-test/tests/ctypes/function-definition.js | 47 ++++++++++ js/src/jit-test/tests/ctypes/incompatible-abi.js | 11 +++ js/src/jit-test/tests/ctypes/incompatible-array.js | 13 +++ js/src/jit-test/tests/ctypes/incompatible-cdata.js | 27 ++++++ js/src/jit-test/tests/ctypes/incompatible-ctype.js | 13 +++ .../tests/ctypes/incompatible-finalizer.js | 26 ++++++ .../jit-test/tests/ctypes/incompatible-function.js | 13 +++ js/src/jit-test/tests/ctypes/incompatible-int64.js | 28 ++++++ .../jit-test/tests/ctypes/incompatible-pointer.js | 19 ++++ .../jit-test/tests/ctypes/incompatible-struct.js | 31 +++++++ js/src/jit-test/tests/ctypes/pointer.js | 31 +++++++ .../jit-test/tests/ctypes/size-overflow-array.js | 18 ++++ .../jit-test/tests/ctypes/size-overflow-struct.js | 24 +++++ js/src/jit-test/tests/ctypes/struct-field.js | 21 +++++ js/src/jit-test/tests/ctypes/typedarrays.js | 102 +++++++++++++++++++++ 47 files changed, 1186 insertions(+) create mode 100644 js/src/jit-test/tests/ctypes/AddressOfField.js create mode 100644 js/src/jit-test/tests/ctypes/argument-length-abi.js create mode 100644 js/src/jit-test/tests/ctypes/argument-length-array.js create mode 100644 js/src/jit-test/tests/ctypes/argument-length-cdata.js create mode 100644 js/src/jit-test/tests/ctypes/argument-length-ctypes.js create mode 100644 js/src/jit-test/tests/ctypes/argument-length-finalizer.js create mode 100644 js/src/jit-test/tests/ctypes/argument-length-function.js create mode 100644 js/src/jit-test/tests/ctypes/argument-length-int64.js create mode 100644 js/src/jit-test/tests/ctypes/argument-length-pointer.js create mode 100644 js/src/jit-test/tests/ctypes/argument-length-primitive.js create mode 100644 js/src/jit-test/tests/ctypes/argument-length-struct.js create mode 100644 js/src/jit-test/tests/ctypes/argument-type-array.js create mode 100644 js/src/jit-test/tests/ctypes/argument-type-ctypes.js create mode 100644 js/src/jit-test/tests/ctypes/argument-type-function.js create mode 100644 js/src/jit-test/tests/ctypes/argument-type-int64.js create mode 100644 js/src/jit-test/tests/ctypes/argument-type-pointer.js create mode 100644 js/src/jit-test/tests/ctypes/argument-type-struct.js create mode 100644 js/src/jit-test/tests/ctypes/array-index.js create mode 100644 js/src/jit-test/tests/ctypes/bug1155985.js create mode 100644 js/src/jit-test/tests/ctypes/cast.js create mode 100644 js/src/jit-test/tests/ctypes/construct.js create mode 100644 js/src/jit-test/tests/ctypes/conversion-array.js create mode 100644 js/src/jit-test/tests/ctypes/conversion-error.js create mode 100644 js/src/jit-test/tests/ctypes/conversion-finalizer.js create mode 100644 js/src/jit-test/tests/ctypes/conversion-function.js create mode 100644 js/src/jit-test/tests/ctypes/conversion-int64.js create mode 100644 js/src/jit-test/tests/ctypes/conversion-native-function.js create mode 100644 js/src/jit-test/tests/ctypes/conversion-pointer.js create mode 100644 js/src/jit-test/tests/ctypes/conversion-primitive.js create mode 100644 js/src/jit-test/tests/ctypes/conversion-struct.js create mode 100644 js/src/jit-test/tests/ctypes/conversion-to-number.js create mode 100644 js/src/jit-test/tests/ctypes/conversion-to-primitive.js create mode 100644 js/src/jit-test/tests/ctypes/function-definition.js create mode 100644 js/src/jit-test/tests/ctypes/incompatible-abi.js create mode 100644 js/src/jit-test/tests/ctypes/incompatible-array.js create mode 100644 js/src/jit-test/tests/ctypes/incompatible-cdata.js create mode 100644 js/src/jit-test/tests/ctypes/incompatible-ctype.js create mode 100644 js/src/jit-test/tests/ctypes/incompatible-finalizer.js create mode 100644 js/src/jit-test/tests/ctypes/incompatible-function.js create mode 100644 js/src/jit-test/tests/ctypes/incompatible-int64.js create mode 100644 js/src/jit-test/tests/ctypes/incompatible-pointer.js create mode 100644 js/src/jit-test/tests/ctypes/incompatible-struct.js create mode 100644 js/src/jit-test/tests/ctypes/pointer.js create mode 100644 js/src/jit-test/tests/ctypes/size-overflow-array.js create mode 100644 js/src/jit-test/tests/ctypes/size-overflow-struct.js create mode 100644 js/src/jit-test/tests/ctypes/struct-field.js create mode 100644 js/src/jit-test/tests/ctypes/typedarrays.js (limited to 'js/src/jit-test/tests/ctypes') 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); }, + "<> 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 <> 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 <>"); + assertTypeErrorMessage(() => { o.readStringReplaceMalformed(); }, + "CData.prototype.readStringReplaceMalformed called on incompatible object, got <>"); +} + +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 <>"); + assertTypeErrorMessage(() => { o.x = 1; }, + "StructType property setter called on incompatible object, got <>"); + + 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(); -- cgit v1.2.3