plasma.include() and member visibility

Aaron J. Seigo aseigo at kde.org
Fri Jan 15 23:07:54 CET 2010


On January 14, 2010, Amos Kariuki wrote:
> I’m trying to create a javascript plasmoid with multiple modules.  My
> main.js file includes another script file; my problem is that I’m unable to
> reference the variables and functions declared in the included file.
> Example:
> 
> [lib.js]
> var name = “Amos”;
> 
> 
> [main.js]
> plasmoid.include(“lib.js”);
> print(name);
> 
> When I run the plasmoid, I get a message stating that x is undefined.  I’m
> I referencing the variables incorrectly or is there some other way to
> achieve what I want?

it is a scoping problem. declaring "var name" means that the 'name' variable 
is local to that context (the file in this case). if you instead do:

	name = 'Amos'

or 

	plasmoid.name = 'Amos'

it works just fine. (i just tested this, in fact :)

note that reverse isn't true, however: if you declared "var name" in your 
main.js then it will be visible in lib.js. that's because main.js is the 
context for lib.js (but not vice versa)

the same, btw, is true of functions. (just tested that too :)

this keeps multiple files from conflicting with one another in odd ways just 
because they have similarly named local variables and functions.

however, this can be easily changed with this patch:

Index: scriptenv.cpp
===================================================================
--- scriptenv.cpp       (revision 1073899)
+++ scriptenv.cpp       (working copy)
@@ -74,7 +74,13 @@
     QString script = file.readAll();
     //kDebug() << "Script says" << script;

-    evaluate(script);
+    QScriptContext *ctx = currentContext();
+    if (ctx->parentContext()) {
+        ctx->setActivationObject(ctx->parentContext()->activationObject());
+        ctx->setThisObject(ctx->parentContext()->thisObject());
+    }
+
+    evaluate(script, path);
     if (hasUncaughtException()) {
         emit reportError(this, true);
         return false;

this works with your example code.

i just took a look at the apidox for QScriptEngine::currentContext() and, 
interestingly, read this:

"A typical usage of these functions is when you want script code to be 
evaluated in the context of the parent context, e.g. to implement an include() 
function:"

so apparently this is what people writing javascript expect. to me it sounds 
like a problem waiting to happen:

[second.js]
var test = 'rocking'

[third.js]
var test = 'not rocking'

[main.js]
include('second.js')
include('third.js')
print(test)

the output is: not rocking

ugh. as there is a way to export such variables (don't use "var" or have a 
global object to register them with) it seems unreasonably messy. but, yes, 
since that's what is expected i'll commit this change and backport it for 
4.4.0.

-- 
Aaron J. Seigo
humru othro a kohnu se
GPG Fingerprint: 8B8B 2209 0C6F 7C47 B1EA  EE75 D6B7 2EB1 A7F1 DB43

KDE core developer sponsored by Qt Development Frameworks


More information about the Plasma-devel mailing list