55 * @version 0.1
66 * @date 2023-03-29
77 *
8- * @copyright Copyright (c) 2023
8+ * @copyright Copyright (c) 2023 Distributive Corp.
99 *
1010 */
1111
@@ -188,7 +188,7 @@ static PyObject *eval(PyObject *self, PyObject *args) {
188188
189189 JSAutoRealm ar (GLOBAL_CX, *global);
190190 JS::CompileOptions options (GLOBAL_CX);
191- options.setFileAndLine (" @ evaluate" , 1 )
191+ options.setFileAndLine (" evaluate" , 1 )
192192 .setIsRunOnce (true )
193193 .setNoScriptRval (false )
194194 .setIntroductionType (" pythonmonkey eval" );
@@ -206,9 +206,29 @@ static PyObject *eval(PyObject *self, PyObject *args) {
206206 if (getEvalOption (evalOptions, " selfHosting" , &b)) options.setSelfHostingMode (b);
207207 if (getEvalOption (evalOptions, " strict" , &b)) if (b) options.setForceStrictMode ();
208208 if (getEvalOption (evalOptions, " module" , &b)) if (b) options.setModule ();
209- }
210209
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
212232 JS::SourceText<mozilla::Utf8Unit> source;
213233 if (!source.init (GLOBAL_CX, code->getValue (), strlen (code->getValue ()), JS::SourceOwnership::Borrowed)) {
214234 setSpiderMonkeyException (GLOBAL_CX);
@@ -230,13 +250,13 @@ static PyObject *eval(PyObject *self, PyObject *args) {
230250 }
231251
232252 // 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
234254 if (rval->isObject ()) {
235255 JS::GetBuiltinClass (GLOBAL_CX, JS::RootedObject (GLOBAL_CX, &rval->toObject ()), &cls);
236256 }
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.
240260 delete rval;
241261 }
242262
@@ -278,7 +298,7 @@ struct PyModuleDef pythonmonkey =
278298{
279299 PyModuleDef_HEAD_INIT,
280300 " 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 */
282302 -1 , /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
283303 PythonMonkeyMethods
284304};
@@ -302,29 +322,29 @@ static bool setTimeout(JSContext *cx, unsigned argc, JS::Value *vp) {
302322
303323 // Get the function to be executed
304324 // 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
306326 JS::RootedValue *jobArg = new JS::RootedValue (cx, jobArgVal);
307327 // `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
309329 // Wrap the job function into a bound function with the given additional arguments
310330 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
311331 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 */
313333 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 */
315335 }
316336 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)
318338 }
319339 // Convert to a Python function
320340 PyObject *job = pyTypeFactory (cx, thisv, jobArg)->getPyObject ();
321341
322342 // Get the delay time
323343 // 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
328348
329349 // Schedule job to the running Python event-loop
330350 PyEventLoop loop = PyEventLoop::getRunningLoop ();
@@ -355,7 +375,7 @@ static bool clearTimeout(JSContext *cx, unsigned argc, JS::Value *vp) {
355375 // Retrieve the AsyncHandle by `timeoutID`
356376 int32_t timeoutID = timeoutIdArg.toInt32 ();
357377 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
359379
360380 // Cancel this job on Python event-loop
361381 handle->cancel ();
@@ -424,7 +444,7 @@ PyMODINIT_FUNC PyInit_pythonmonkey(void)
424444 // 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)
425445 // Temporarily solved by explicitly setting the `domProxyShadowsCheck` callback here
426446 JS::SetDOMProxyInformation (nullptr ,
427- [](JSContext *, JS::HandleObject, JS::HandleId) { // domProxyShadowsCheck
447+ [](JSContext *, JS::HandleObject, JS::HandleId) { // domProxyShadowsCheck
428448 return JS::DOMProxyShadowsResult::ShadowCheckFailed;
429449 }, nullptr );
430450
0 commit comments