Stratified JS and PhoneGap 3.1 for Windows Phone 8

170 views
Skip to first unread message

anev...@gmail.com

unread,
Nov 7, 2013, 5:03:58 PM11/7/13
to strati...@googlegroups.com
Hello,
 
I am getting moved into a new development environment, upgrading my PhoneGap app from running an older version of PhoneGap to the very latest, which is 3.1.  There are lots of moving parts that have to work together, but I think I have most of them working right.  I am getting through all the PhoneGap onDeviceReady event, so that much is good.  The problem I am having is that I am not able to call a function that is in an inline SJS script block from standard javascript.  I know that the inline SJS script block is getting wired up because if I put console.log calls in there, I get output in the Output window.  But if I try to call a function from within my standard javascript, nothing happens.  Here is a bit of code to demonstrate what I am talking about:
 
////////////////////////////////
 <script type="text/javascript">
            function onDeviceReady() {
                console.log("PhoneGap onDeviceReady");
                myTestFunc();
            }
        </script>

 <script type="text/sjs">
            function myTestFunc() {
                console.log("my Test Function");
            }
        </script>
////////////////////////////////
 
I get the "PhoneGap onDeviceReady" in the console, but I never get "my Test Function".
 
Is there something simple that I am missing?  I am using the very latest stable stratified.js from Git which is 0.14.
 
Many thanks in advance!
 
AN

anev...@gmail.com

unread,
Nov 7, 2013, 6:24:48 PM11/7/13
to strati...@googlegroups.com, anev...@gmail.com
Oh, I tried doing a try/catch around the call to myTestFunc, and the exception that I get is:
 

ReferenceError: 'myTestFunc' is undefined

Maybe that helps?

Tim Cuthbertson

unread,
Nov 7, 2013, 7:34:45 PM11/7/13
to strati...@googlegroups.com, anev...@gmail.com

Hi,

<script type="text/sjs"> tags run in their own module scope, which is why you can't see `myTestFunc` as a global variable - it's actually a module-local variable. If you want to, you can explicitly make it a global variable by assigning it to `window`:

            window.myTestFunc = function myTestFunc() {

                console.log("my Test Function");
            }

However, it's generally best to avoid calling SJS from JS if possible. In particular, note that this code won't work if onDeviceReady runs before the SJS runtime has finished executing the second script. This is almost certain to happen if you add a require() call to the top of the SJS code, since myTestFunc won't be defined until the required module has been fetched and loaded.

So I'd recommend doing something like I discussed in https://groups.google.com/d/msg/stratifiedjs/g9-BfKpvkU0/1aTtuZ5GYVwJ, where the SJS code registers the listener when it's ready, rather than trying to coordinate two different events (SJS code executed / deviceReady triggered) that could happen in either order.

But since I just realised it was you who was in that thread, I guess perhaps you have a good reason for not doing that. If you do stick to this hybrid JS + SJS solution, you will need to make sure that your code can handle the onDeviceReady function being called before myTestFunc is defined.

Cheers,
 - Tim.

anev...@gmail.com

unread,
Nov 7, 2013, 11:44:31 PM11/7/13
to strati...@googlegroups.com, anev...@gmail.com
Hi Tim,
 
You're the best, thanks for helping me out here.  It turns out that there are some new constructs that Cordova introduced in 3.0 and I wasn't doing things right in their world.  Once I got that straightened out, I was able to get through this problem by doing exactly what you recommend, which is to register for the listener in the proper order.  That part works great!
 
My next problem is that I'm now unable to use require to load my .sjs file into a scope. Here is my code:
 
            var sys = require('sjs:apollo-sys');
            require.hubs.unshift(["file:x-wmapp", {
              src:function(path) {
                var load_path = 'file:'+path.substring(7);
                return { src: sys.request(load_path),
                   loaded_from:  load_path
                };
              }
            }]);
            require.hubs.push(["x-wmapp1:", { src:require.hubs[2][1].src }]);
            require.hubs.push(["x-wmapp0:", { src:require.hubs[2][1].src }]);
            require.hubs.push(["file:", {src:require.hubs[2][1].src}]);
            require.hubs.push(["local:", {src:require.hubs[2][1].src}]);
            if (isWP()) {
                cm = require("file:x-wmapp0:/app/www/Scripts/CMStratified.sjs");
            }
            else {
                cm = require("Scripts/CMStratified.sjs");
            }
What is happening is that the line that says: var sys = require('sjs:apollo-sys');  is returning this error:
 

Error: Don't know how to load module at x-wmapp0:www/www/www/Scripts/modules/apollo-sys.sjs

So obviously the www/www/www thing seems to be the problem here.  When I do a console.log in the middle of that hubs.unshift function, the path is this:

file://x-wmapp0:/app/www/Scripts/CMStratified.sjs

But earlier while I was trying to call myTestFunc, I got this error back:
 
ReferenceError: 'myTestFunc' is undefined
    at module x-wmapp0://www/index.html_inline_sjs_1:7
 
So it looks to me like the real path should be this:
 
 
Right?
 
But maybe I need to get the first call to require sjs:apollo-sys to work properly???  I'm kind of lost here, need help.  Thanks SO MUCH!
 
One more piece of info..  First I need to get this working on Windows Phone, and then after that I'll get the exact same code working on Android, iOS and BlackBerry.  That is why those other require.hubs.push statements are in there - file: works for Android and iOS (IIRC) and local: works for BB.
 

THANK YOU!

 

 

 

 

 

 

Tim Cuthbertson

unread,
Nov 8, 2013, 12:53:32 AM11/8/13
to strati...@googlegroups.com, anev...@gmail.com

No worries, happy to help you out.


 > var sys = require('sjs:apollo-sys');

Do you mean "builtin:apollo-sys"?

Aside: apollo-sys is somewhat of an internal module, so it might be wiser to use the `request` function from "sjs:http" instead (it's the same function, but sjs:http is part of the public API so it's less likely to disappear).

As for the hubs issues, I'm afraid I'm finding it difficult to follow your hub configuration, and am not entirely sure where some of these URLs are coming from.

One thing I can suggest is that presumably you're doing that logging after removing the require("sjs:apollo-sys") call?

If so, it looks like the URL you're getting:

file://x-wmapp0:/app/www/Scripts/CMStratified.sjs

is probably a response to the call:


cm = require("file:x-wmapp0:/app/www/Scripts/CMStratified.sjs");

So if you think that shouldn't have /app in it, have you tried removing the "/app" from that line of code?


Also, you may be experiencing some problems where a given URL could match multiple hubs - e.g anything matching "file:x-wmapp" will also match the "file:" hub. Given that "file:x-wmapp" appears first on require.hubs I think this will do what you want, but you may want to temporarily comment any hubs you're not using just to remove any potential confusion there.

Cheers,
 - Tim.

anev...@gmail.com

unread,
Nov 8, 2013, 11:03:51 AM11/8/13
to strati...@googlegroups.com, anev...@gmail.com
Switching to builtin:apollo-sys seems to have solved half of my issues.  Thanks for that!  I think the sjs:apollo-sys is old and has been deprecated.
 
Now I am just arm wrestling through the internals of how Windows Phone 8 makes the isolated storage available.  If I can get one thing resolved there, then I will next want to ask you to help me with require.hubs.  Stay tuned..
 
Thanks again!

anev...@gmail.com

unread,
Nov 8, 2013, 3:31:48 PM11/8/13
to strati...@googlegroups.com, anev...@gmail.com
Okay, I figured out something that works.  For some reason when I do this:
 

var cm = require("www/Scripts/CMStratified.sjs");

What comes through is this:

x-wmapp0:www/www/www/Scripts/CMStratified.sjs

So I have to use the hubs.unshift to clean up that www/www/www, like this:

            require.hubs.unshift(["x-wmapp", {
                src:function(path) {
                    path = path.replace("www/www/www", "www");
                    return { src: sys.request(path),
                        loaded_from:  path
                    };
                }
            }]);

And that works!

Any idea where the www/www/www is coming from?

Tim Cuthbertson

unread,
Nov 8, 2013, 11:10:05 PM11/8/13
to strati...@googlegroups.com, anev...@gmail.com
> var cm = require("www/Scripts/CMStratified.sjs");

Since that module name doesn't start with a slash, it's assumed to be
a path relative to the current module URL. Can you print out
`module.id` before this line, and see what it gives you?

In order to get a URL like:
x-wmapp0:www/www/www/Scripts/CMStratified.sjs

The most obvious cause would be if your module had an ID of
`x-wmapp0:www/www/<filename>`
Which seems unlikely, but see what `module.id` is - and make sure you
don't have any other redirect hubs which might be interfering.
> --
> You received this message because you are subscribed to the Google Groups
> "StratifiedJS" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to stratifiedjs...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.

anev...@gmail.com

unread,
Nov 11, 2013, 10:54:59 AM11/11/13
to strati...@googlegroups.com, anev...@gmail.com
I'm actually going to just move along since I have something that works, as far as this issue goes.  I may revisit this later on, but for now I just need to keep tackling all the breaking changes since upgrading to the latest Cordova/PhoneGap and also the latest Stratified.js.  I am posting another question now, on a separate thread.  Thanks so much!

ane...@certify.com

unread,
Nov 3, 2016, 3:54:53 PM11/3/16
to StratifiedJS
Hi Tim,

Now I am upgrading this project from the old Cordova for Windows Phone 7/8 (that was wired up with Visual Studio 2012) to the very latest Cordova for Windows Universal (Windows 10 Mobile, Windows Store) that ships with Visual Studio 2015. I am running into the exact same problem. This time, however, I am able to debug into stratified.js because this new environment is WAY better! This has allowed me to verify that the path looks to be correct. In this new environment my call to require looks like this:

window.cm = require("scripts/test.sjs");

When I call this, I get this error: Don't know how to load module at ms-appx://io.cordova.certifymobile/www/scripts/test/sjs

I guess my question is this: what actual mechanism does stratified.js use to read this file?

It seems like it may be a permissions problem. I have sent a message to someone who knows someone on the Visual Studio team, so if I hear back from them I will certainly post the response here, for everyone's benefit.

Any thoughts?

Alan

ane...@certify.com

unread,
Nov 3, 2016, 4:07:11 PM11/3/16
to StratifiedJS
Whoops, I typed that incorrectly, should have been a dot instead of a slash. Here is how that line should have read:

When I call this, I get this error: Don't know how to load module at ms-appx://io.cordova.certifymobile/www/scripts/test.sjs


Alan


On Thursday, November 7, 2013 at 5:03:58 PM UTC-5, Alan Neveu wrote:

Alexander Fritze

unread,
Nov 3, 2016, 4:31:57 PM11/3/16
to strati...@googlegroups.com
Hi Alan,

From the error message, it looks like stratifiedjs just doesn't know
how it should load stuff from "ms-appx:".

You need to add a hub definition that instructs SJS to load everything
prefixed with 'ms-appx' via a http request. IIRC you did this
previously for things like x-wmapp1. Could go to your code and locate
the line:

require.hubs.push(["x-wmapp1:", { src:require.hubs[2][1].src }]);

and change that to

require.hubs.push(["ms-appx:", { src:require.hubs[2][1].src }]);

and see if that works?

Thanks,
Alex
> --
> You received this message because you are subscribed to the Google Groups
> "StratifiedJS" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to stratifiedjs...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

ane...@certify.com

unread,
Nov 3, 2016, 5:33:17 PM11/3/16
to StratifiedJS
Brilliant! I will look into that pronto! Thanks Alex!

ane...@certify.com

unread,
Nov 3, 2016, 8:31:54 PM11/3/16
to StratifiedJS, ane...@certify.com
Okay, I added:

require.hubs.push({"ms-appx:", { src:require.hubs[2][1].src }]);

and now I am getting:

Malformed module id 'ms-appx://io.cordova.certifymobile/www/scripts/test.sjs'

The contents of my test.sjs is very simple:

exports.returnValueTest = returnValueTest;
function returnValueTest() {
    return "wahoo";
}


So the error message changed, but now it says "malformed module id". Is that saying the path is malformed? Or is it saying the module content is malformed and the id of that malformed module is ....

?

Alan

Alexander Fritze

unread,
Nov 3, 2016, 8:38:16 PM11/3/16
to strati...@googlegroups.com
Can you try:

require.hubs.push({"ms-appx:", { src:require.hubs[3][1].src }]);

(Note index '3' instead of '2')
and failing that:

require.hubs.push({"ms-appx:/", { src:require.hubs[3][1].src }]);

ane...@certify.com

unread,
Nov 3, 2016, 9:44:00 PM11/3/16
to StratifiedJS
Bingo - changing the index to 3 did the trick. This is fantastic, thanks so much for your help!

Alan
Reply all
Reply to author
Forward
0 new messages