5
5
* @version 0.1
6
6
* @date 2023-03-29
7
7
*
8
- * @copyright Copyright (c) 2023
8
+ * @copyright Copyright (c) 2023 Distributive Corp.
9
9
*
10
10
*/
11
11
@@ -188,7 +188,7 @@ static PyObject *eval(PyObject *self, PyObject *args) {
188
188
189
189
JSAutoRealm ar (GLOBAL_CX, *global);
190
190
JS::CompileOptions options (GLOBAL_CX);
191
- options.setFileAndLine (" @ evaluate" , 1 )
191
+ options.setFileAndLine (" evaluate" , 1 )
192
192
.setIsRunOnce (true )
193
193
.setNoScriptRval (false )
194
194
.setIntroductionType (" pythonmonkey eval" );
@@ -206,9 +206,29 @@ static PyObject *eval(PyObject *self, PyObject *args) {
206
206
if (getEvalOption (evalOptions, " selfHosting" , &b)) options.setSelfHostingMode (b);
207
207
if (getEvalOption (evalOptions, " strict" , &b)) if (b) options.setForceStrictMode ();
208
208
if (getEvalOption (evalOptions, " module" , &b)) if (b) options.setModule ();
209
- }
210
209
211
- // initialize JS context
210
+ if (getEvalOption (evalOptions, " fromPythonFrame" , &b) && b) {
211
+ #if PY_VERSION_HEX >= 0x03090000
212
+ PyFrameObject *frame = PyEval_GetFrame ();
213
+ if (frame && !getEvalOption (evalOptions, " lineno" , &l)) {
214
+ options.setLine (PyFrame_GetLineNumber (frame));
215
+ } /* lineno */
216
+ #endif
217
+ #if 0 && (PY_VERSION_HEX >= 0x030a0000) && (PY_VERSION_HEX < 0x030c0000)
218
+ PyObject *filename = PyDict_GetItemString(frame->f_builtins, "__file__");
219
+ #elif (PY_VERSION_HEX >= 0x030c0000)
220
+ PyObject *filename = PyDict_GetItemString(PyFrame_GetGlobals(frame), "__file__");
221
+ #else
222
+ PyObject *filename = NULL ;
223
+ #endif
224
+ if (!getEvalOption (evalOptions, " filename" , &s)) {
225
+ if (filename && PyUnicode_Check (filename)) {
226
+ options.setFile (PyUnicode_AsUTF8 (filename));
227
+ }
228
+ } /* filename */
229
+ } /* fromPythonFrame */
230
+ } /* eval options */
231
+ // initialize JS context
212
232
JS::SourceText<mozilla::Utf8Unit> source;
213
233
if (!source.init (GLOBAL_CX, code->getValue (), strlen (code->getValue ()), JS::SourceOwnership::Borrowed)) {
214
234
setSpiderMonkeyException (GLOBAL_CX);
@@ -230,13 +250,13 @@ static PyObject *eval(PyObject *self, PyObject *args) {
230
250
}
231
251
232
252
// TODO: Find a better way to destroy the root when necessary (when the returned Python object is GCed).
233
- js::ESClass cls = js::ESClass::Other; // placeholder if `rval` is not a JSObject
253
+ js::ESClass cls = js::ESClass::Other; // placeholder if `rval` is not a JSObject
234
254
if (rval->isObject ()) {
235
255
JS::GetBuiltinClass (GLOBAL_CX, JS::RootedObject (GLOBAL_CX, &rval->toObject ()), &cls);
236
256
}
237
- bool rvalIsFunction = cls == js::ESClass::Function; // function object
238
- bool rvalIsString = rval->isString () || cls == js::ESClass::String; // string primitive or boxed String object
239
- if (!(rvalIsFunction || rvalIsString)) { // rval may be a JS function or string which must be kept alive.
257
+ bool rvalIsFunction = cls == js::ESClass::Function; // function object
258
+ bool rvalIsString = rval->isString () || cls == js::ESClass::String; // string primitive or boxed String object
259
+ if (!(rvalIsFunction || rvalIsString)) { // rval may be a JS function or string which must be kept alive.
240
260
delete rval;
241
261
}
242
262
@@ -278,7 +298,7 @@ struct PyModuleDef pythonmonkey =
278
298
{
279
299
PyModuleDef_HEAD_INIT,
280
300
" pythonmonkey" , /* name of module */
281
- " A module for python to JS interoperability" , /* module documentation, may be NULL */
301
+ " A module for python to JS interoperability" , /* module documentation, may be NULL */
282
302
-1 , /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
283
303
PythonMonkeyMethods
284
304
};
@@ -302,29 +322,29 @@ static bool setTimeout(JSContext *cx, unsigned argc, JS::Value *vp) {
302
322
303
323
// Get the function to be executed
304
324
// FIXME (Tom Tang): memory leak, not free-ed
305
- JS::RootedObject *thisv = new JS::RootedObject (cx, JS::GetNonCCWObjectGlobal (&args.callee ())); // HTML spec requires `thisArg` to be the global object
325
+ JS::RootedObject *thisv = new JS::RootedObject (cx, JS::GetNonCCWObjectGlobal (&args.callee ())); // HTML spec requires `thisArg` to be the global object
306
326
JS::RootedValue *jobArg = new JS::RootedValue (cx, jobArgVal);
307
327
// `setTimeout` allows passing additional arguments to the callback, as spec-ed
308
- if (args.length () > 2 ) { // having additional arguments
328
+ if (args.length () > 2 ) { // having additional arguments
309
329
// Wrap the job function into a bound function with the given additional arguments
310
330
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
311
331
JS::RootedVector<JS::Value> bindArgs (cx);
312
- (void )bindArgs.append (JS::ObjectValue (**thisv)); /* * @todo XXXwg handle return value */
332
+ (void )bindArgs.append (JS::ObjectValue (**thisv)); /* * @todo XXXwg handle return value */
313
333
for (size_t j = 2 ; j < args.length (); j++) {
314
- (void )bindArgs.append (args[j]); /* * @todo XXXwg handle return value */
334
+ (void )bindArgs.append (args[j]); /* * @todo XXXwg handle return value */
315
335
}
316
336
JS::RootedObject jobArgObj = JS::RootedObject (cx, &jobArgVal.toObject ());
317
- JS_CallFunctionName (cx, jobArgObj, " bind" , JS::HandleValueArray (bindArgs), jobArg); // jobArg = jobArg.bind(thisv, ...bindArgs)
337
+ JS_CallFunctionName (cx, jobArgObj, " bind" , JS::HandleValueArray (bindArgs), jobArg); // jobArg = jobArg.bind(thisv, ...bindArgs)
318
338
}
319
339
// Convert to a Python function
320
340
PyObject *job = pyTypeFactory (cx, thisv, jobArg)->getPyObject ();
321
341
322
342
// Get the delay time
323
343
// JS `setTimeout` takes milliseconds, but Python takes seconds
324
- double delayMs = 0 ; // use value of 0 if the delay parameter is omitted
325
- if (args.hasDefined (1 )) { JS::ToNumber (cx, args[1 ], &delayMs); } // implicitly do type coercion to a `number`
326
- if (delayMs < 0 ) { delayMs = 0 ; } // as spec-ed
327
- double delaySeconds = delayMs / 1000 ; // convert ms to s
344
+ double delayMs = 0 ; // use value of 0 if the delay parameter is omitted
345
+ if (args.hasDefined (1 )) { JS::ToNumber (cx, args[1 ], &delayMs); } // implicitly do type coercion to a `number`
346
+ if (delayMs < 0 ) { delayMs = 0 ; } // as spec-ed
347
+ double delaySeconds = delayMs / 1000 ; // convert ms to s
328
348
329
349
// Schedule job to the running Python event-loop
330
350
PyEventLoop loop = PyEventLoop::getRunningLoop ();
@@ -355,7 +375,7 @@ static bool clearTimeout(JSContext *cx, unsigned argc, JS::Value *vp) {
355
375
// Retrieve the AsyncHandle by `timeoutID`
356
376
int32_t timeoutID = timeoutIdArg.toInt32 ();
357
377
AsyncHandle *handle = AsyncHandle::fromId ((uint32_t )timeoutID);
358
- if (!handle) return true ; // does nothing on invalid timeoutID
378
+ if (!handle) return true ; // does nothing on invalid timeoutID
359
379
360
380
// Cancel this job on Python event-loop
361
381
handle->cancel ();
@@ -424,7 +444,7 @@ PyMODINIT_FUNC PyInit_pythonmonkey(void)
424
444
// In https://hg.mozilla.org/releases/mozilla-esr102/file/3b574e1/js/src/jit/CacheIR.cpp#l317, trying to use the callback returned by `js::GetDOMProxyShadowsCheck()` even it's unset (nullptr)
425
445
// Temporarily solved by explicitly setting the `domProxyShadowsCheck` callback here
426
446
JS::SetDOMProxyInformation (nullptr ,
427
- [](JSContext *, JS::HandleObject, JS::HandleId) { // domProxyShadowsCheck
447
+ [](JSContext *, JS::HandleObject, JS::HandleId) { // domProxyShadowsCheck
428
448
return JS::DOMProxyShadowsResult::ShadowCheckFailed;
429
449
}, nullptr );
430
450
0 commit comments