Skip to content

Commit 3b02465

Browse files
Merge branch 'main' into philippe/396-fix
2 parents 6561d5a + 8f1ac3c commit 3b02465

File tree

4 files changed

+48
-12
lines changed

4 files changed

+48
-12
lines changed

include/PyBytesProxyHandler.hh

+18
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ public:
2424
PyBytesProxyHandler() : PyObjectProxyHandler(&family) {};
2525
static const char family;
2626

27+
/**
28+
* @brief [[Set]]
29+
*
30+
* @param cx pointer to JSContext
31+
* @param proxy The proxy object who's property we wish to set
32+
* @param id Key of the property we wish to set
33+
* @param v Value that we wish to set the property to
34+
* @param receiver The `this` value to use when executing any code
35+
* @param result whether or not the call succeeded
36+
* @return true call succeed
37+
* @return false call failed and an exception has been raised
38+
*/
2739
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
2840
JS::HandleValue v, JS::HandleValue receiver,
2941
JS::ObjectOpResult &result) const override;
@@ -33,6 +45,12 @@ public:
3345
JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc
3446
) const override;
3547

48+
/**
49+
* @brief Handles python object reference count when JS Proxy object is finalized
50+
*
51+
* @param gcx pointer to JS::GCContext
52+
* @param proxy the proxy object being finalized
53+
*/
3654
void finalize(JS::GCContext *gcx, JSObject *proxy) const override;
3755
};
3856

src/BufferType.cc

+9-2
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,19 @@
1616
#include <js/experimental/TypedData.h>
1717
#include <js/ScalarType.h>
1818

19+
#include <limits.h>
1920

2021
// JS to Python
2122

2223
/* static */
2324
const char *BufferType::_toPyBufferFormatCode(JS::Scalar::Type subtype) {
2425
// floating point types
25-
if (subtype == JS::Scalar::Float32) {
26+
switch (subtype) {
27+
case JS::Scalar::Float16:
28+
return "e";
29+
case JS::Scalar::Float32:
2630
return "f";
27-
} else if (subtype == JS::Scalar::Float64) {
31+
case JS::Scalar::Float64:
2832
return "d";
2933
}
3034

@@ -216,8 +220,11 @@ JS::Scalar::Type BufferType::_getPyBufferType(Py_buffer *bufView) {
216220
return JS::Scalar::Float32;
217221
} else if (typeCode == 'd') {
218222
return JS::Scalar::Float64;
223+
} else if (typeCode == 'e') {
224+
return JS::Scalar::Float16;
219225
}
220226

227+
221228
// integer types
222229
// We can't rely on the type codes alone since the typecodes are mapped to C types and would have different sizes on different architectures
223230
// see https://docs.python.org/3.9/library/array.html#module-array

src/PyBytesProxyHandler.cc

+19-10
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,27 @@ static bool array_valueOf(JSContext *cx, unsigned argc, JS::Value *vp) {
3434
bool isSharedMemory;
3535
JS::AutoCheckCannotGC autoNoGC(cx);
3636
uint8_t *data = JS::GetArrayBufferData(rootedArrayBuffer, &isSharedMemory, autoNoGC);
37-
38-
std::string valueOfString;
39-
40-
for (Py_ssize_t index = 0; index < byteLength; index++) {
41-
if (index > 0) {
42-
valueOfString += ",";
43-
}
44-
45-
valueOfString += std::to_string(data[index]);
37+
38+
size_t numberOfDigits = 0;
39+
for (size_t i = 0; i < byteLength; i++) {
40+
numberOfDigits += data[i] < 10 ? 1 : data[i] < 100 ? 2 : 3;
41+
}
42+
const size_t STRING_LENGTH = byteLength + numberOfDigits;
43+
JS::Latin1Char* buffer = (JS::Latin1Char *)malloc(sizeof(JS::Latin1Char) * STRING_LENGTH);
44+
45+
size_t charIndex = 0;
46+
sprintf((char*)&buffer[charIndex], "%d", data[0]);
47+
charIndex += data[0] < 10 ? 1 : data[0] < 100 ? 2 : 3;
48+
49+
for (size_t dataIndex = 1; dataIndex < byteLength; dataIndex++) {
50+
buffer[charIndex] = ',';
51+
charIndex++;
52+
sprintf((char*)&buffer[charIndex], "%d", data[dataIndex]);
53+
charIndex += data[dataIndex] < 10 ? 1 : data[dataIndex] < 100 ? 2 : 3;
4654
}
4755

48-
args.rval().setString(JS_NewStringCopyZ(cx, valueOfString.c_str()));
56+
JS::UniqueLatin1Chars str(buffer);
57+
args.rval().setString(JS_NewLatin1String(cx, std::move(str), STRING_LENGTH - 1)); // don't include null byte
4958
return true;
5059
}
5160

tests/python/test_buffer_typed_array.py

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def assert_js_to_py_memoryview(buf: memoryview):
5050
assert pm.eval("(arr)=>arr instanceof Int16Array")(numpy.array([1], dtype=numpy.int16))
5151
assert pm.eval("(arr)=>arr instanceof Int32Array")(numpy.array([1], dtype=numpy.int32))
5252
assert pm.eval("(arr)=>arr instanceof BigInt64Array")(numpy.array([1], dtype=numpy.int64))
53+
assert pm.eval("(arr)=>arr instanceof Float16Array")(numpy.array([1], dtype=numpy.float16))
5354
assert pm.eval("(arr)=>arr instanceof Float32Array")(numpy.array([1], dtype=numpy.float32))
5455
assert pm.eval("(arr)=>arr instanceof Float64Array")(numpy.array([1], dtype=numpy.float64))
5556
assert pm.eval("new Uint8Array([1])").format == "B"
@@ -60,6 +61,7 @@ def assert_js_to_py_memoryview(buf: memoryview):
6061
assert pm.eval("new Int16Array([1])").format == "h"
6162
assert pm.eval("new Int32Array([1])").format == "i"
6263
assert pm.eval("new BigInt64Array([1n])").format == "q"
64+
assert pm.eval("new Float16Array([1])").format == "e"
6365
assert pm.eval("new Float32Array([1])").format == "f"
6466
assert pm.eval("new Float64Array([1])").format == "d"
6567

0 commit comments

Comments
 (0)