1010
1111#include " include/StrType.hh"
1212#include " include/JSStringProxy.hh"
13+ #include " include/jsTypeFactory.hh"
1314
1415#include < jsapi.h>
1516#include < js/String.h>
@@ -58,15 +59,15 @@ static bool containsSurrogatePair(const char16_t *chars, size_t length) {
5859 * @return PyObject* - the UCS4-encoding of the pyObject string
5960 *
6061 */
61- static PyObject *asUCS4 (PyObject *pyObject ) {
62- if (PyUnicode_KIND (pyObject ) != PyUnicode_2BYTE_KIND) {
62+ static PyObject *asUCS4 (PyObject *pyString ) {
63+ if (PyUnicode_KIND (pyString ) != PyUnicode_2BYTE_KIND) {
6364 // return a new reference to match the behaviour of `PyUnicode_FromKindAndData`
64- Py_INCREF (pyObject );
65- return pyObject ;
65+ Py_INCREF (pyString );
66+ return pyString ;
6667 }
6768
68- uint16_t *chars = PY_UNICODE_OBJECT_DATA_UCS2 (pyObject );
69- size_t length = PY_UNICODE_OBJECT_LENGTH (pyObject );
69+ uint16_t *chars = PY_UNICODE_OBJECT_DATA_UCS2 (pyString );
70+ size_t length = PY_UNICODE_OBJECT_LENGTH (pyString );
7071
7172 uint32_t *ucs4String = new uint32_t [length];
7273 size_t ucs4Length = 0 ;
@@ -94,45 +95,51 @@ static PyObject *asUCS4(PyObject *pyObject) {
9495 return ret;
9596}
9697
97- static PyObject *processString (JSContext *cx, JSString *str) {
98+ static PyObject *processString (JSContext *cx, JS::HandleValue strVal) {
99+ JS::RootedString str (cx, strVal.toString ());
98100 JSLinearString *lstr = JS_EnsureLinearString (cx, str);
99101 JS::AutoCheckCannotGC nogc;
100102 PyObject *p;
101103
102104 size_t length = JS::GetLinearStringLength (lstr);
103105
104- PyObject *pyObject = (PyObject *)PyObject_New (JSStringProxy, &JSStringProxyType); // new reference
105- Py_INCREF (pyObject);
106+ JSStringProxy *pyString = PyObject_New (JSStringProxy, &JSStringProxyType); // new reference
106107
107- ((JSStringProxy *)pyObject)->jsString .setString ((JSString *)lstr);
108+ if (pyString == NULL ) {
109+ return NULL ;
110+ }
111+
112+ JS::RootedObject obj (cx);
113+ pyString->jsString = new JS::PersistentRootedValue (cx);
114+ pyString->jsString ->setString ((JSString *)lstr);
108115
109116 // Initialize as legacy string (https://github.com/python/cpython/blob/v3.12.0b1/Include/cpython/unicodeobject.h#L78-L93)
110117 // see https://github.com/python/cpython/blob/v3.11.3/Objects/unicodeobject.c#L1230-L1245
111- PY_UNICODE_OBJECT_HASH (pyObject ) = -1 ;
112- PY_UNICODE_OBJECT_STATE (pyObject ).interned = 0 ;
113- PY_UNICODE_OBJECT_STATE (pyObject ).compact = 0 ;
114- PY_UNICODE_OBJECT_STATE (pyObject ).ascii = 0 ;
115- PY_UNICODE_OBJECT_UTF8 (pyObject ) = NULL ;
116- PY_UNICODE_OBJECT_UTF8_LENGTH (pyObject ) = 0 ;
118+ PY_UNICODE_OBJECT_HASH (pyString ) = -1 ;
119+ PY_UNICODE_OBJECT_STATE (pyString ).interned = 0 ;
120+ PY_UNICODE_OBJECT_STATE (pyString ).compact = 0 ;
121+ PY_UNICODE_OBJECT_STATE (pyString ).ascii = 0 ;
122+ PY_UNICODE_OBJECT_UTF8 (pyString ) = NULL ;
123+ PY_UNICODE_OBJECT_UTF8_LENGTH (pyString ) = 0 ;
117124
118125 if (JS::LinearStringHasLatin1Chars (lstr)) { // latin1 spidermonkey, latin1 python
119126 const JS::Latin1Char *chars = JS::GetLatin1LinearStringChars (nogc, lstr);
120127
121- PY_UNICODE_OBJECT_DATA_ANY (pyObject ) = (void *)chars;
122- PY_UNICODE_OBJECT_KIND (pyObject ) = PyUnicode_1BYTE_KIND;
123- PY_UNICODE_OBJECT_LENGTH (pyObject ) = length;
128+ PY_UNICODE_OBJECT_DATA_ANY (pyString ) = (void *)chars;
129+ PY_UNICODE_OBJECT_KIND (pyString ) = PyUnicode_1BYTE_KIND;
130+ PY_UNICODE_OBJECT_LENGTH (pyString ) = length;
124131 #if PY_UNICODE_HAS_WSTR
125- PY_UNICODE_OBJECT_WSTR (pyObject ) = NULL ;
126- PY_UNICODE_OBJECT_WSTR_LENGTH (pyObject ) = 0 ;
127- PY_UNICODE_OBJECT_READY (pyObject ) = 1 ;
132+ PY_UNICODE_OBJECT_WSTR (pyString ) = NULL ;
133+ PY_UNICODE_OBJECT_WSTR_LENGTH (pyString ) = 0 ;
134+ PY_UNICODE_OBJECT_READY (pyString ) = 1 ;
128135 #endif
129136 }
130137 else { // utf16 spidermonkey, ucs2 python
131138 const char16_t *chars = JS::GetTwoByteLinearStringChars (nogc, lstr);
132139
133- PY_UNICODE_OBJECT_DATA_ANY (pyObject ) = (void *)chars;
134- PY_UNICODE_OBJECT_KIND (pyObject ) = PyUnicode_2BYTE_KIND;
135- PY_UNICODE_OBJECT_LENGTH (pyObject ) = length;
140+ PY_UNICODE_OBJECT_DATA_ANY (pyString ) = (void *)chars;
141+ PY_UNICODE_OBJECT_KIND (pyString ) = PyUnicode_2BYTE_KIND;
142+ PY_UNICODE_OBJECT_LENGTH (pyString ) = length;
136143
137144 #if PY_UNICODE_HAS_WSTR
138145 // python unicode objects take advantage of a possible performance gain on systems where
@@ -141,38 +148,49 @@ static PyObject *processString(JSContext *cx, JSString *str) {
141148 // On systems where sizeof(wchar_t) == 4, i.e. Unixy systems, a similar performance gain happens if the
142149 // string is using UCS4 encoding [this is automatically handled by asUCS4()]
143150 if (sizeof (wchar_t ) == 2 ) {
144- PY_UNICODE_OBJECT_WSTR (pyObject ) = (wchar_t *)chars;
145- PY_UNICODE_OBJECT_WSTR_LENGTH (pyObject ) = length;
151+ PY_UNICODE_OBJECT_WSTR (pyString ) = (wchar_t *)chars;
152+ PY_UNICODE_OBJECT_WSTR_LENGTH (pyString ) = length;
146153 }
147154 else {
148- PY_UNICODE_OBJECT_WSTR (pyObject ) = NULL ;
149- PY_UNICODE_OBJECT_WSTR_LENGTH (pyObject ) = 0 ;
155+ PY_UNICODE_OBJECT_WSTR (pyString ) = NULL ;
156+ PY_UNICODE_OBJECT_WSTR_LENGTH (pyString ) = 0 ;
150157 }
151- PY_UNICODE_OBJECT_READY (pyObject ) = 1 ;
158+ PY_UNICODE_OBJECT_READY (pyString ) = 1 ;
152159 #endif
153160
154161 if (containsSurrogatePair (chars, length)) {
155162 // We must convert to UCS4 here because Python does not support decoding string containing surrogate pairs to bytes
156- PyObject *ucs4Obj = asUCS4 (pyObject ); // convert to a new PyUnicodeObject with UCS4 data
163+ PyObject *ucs4Obj = asUCS4 ((PyObject *)pyString ); // convert to a new PyUnicodeObject with UCS4 data
157164 if (!ucs4Obj) {
158- // conversion fails, keep the original `pyObject `
159- return pyObject ;
165+ // conversion fails, keep the original `pyString `
166+ return (PyObject *)pyString ;
160167 }
161- Py_DECREF (pyObject );
168+ Py_DECREF (pyString );
162169 return ucs4Obj;
163170 }
164171 }
165172
166- return pyObject ;
173+ return (PyObject *)pyString ;
167174}
168175
169- PyObject *StrType::getPyObject (JSContext *cx, JSString *str) {
176+ PyObject *StrType::getPyObject (JSContext *cx, JS::HandleValue str) {
177+ const PythonExternalString *callbacks;
178+ const char16_t *chars;
179+
180+ if (JS::IsExternalString (str.toString (), (const JSExternalStringCallbacks **)&callbacks, &chars)) {
181+ if (callbacks == &PythonExternalStringCallbacks) {
182+ PyObject *pyString = callbacks->getPyString (chars);
183+ Py_INCREF (pyString);
184+ return pyString;
185+ }
186+ }
187+
170188 return processString (cx, str);
171189}
172190
173- const char *StrType::getValue (JSContext *cx, JSString * str) {
174- PyObject *pyObject = processString (cx, str);
175- const char *value = PyUnicode_AsUTF8 (pyObject );
176- Py_DECREF (pyObject );
191+ const char *StrType::getValue (JSContext *cx, JS::HandleValue str) {
192+ PyObject *pyString = processString (cx, str);
193+ const char *value = PyUnicode_AsUTF8 (pyString );
194+ Py_DECREF (pyString );
177195 return value;
178196}
0 commit comments