Reputation: 697
According to the Parser API you can call Reflect.parse()
to get an AST back. Unfortunately, when trying to evaluate a script in C++ it gives me an error saying ReferenceError: Reflect is not defined
:
const char *script = "var r = Reflect.parse(\"obj.foo + 42\");";
bool ok = JS_EvaluateScript(cx, global, script, strlen(script), filename, lineno, rval.address());
Actually, I want to parse some simple JS Scripts and get the AST within C++, I don't like the way doing a detour and having it analyzed in JS itself. Do you have any suggestions? The documentation is not very good imho.
I tried using JS_CompileScript()
, but it seems like 1) the members of JSScript
class are not visible when using the compiled lib 2) don't have information about the tree anymore (?).
I'm tempted to use the very old version 1.6 as there is a very nice parsing tutorial out there. What are your thoughts about that?
Another way would be not to compile SpiderMonkey and use the Parser classes directly.
Any hints/suggestions in what the best way (in your opinion) would be are highly appreciated. Thank you :)
Upvotes: 1
Views: 495
Reputation: 151
Actually, I want to parse some simple JS Scripts and get the AST within C++, I don't like the way doing a detour and having it analyzed in JS itself. Do you have any suggestions?
If patching the Monkey is (was) an option for you, I have a possible approach. I'm doing this with SpiderMonkey 45, but the Reflect API already existed in 24.
In ReflectParse.cpp:3593
, there's the function
static bool reflect_parse(JSContext* cx, uint32_t argc, Value* vp)
Make that non-static and declare it in jsapi.h
like this:
extern JS_PUBLIC_API(bool) reflect_parse(JSContext* cx, uint32_t argc, JS::Value* vp);
Actually, this is copy/paste from the JS_InitReflectParse
declaration in said file. Now you can call the C implementation of Reflect.parse()
from outside.
You'll also need a bunch of private headers, I currently include these: builtin/ModuleObject.h
, jscntxt.h
, jscompartment.h
, jsobj.h
, frontend/ParseNode.h
The Value* vp
that reflect_parse
expects as second parameter is a JS::AutoValueArray<3>
constructed as follows:
JSValue
to the returned object. CallArgs::rval()
retrieves it from there.JS::AutoValueArray<n>
that contains the parameters for Reflect.parse
.So for a simple call like Reflect.parse(code)
, the parameters can look like this:
JS::RootedString codeJsStr(context); // Empty string for now
JS::AutoValueArray<1> parseParams(context);
parseParams[0].setString(codeJsStr);
JS::AutoValueArray<3> vp(m_context);
vp[2].set(*parseParams.begin());
reflect_parse(m_context, parseParams.length(), vp.begin());
The return value can then be processed with help of CallArgs
just like it is documented for calling js functions from C.
Upvotes: 3