Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How can I call variable in script like this global.var

74 views
Skip to first unread message

muhammad sami

unread,
Apr 1, 2019, 11:41:25 AM4/1/19
to
in class --> JavaScriptEngine
bool run(JSContext *cx, RootedObject *globaloObj, const char *script, const char *filename = "noname", int lineno = 1) {
JSAutoRequest ar(cx);
JSAutoCompartment ac(cx, *globaloObj);

JS::RootedValue rval(cx);

JS::CompileOptions opts(cx);
opts.setFileAndLine(filename, lineno);

bool ok = JS::Evaluate(cx, opts, script, strlen(script), &rval);

if (!ok)
return 1;

JSString *str = rval.toString();

printf("output: %s\n", JS_EncodeString(cx, str));

}

JSClass JavaScriptEngine::document_class = {
"global",
JSCLASS_GLOBAL_FLAGS,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, nullptr, nullptr, nullptr,
JS_GlobalObjectTraceHook
};

in main(){
JavaScriptEngine e;
run(e.cx, e.dialog, "x=5");
run(cx,e.dialog, "global.x");
}

-----output------
noname:1:ReferenceError: global is not defined

Boris Zbarsky

unread,
Apr 1, 2019, 12:03:53 PM4/1/19
to
On 4/1/19 11:41 AM, muhammad sami wrote:
> noname:1:ReferenceError: global is not defined

Right, because you never defined it. You could do:

run(cx, e.dialog, "x");

or

run(cx, e.dialog, "this.x");

depending on the semantics you want. Or if you have a new enough
SpiderMonkey (corresponding to Gecko 65 or later):

run(cx, e.dialog, "globalThis.x");

-Boris

Message has been deleted

muhammad sami

unread,
Apr 1, 2019, 12:24:58 PM4/1/19
to
Hi Boris
Thanks for quick response. I'm using spidermonkey 45. can I rename the global object as in v8. I have tried
run(cx, e.dialog, "globalThis.x");
but still same output.
noname:1:ReferenceError: globalThis is not defined

please consider that I'm new to spidermonkey so parden me if I'm missing something obvious.

My main goal is to achieve scoping in vxml interpreter which allow users to run scripts as follow

<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/vxml
http://www.w3.org/TR/voicexml20/vxml.xsd">
<form>
<script>
var now = new Date(); <!-- this has a dialog scope-->
</script>
<var name="seconds" expr="now.getSeconds()"/> <!--this has a dialog scope->
<block>
<var name="now" expr="new Date()"/><!--this has an anonymous scope -->
<script>
var current = now.getSeconds(); <!-- "now" in the anonymous scope -->
var approx = dialog.now.getSeconds();<!-- "now" in the dialog scope -->
</script>
</block>
</form>
</vxml>

for more info please read this
https://stackoverflow.com/questions/55442153/how-to-specify-script-execution-scope-in-spidermonkey

Boris Zbarsky

unread,
Apr 1, 2019, 12:36:32 PM4/1/19
to
On 4/1/19 12:21 PM, muhammad sami wrote:
> Thanks for quick response. I'm using spidermonkey 45. can I rename the global object as in v8.

You can do:

run(cx, e.dialog, "var global = this;");

if you want to just stick a reference to the global in the variable
named "global". If that's evaluated in global scope it will end up with
the global stored in the variable.

> I have tried
> run(cx, e.dialog, "globalThis.x");

Right, that won't work in SpiderMonkey 45. Like I said in my previous
mail, it needs SpiderMonkey 55 or later.

-Boris
Message has been deleted

muhammad sami

unread,
Apr 1, 2019, 12:59:59 PM4/1/19
to
I have tried your idea it's working but it's doesn't fully serve my main goal which is scoping

that's what I did
I ran this script over global 'var x = 5 ; var global = this; global.x' works perfectly, then I created another child object which has global as a prototype


I ran this script over child object 'var x = 10 ; var child = this; child.x'

but x=child.x=global.x which totally make scence as child=global=this

I want the global.x still the same without change any idea how can I do it.

Boris Zbarsky

unread,
Apr 1, 2019, 2:16:56 PM4/1/19
to
On 4/1/19 12:58 PM, muhammad sami wrote:
> I ran this script over global 'var x = 5 ; var global = this; global.x' works perfectly, the I created another global object which has global as a prototype
>
> I ran this script over child object 'var x = 10 ; var child = this; child.x'

OK. So now you have two objects, right? You have "child", which has a
property named "x", which has the value 10. And its prototype is
"global" (which happens to be a global too, but that's not really
important here, afaict), which also has a property named "x", which has
the value 5.

> but x=child.x=global.x which totally make scence as child=global=this

That's a bit odd. I would expect x == child.x == 10 and global.x == 5
in your situation, if I understood it correctly. What does the actual
code you're using look like?

-Boris

muhammad sami

unread,
Apr 1, 2019, 4:19:14 PM4/1/19
to
document is the global object
dialog is the child object
// following code might be needed in some case
// #define __STDC_LIMIT_MACROS
// #include <stdint.h>
#include <mozjs-45/js/TypeDecls.h>
#include <mozjs-45/js/RootingAPI.h>
#include <mozjs-45/js/Class.h>

#include "jsapi.h"
#include "js/Initialization.h"
#include "js/Conversions.h"

using namespace JS;

class JavaScriptEngine {
public:
static JSClass document_class;
static JSClass dialog_class;

JSRuntime *rt = NULL;
JSContext *cx = NULL;
RootedObject* document;
RootedObject* dialog;
RootedObject* anonymous;

JavaScriptEngine() {

JS_Init();

// Create a JS runtime.
rt = JS_NewRuntime(8L * 1024L * 1024L);

// Create a context.
cx = JS_NewContext(rt, 8192);

// Enter a request before running anything in the context.
JSAutoRequest ar(cx);

// Create the global object and a new compartment.
document = new RootedObject(cx, JS_NewGlobalObject(cx, &document_class, nullptr,
JS::DontFireOnNewGlobalHook));

JSAutoCompartment ac(cx, *document);

JS_InitStandardClasses(cx, *document);

JS_SetErrorReporter(rt, reportError);

}

~JavaScriptEngine() {

// Shut everything down.
JS_DestroyContext(cx);
JS_DestroyRuntime(rt);
JS_ShutDown();

delete document;
delete dialog;
delete anonymous;
}

static void reportError(JSContext *cx, const char *message, JSErrorReport * report) {
fprintf(stderr, "%s:%u:%s\n",
report->filename ? report->filename : "[no filename]",
(unsigned int) report->lineno,
message);
}

bool run(JSContext *cx, RootedObject *globaloObj, const char *script, const char *filename = "noname", int lineno = 1) {
JSAutoRequest ar(cx);
JSAutoCompartment ac(cx, *globaloObj);

JS::RootedValue rval(cx);

JS::CompileOptions opts(cx);
opts.setFileAndLine(filename, lineno);

bool ok = JS::Evaluate(cx, opts, script, strlen(script), &rval);

if (!ok)
return 1;

JSString *str = rval.toString();
if (rval.isObject()) {

char result[500];
strcpy(result, script);
bool ok = JS::Evaluate(cx, opts, strcat(result, " + ' '"), strlen(strcat(result, " + ' '")), &rval);

if (!ok)
return 1;
str = rval.toString();

if (str != NULL)
printf("output: %s\n", JS_EncodeString(cx, str));

} else if (rval.isInt32()) {

size_t i = rval.toInt32();

printf("output: is number %d\n", i);

} else if (rval.isNull()) {

printf("rval.isNull\n");

} else if (rval.isUndefined()) {

printf("rval.undefined()\n");

} else if (str != NULL) {
printf("output: %s\n", JS_EncodeString(cx, str));

} else {
printf("output: no match \n");

}

return true;

}

bool changeScope() {

JSAutoRequest ar(cx);
JSAutoCompartment ac(cx, *document);

JS::HandleObject parent = JS::HandleObject::fromMarkedLocation(&document->get());
JS::MutableHandleObject protop = JS::MutableHandleObject::fromMarkedLocation(&document->get());

if (JS_GetPrototype(cx, parent, protop)) {

JS::HandleObject parentprotop = JS::HandleObject::fromMarkedLocation(&protop.get());
dialog = new RootedObject(cx, JS_NewObjectWithGivenProto(cx, &dialog_class, parentprotop));
}

}

};

JSClass JavaScriptEngine::document_class = {
"document",
JSCLASS_GLOBAL_FLAGS,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, nullptr, nullptr, nullptr,
JS_GlobalObjectTraceHook
};

JSClass JavaScriptEngine::dialog_class = {
"dialog",
JSCLASS_GLOBAL_FLAGS,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, nullptr, nullptr, nullptr,
JS_GlobalObjectTraceHook
};

int main(int argc, const char *argv[]) {

JavaScriptEngine e;
e.run(e.cx, e.document, "var document = this; var x = 5;");
e.run(e.cx, e.document, "document.x");
e.changeScope();
e.run(e.cx, e.dialog, "x");
e.run(e.cx, e.dialog, "var dialog = this;");
e.run(e.cx, e.dialog, "x=10");
e.run(e.cx, e.dialog, "dialog.x");
e.run(e.cx, e.dialog, "document.x");

}


muhammad sami

unread,
Apr 1, 2019, 4:20:46 PM4/1/19
to
ouput:
rval.undefined()
output: is number 5
output: is number 5
rval.undefined()
output: is number 10
output: is number 10
output: is number 10


Boris Zbarsky

unread,
Apr 1, 2019, 5:06:21 PM4/1/19
to
Where to start...


On 4/1/19 4:19 PM, muhammad sami wrote:
> RootedObject* document;
> RootedObject* dialog;
> RootedObject* anonymous;

You do know that RootedObject should only be used on the stack, right?
Heap-allocating them is pretty much guaranteed to not work well in the
end. But that's not the immediate problem here...

> JSString *str = rval.toString();
> if (rval.isObject()) {

That toString() should really not happen until you know it's a string...
I strongly urge you to run this in debug mode, then fix all the
resulting assertion failures.

> bool changeScope() {
> JS::HandleObject parent = JS::HandleObject::fromMarkedLocation(&document->get());
> JS::MutableHandleObject protop = JS::MutableHandleObject::fromMarkedLocation(&document->get());

OK. So both "parent" and "protop" are pointing to the same memory.

> if (JS_GetPrototype(cx, parent, protop)) {

And therefore this overwrites "document" with its prototype. After this
point, "document" stores the thing that used to be its prototype
(Object.prototype in the original "document" global, I would guess?

You should pretty much never create HandleObject or MutableHandleObject
explicitly. What this cod should have looked like, I suspect:

RootedObject proto(cx);
if (!JS_GetPrototype(cx, *document, &proto)) {
// handle failure here
}
dialog = new RootedObject(cx, JS_NewObjectWithGivenProto(cx,
&dialog_class, proto));

But none of that matters for the real issue at hand, because...

> dialog = new RootedObject(cx, JS_NewObjectWithGivenProto(cx, &dialog_class, parentprotop));

OK, so this is creating a new object that is _not_ a global.

Then when you call run() and pass it "dialog" as globaloObj, and enter
its compartment, you are actually entering the compartment of the global
of "dialog", which is the compartment you were in when you called
JS_NewObjectWithGivenProto, which is the compartment of "document". So
all the run() calls evaluate things at global scope, with the global
being "document".

It sounds like you want to run things with a non-global "dialog" on the
scope chain. To do that, you need to use the version of JS::Evaluate
that takes an AutoObjectVector scope chain. See
https://searchfox.org/mozilla-central/rev/09a322c117d64de4c652dd007daf515a13be1254/js/src/jsapi.h#3210-3216
(though the line numbers may not match up in SpiderMonkey 45; I would
check on that).

Hope that helps,
Boris

muhammad sami

unread,
Apr 2, 2019, 4:47:02 AM4/2/19
to

> Right, that won't work in SpiderMonkey 45. Like I said in my previous
> mail, it needs SpiderMonkey 55 or later.
>
> -Boris

Where can I get these versions? and if you please recommend a version for me to use.

these two links is from spidermonkey site https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Getting_SpiderMonkey_source_code

http://ftp.mozilla.org/pub/spidermonkey/releases/
http://ftp.mozilla.org/pub/spidermonkey/prereleases/

I got the last released version which is 45



muhammad sami

unread,
Apr 2, 2019, 4:51:15 AM4/2/19
to
Thanks for your valuable notes,

> It sounds like you want to run things with a non-global "dialog" on the
> scope chain. To do that, you need to use the version of JS::Evaluate
> that takes an AutoObjectVector scope chain. See
> https://searchfox.org/mozilla-central/rev/09a322c117d64de4c652dd007daf515a13be1254/js/src/jsapi.h#3210-3216
> (though the line numbers may not match up in SpiderMonkey 45; I would
> check on that).
>
> Hope that helps,
> Boris

I will check that thanks.

tcam...@mozilla.com

unread,
Apr 2, 2019, 9:03:53 AM4/2/19
to
On Tuesday, April 2, 2019 at 4:47:02 AM UTC-4, muhammad sami wrote:
> Where can I get these versions? and if you please recommend a version for me to use.
>
> these two links is from spidermonkey site https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Getting_SpiderMonkey_source_code
>
> http://ftp.mozilla.org/pub/spidermonkey/releases/
> http://ftp.mozilla.org/pub/spidermonkey/prereleases/
>
> I got the last released version which is 45

It is recommended that embedders follow the latest ESR release of firefox/spidermonkey which is current ESR60. The use cases of SpiderMonkey by embedders are typically different from Firefox. There is a github project that is collecting more up-to-date embedding information at https://github.com/spidermonkey-embedders/spidermonkey-embedding-examples that may help to look at.

In https://github.com/spidermonkey-embedders/spidermonkey-embedding-examples/blob/esr60/docs/Building%20SpiderMonkey.md there are some notes around getting sources and building. Currently the most reliable way to get an up-to-date ESR version is to download the full Firefox source tarball which contains all the SpiderMonkey code as well.

--Ted

Kent Williams

unread,
Apr 2, 2019, 12:11:38 PM4/2/19
to dev-tech-...@lists.mozilla.org
I am an embedder, and I use ESR60. I checked out the github repo for
SpiderMonkey -- so I don't have to deal with using Mercurial, which I've
so far avoided -- and it has an ESR60 tag, which I check out.

Not looking forward to porting to the next ESR release version, because
for some reason, it requires Rust.  Not a big deal installing Rust, but
it's another way that the Mozilla crew are in their own world.

Though in fairness the Google V8 build process and source control is
wackadoodle bespoke tools all the way down.
> _______________________________________________
> dev-tech-js-engine mailing list
> dev-tech-...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-tech-js-engine

Steve Fink

unread,
Apr 2, 2019, 12:49:50 PM4/2/19
to dev-tech-...@lists.mozilla.org
Sorry, we have no really good answer to that question currently. You can get later versions from the http://ftp.mozilla.org/pub/spidermonkey/prereleases/ directory. The only thing really holding me up from declaring those to be releases is that using them with default options, or with commonly-desired configuration parameters, will fail to work during startup. Mostly it's just a matter of configuring with --disable-jemalloc. All it would take to declare these packages release-quality would be identifying basic working configurations on Windows, Linux, and OSX, including static and shared variants of debug and non-debug. And making sure they work with a basic embedding. And maybe adjusting the configure script to at least not default to a broken setup.

Release notes, even if autogenerated, would be nice but need not hold up releases.

I perpetually intend to get around to doing that stuff, but can never justify prioritizing it above my other overdue projects. Volunteers welcome.

Boris Zbarsky

unread,
Apr 2, 2019, 12:56:25 PM4/2/19
to
On 4/2/19 12:11 PM, Kent Williams wrote:
> Not looking forward to porting to the next ESR release version, because
> for some reason, it requires Rust.

The reason is simple: parts of SpiderMonkey are implemented in Rust at
this point. Specifically, the BinAST parser seems to be, and the
CraneLift WASM compiler.

Now mayne you should be able to configure those off, and if you do that,
maybe Rust should not be required at this stage... But when CraneLift
becomes the default WASM compiler that won't be viable, of course.

-Boris
0 new messages