Skip to content

Commit

Permalink
implement Py to JS string conversion [not working yet]
Browse files Browse the repository at this point in the history
  • Loading branch information
zollqir committed Mar 3, 2023
1 parent 5834ae5 commit 8283b1c
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 9 deletions.
3 changes: 2 additions & 1 deletion include/jsTypeFactory.hh
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
/**
* @brief Function that takes a PyType and returns a corresponding JS::Value, doing shared memory management when necessary
*
* @param cx - Pointer to the JSContext
* @param object - Pointer to the PyObject who's type and value we wish to encapsulate
* @return JS::Value - A JS::Value corresponding to the PyType
*/
JS::Value jsTypeFactory(PyObject *object);
JS::Value jsTypeFactory(JSContext *cx, PyObject *object);

#endif
57 changes: 55 additions & 2 deletions src/jsTypeFactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,39 @@
#include "include/jsTypeFactory.hh"

#include "include/modules/pythonmonkey/pythonmonkey.hh"
#include "include/StrType.hh"

#include <jsapi.h>

JS::Value jsTypeFactory(PyObject *object) {
JS::Value returnType;
#include <Python.h>

#define HIGH_SURROGATE_START 0xD800
#define HIGH_SURROGATE_END 0xDBFF
#define LOW_SURROGATE_START 0xDC00
#define LOW_SURROGATE_END 0xDFFF
#define BMP_END 0x10000

size_t UCS4ToUTF16(const uint32_t *chars, size_t length, uint16_t *outStr) {
uint16_t utf16String[length*2];
size_t utf16Length = 0;

for (size_t i = 0; i < length; i++) {
if (chars[i] < HIGH_SURROGATE_START || (chars[i] > LOW_SURROGATE_END && chars[i] < BMP_END)) {
utf16String[utf16Length] = uint16_t(chars[i]);
utf16Length += 1;
}
else {
utf16String[utf16Length] = uint16_t(((0b1111'1111'1100'0000'0000 & (chars[i] - BMP_END)) >> 10) + HIGH_SURROGATE_START);
utf16String[utf16Length + 1] = uint16_t(((0b0000'0000'0011'1111'1111 & (chars[i] - BMP_END)) >> 00) + LOW_SURROGATE_START);
utf16Length += 2;
}
}
outStr = utf16String;
return utf16Length;
}

JS::Value jsTypeFactory(JSContext *cx, PyObject *object) {
JS::RootedValue returnType(cx);

if (PyBool_Check(object)) {
returnType.setBoolean(PyLong_AsLong(object));
Expand All @@ -27,6 +55,31 @@ JS::Value jsTypeFactory(PyObject *object) {
else if (PyFloat_Check(object)) {
returnType.setNumber(PyFloat_AsDouble(object));
}
else if (PyUnicode_Check(object)) {
switch (PyUnicode_KIND(object)) {
case (PyUnicode_4BYTE_KIND): {
uint32_t *u32Chars = PyUnicode_4BYTE_DATA(object);
uint16_t *u16Chars;
size_t u16Length = UCS4ToUTF16(u32Chars, PyUnicode_GET_LENGTH(object), u16Chars);
JSString *str = JS_NewUCStringCopyN(cx, (char16_t *)u16Chars, u16Length);
returnType.setString(str);
break;
}
case (PyUnicode_2BYTE_KIND): {
JS::UniqueTwoByteChars chars((char16_t *)PyUnicode_2BYTE_DATA(object));
JSString *str = JS_NewUCString(cx, std::move(chars), PyUnicode_GET_LENGTH(object));
returnType.setString(str);
break;
}
case (PyUnicode_1BYTE_KIND): {
JS::UniqueLatin1Chars chars(PyUnicode_1BYTE_DATA(object));
JSString *str = JS_NewLatin1String(cx, std::move(chars), PyUnicode_GET_LENGTH(object));
returnType.setString(str);
break;
}
}
memoizePyTypeAndGCThing(new StrType(object), returnType);
}
else if (object == Py_None) {
returnType.setUndefined();
}
Expand Down
4 changes: 2 additions & 2 deletions src/modules/pythonmonkey/pythonmonkey.cc
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ PyMODINIT_FUNC PyInit_pythonmonkey(void)
PyErr_SetString(SpiderMonkeyError, "Spidermonkey could not be initialized.");
return NULL;
}


cx = JS_NewContext(JS::DefaultHeapMaxBytes);
if (!cx) {
Expand Down Expand Up @@ -255,4 +255,4 @@ PyMODINIT_FUNC PyInit_pythonmonkey(void)
return NULL;
}
return pyModule;
}
}
5 changes: 2 additions & 3 deletions src/pyTypeFactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,7 @@ static PyObject *callJSFunc(PyObject *JSCxGlobalFuncTuple, PyObject *args) {

JS::RootedVector<JS::Value> JSargsVector(JScontext);
for (size_t i = 0; i < PyTuple_Size(args); i++) {
// TODO (Caleb Aikens) write an overload for jsTypeFactory to handle PyObjects directly
JS::Value jsValue = jsTypeFactory(PyTuple_GetItem(args, i));
JS::Value jsValue = jsTypeFactory(JScontext, PyTuple_GetItem(args, i));
JSargsVector.append(jsValue);
}

Expand All @@ -146,6 +145,6 @@ static PyObject *callJSFunc(PyObject *JSCxGlobalFuncTuple, PyObject *args) {
setSpiderMonkeyException(JScontext);
return NULL;
}

return pyTypeFactory(JScontext, globalObject, JSreturnVal)->getPyObject();
}
2 changes: 1 addition & 1 deletion src/setSpiderMonkeyException.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,4 @@ void setSpiderMonkeyException(JSContext *cx) {
}

PyErr_SetString(SpiderMonkeyError, outStrStream.str().c_str());
}
}

0 comments on commit 8283b1c

Please sign in to comment.