* Implement the pythonmonkey.eval function. From Python-land, that function has the following API: * argument 0 - unicode string of JS code or open file containing JS code in UTF-8 * argument 1 - a Dict of options which roughly correspond to the jsapi CompileOptions. A novel option, * fromPythonFrame, sets the filename and line offset according to the pm.eval call in the *
| 377 | * and still get stack dumps which point to the source code. |
| 378 | */ |
| 379 | static PyObject *eval(PyObject *self, PyObject *args) { |
| 380 | size_t argc = PyTuple_GET_SIZE(args); |
| 381 | if (argc > 2 || argc == 0) { |
| 382 | PyErr_SetString(PyExc_TypeError, "pythonmonkey.eval accepts one or two arguments"); |
| 383 | return NULL; |
| 384 | } |
| 385 | |
| 386 | PyObject *code = NULL; |
| 387 | FILE *file = NULL; |
| 388 | PyObject *arg0 = PyTuple_GetItem(args, 0); |
| 389 | PyObject *arg1 = argc == 2 ? PyTuple_GetItem(args, 1) : NULL; |
| 390 | |
| 391 | if (PyUnicode_Check(arg0)) { |
| 392 | code = arg0; |
| 393 | } else if (1 /*PyFile_Check(arg0)*/) { |
| 394 | /* First argument is an open file. Open a stream with a dup of the underlying fd (so we can fclose |
| 395 | * the stream later). Future: seek to current Python file position IFF the fd is for a real file. |
| 396 | */ |
| 397 | int fd = PyObject_AsFileDescriptor(arg0); |
| 398 | int fd2 = fd == -1 ? -1 : dup(fd); |
| 399 | file = fd2 == -1 ? NULL : fdopen(fd, "rb"); |
| 400 | if (!file) { |
| 401 | PyErr_SetString(PyExc_TypeError, "error opening file stream"); |
| 402 | return NULL; |
| 403 | } |
| 404 | } else { |
| 405 | PyErr_SetString(PyExc_TypeError, "pythonmonkey.eval expects either a string or an open file as its first argument"); |
| 406 | return NULL; |
| 407 | } |
| 408 | |
| 409 | PyObject *evalOptions = argc == 2 ? arg1 : NULL; |
| 410 | if (evalOptions && !PyDict_Check(evalOptions)) { |
| 411 | PyErr_SetString(PyExc_TypeError, "pythonmonkey.eval expects a dict as its second argument"); |
| 412 | if (file) |
| 413 | fclose(file); |
| 414 | return NULL; |
| 415 | } |
| 416 | |
| 417 | // initialize JS context |
| 418 | JSAutoRealm ar(GLOBAL_CX, *global); |
| 419 | JS::CompileOptions options (GLOBAL_CX); |
| 420 | options.setFileAndLine("evaluate", 1) |
| 421 | .setIsRunOnce(true) |
| 422 | .setNoScriptRval(false) |
| 423 | .setIntroductionType("pythonmonkey eval"); |
| 424 | |
| 425 | if (evalOptions) { |
| 426 | const char *s; |
| 427 | unsigned long l; |
| 428 | bool b; |
| 429 | |
| 430 | if (getEvalOption(evalOptions, "filename", &s)) options.setFile(s); |
| 431 | if (getEvalOption(evalOptions, "lineno", &l)) options.setLine(l); |
| 432 | if (getEvalOption(evalOptions, "column", &l)) options.setColumn(JS::ColumnNumberOneOrigin(l)); |
| 433 | if (getEvalOption(evalOptions, "mutedErrors", &b)) options.setMutedErrors(b); |
| 434 | if (getEvalOption(evalOptions, "noScriptRval", &b)) options.setNoScriptRval(b); |
| 435 | if (getEvalOption(evalOptions, "selfHosting", &b)) options.setSelfHostingMode(b); |
| 436 | if (getEvalOption(evalOptions, "strict", &b)) if (b) options.setForceStrictMode(); |
no test coverage detected