Hopbot log for 2008-03-20 - Helma IRC channel: #helma on irc.freenode.net

2008-03-20:

[2:35] <v_thunder> hello #helma!
[2:35] <v_thunder> aw, maybe nobody is home
[2:36] <v_thunder> I have a question: I have some js 1.7 code (uses let) that I'd like to run under helma
[2:37] <v_thunder> I found I have to set the rhino.languageVersion property to "170", but will that work with the bundled rhino jar file?
[2:37] <v_thunder> (in the 1.6.1 download)
[2:38] <bard> v_thunder: iirc js 1.7 is in svn
[2:38] <bard> http://dev.helma.org/weblog/2008/01/helma_update/ - not sure about 1.6.1
[2:38] <v_thunder> does that mean I should check out from svn and build from source?
[2:38] <v_thunder> ok
[2:38] <bard> there are snapshots lying around
[2:38] <v_thunder> I was looking at http://dev.helma.org/wiki/Helma+1.6.1+Changelog/
[2:38] <v_thunder> which mentions 1.7
[2:39] <bard> cool, then must be in 1.6.1 already :-)
[2:39] <v_thunder> nice. I'll give it a try and see
[2:40] <v_thunder> helma seems really nice so far, btw
[2:43] <bslivka> yes yes
[3:34] <v_thunder> so, I have a bunch of js code I wrote for a firefox extension that I'm hoping to reuse in helma
[3:34] <v_thunder> is app.addRepository() in my app's Root/init.js a good way to load it?
[3:35] <v_thunder> my code is in multiple inter-dependent files (I currently use Components.utils.import() to load the files in fx)
[3:36] <bard> v_thunder: can't answer your question (I'd try placing under Global/ though), but I'm curious what extension you're writing (ext writer here too :-))
[3:37] <v_thunder> I'm the project lead for the Weave extension: http://labs.mozilla.com/2007/12/introducing-weave/
[3:37] <v_thunder> I'm hoping to take the sync code and use it server-side
[3:38] <bard> ah I see, cool
[3:38] <v_thunder> what extensions have you made?
[3:39] <bard> mozrepl and sameplace
[3:39] <v_thunder> ah cool
[3:39] <v_thunder> so you wrote xmpp4moz?
[3:40] <bard> yep
[3:40] <v_thunder> nice
[3:40] <v_thunder> I've been itching to give that a try, but I've been too busy
[3:40] <bard> I too am hoping to use js on the server side
[3:41] <bard> for more ordinary web apps though
[3:41] <v_thunder> yeah I'm not sure loading big chunks of firefox js components is the common case for helma users ;)
[3:42] <bard> hehe
[3:42] <v_thunder> ideally I'd be able to load the js I have as-is, but that seems impossible
[3:42] <v_thunder> since I use xpcom, etc
[3:42] <v_thunder> hrm.
[3:44] <bard> would faking the needed Components.classes[] etc be too ugly?
[3:45] <v_thunder> no, maybe that's the way to go
[3:53] <bslivka> you might try going a bit higher level
[3:53] <v_thunder> yeah?
[3:53] <bslivka> that is, wrap your xpcom components in generic functions
[3:54] <v_thunder> then implement the portable layer for helma
[3:54] <v_thunder> yeah
[3:54] <v_thunder> that sounds pretty sane
[3:54] <bslivka> yep that's it
[3:54] <v_thunder> I'm not clear about multiple files and how they fit into helma, though
[3:55] <v_thunder> if I do app.addRepository("modules/weave/foo.js"); app.addRepository("modules/weave/bar.js");
[3:55] <v_thunder> and bar.js uses functionality defined in foo.js
[3:55] <v_thunder> does that work?
[3:56] <bslivka> yeah
[3:56] <bslivka> Really what you want to do, if you can
[3:56] <bslivka> is not add the repositories dynamically
[3:56] <v_thunder> okay, that's great
[3:56] <v_thunder> oh
[3:56] <bslivka> but include them in your app.properties file
[3:56] <v_thunder> and instead use app.properties?
[3:56] <v_thunder> ok
[3:57] <bslivka> projectname.repository.0=/apps/projectname/code
[3:57] <v_thunder> will all objects defined in each file be visible globally?
[3:57] <bslivka> projectname.repository.1=/modules/weave/foo.js
[3:57] <v_thunder> (I currently use Cu.import() where you define an EXPORTED_SYMBOLS variable)
[3:58] <bslivka> Well, helma's concept of a code repository is kind of funny
[3:58] <bslivka> I'm not sure what happens when you try and call a .js file directly as a repository
[3:58] <bslivka> i've only done folders, and zip files
[3:59] <v_thunder> interesting
[3:59] <v_thunder> what's the behavior with a folder
[3:59] <bslivka> How it works is that there's folders in a repository that helma turns into prototypes
[3:59] <v_thunder> or a zip file?
[3:59] <bslivka> any .js files it finds in the folder, get interpreted as though that folder has its own scope
[3:59] <v_thunder> oh
[4:00] <bslivka> and that scope is used as a prototype that you can use to generate objects
[4:00] <v_thunder> okay, interesting
[4:00] <bslivka> there's a global object, also
[4:00] <bslivka> if you have a folder named Global, any js files it has in there is interpreted into the global scope
[4:00] <v_thunder> that bard mentioned above
[4:01] <v_thunder> ok
[4:01] <v_thunder> so the quickest path for me is probably to add there
[4:01] <bslivka> yep
[4:01] <v_thunder> though not the most correct one, really
[4:01] <v_thunder> ok
[4:01] <bslivka> it's fine
[4:01] <bslivka> Really, the other things are for making hopobjects, which are the ones that you can persist
[4:02] <bslivka> and also they form an object graph which gets mapped to the url space
[4:03] <v_thunder> ah, I see
[4:04] <bslivka> so once you start wanting to add things to the url space, you'll need a root folder, which represents the prototype that gets mapped to the url /
[4:04] <v_thunder> right, but I think I'll do that in my app's root
[4:04] <v_thunder> rather than this add-on repository
[4:04] <bslivka> sure
[4:04] <v_thunder> which would just have cod3e
[4:05] <v_thunder> code, even
[4:05] <bslivka> indeed
[4:05] <v_thunder> ok, ok. thanks a lot for the pointers!
[4:05] <v_thunder> I will bang on this for a while
[4:07] <bslivka> Hrmn, having another look, it looks like if you add a .js file directly as a repository, it gets interpreted in the global scope as well
[4:08] <bslivka> So I guess I've been a little misleading.
[4:08] <v_thunder> no, I understood that
[4:09] <v_thunder> well, you didn't say it
[4:09] <v_thunder> but a folder with Global sounds more convenient anyway :)
[4:09] <v_thunder> since I have a bunch of js files
[4:09] <v_thunder> oh--
[4:09] <v_thunder> but they depend on each other
[4:09] <v_thunder> does this mean I can't control the loading order?
[4:10] <bslivka> Well let's see.. that raises a good question, if it encounters multiple js files, what order does it load them..
[4:11] <bslivka> Typically it's just functions in a .js file
[4:11] <v_thunder> right
[4:11] <bslivka> so it doesn't matter
[4:11] <bslivka> javascript is lazy evaluating
[4:11] <v_thunder> it might actually not matter for most of my files
[4:11] <v_thunder> except for one or two
[4:11] <v_thunder> where I actually make an object
[4:12] <bslivka> But the way it's usually handled in a helma module is it will be defining some object as a namespace
[4:12] <bslivka> the first thing it does is check if that object exists
[4:12] <bslivka> and if it doesn't, create it
[4:12] <bslivka> then that methodology eliminates the need for a specific load order
[4:13] <v_thunder> hmm
[4:13] <bslivka> But that still doesn't negate the question of what order helma loads things
[4:13] <bard> v_thunder: you could create the objects in the onStart callback
[4:14] <v_thunder> it would be really nice to have some sort of common js 'library' format
[4:14] <v_thunder> that I could plug into firefox or other apps
[4:14] <v_thunder> bard: yes, I think
[4:14] <bslivka> ecmascript4
[4:14] <v_thunder> aye
[4:14] <v_thunder> I can't wait :)
[4:15] <v_thunder> bard: yeah, that would work in helma since everything will be exported
[4:22] <bslivka> okay here's the answer, the javascript files are loaded in alphabetical order
[4:22] <bslivka> funny
[4:22] <v_thunder> hehe
[4:22] <v_thunder> nice
[4:23] <bslivka> so you can control the load order by the file names
[4:23] <bslivka> but that's a bit silly
[4:23] <v_thunder> yeah, I'm not doing that
[4:23] <v_thunder> I wonder if I can do something like...
[4:23] <v_thunder> hm
[4:24] <bslivka> best way really is to try to write the javascript files so it doesn't matter which order they're loaded
[4:24] <v_thunder> I wonder if I can make an object that will transparently new() the real object, lazily
[4:24] <v_thunder> and replace itself with the real thing
[4:25] <v_thunder> so I have function Foo() {}; Foo.prototype = { ... };
[4:25] <v_thunder> I wonder if I can make a Bar object that is the thing that gets exposed
[4:25] <v_thunder> but instantiates Foo lazily
[4:25] <v_thunder> I can easily do it with a getter
[4:26] <v_thunder> but that moves it one down the chain
[4:26] <bslivka> functions in general are evaluated lazily. for whatever object you're defining, you can go foo = functionname();
[4:26] <bslivka> then define functionname() to return your foo object
[4:27] <v_thunder> e.g., Bar = { get Foo() { if (Bar._foo) { return Bar._foo } else { Bar._foo = new Foo() } }
[4:27] <bslivka> you can define functionname() anywhere and in any order
[4:27] <bslivka> at the end of it all, as soon as something tries to access foo.prop
[4:27] <bslivka> the function is lazily evaluated to get the value of prop
[4:28] <bslivka> very neat trick, just learned it today
[4:28] <bslivka> example minimal code that demonstrates this:
[4:29] <bslivka> var foo = { bar: getHello();};
[4:30] <bslivka> function getHello() { return {x: "hello world" } };
[4:30] <bslivka> foo.bar.x //returns "hello world"
[4:30] <v_thunder> sure
[4:31] <v_thunder> that actually embeds {x: "hello world"} inside foo
[4:31] <v_thunder> but that doesn't solve my problem
[4:31] <bslivka> Not quite. It half embeds it.
[4:32] <v_thunder> ?
[4:32] <bslivka> It's weird, I'm still exploring it
[4:32] <v_thunder> I'm not sure what you mean :)
[4:33] <bslivka> if after that code you redefined getHello() to return {x: "goodbye world"}, then indeed
[4:33] <v_thunder> that is not different than let foo = bar(); function bar() { return "whee"; }
[4:33] <bslivka> foo.bar.x would return goodbye
[4:33] <v_thunder> foo == "whee"
[4:33] <v_thunder> oh
[4:33] <v_thunder> really?
[4:33] <bslivka> It doesn't evaluate the function,
[4:33] <bslivka> until you try to access the property
[4:33] <v_thunder> interesting
[4:33] <v_thunder> and odd
[4:35] <bslivka> Which means that you can define the functions in any order you like
[4:35] <bslivka> and it won't form interdependancies until the first time you access one of the object's properties
[4:35] <bslivka> by that time, all the functions will be defined
[4:36] <bslivka> since they're not evaluated until the very last second, you don't run into missing code
[4:36] <v_thunder> in my case, I have objects I new(), which have constructors that depend on other code
[4:37] <v_thunder> I'll figure it out, hm
[4:37] <bslivka> if you don't new them until after all the constructor definitions, then it's not a problem
[4:38] <v_thunder> I have singleton services
[4:38] <v_thunder> so the code that new()s is the service itself
[4:38] <v_thunder> not the calling code
[4:39] <bslivka> well, it's a tricky problem. at this point I'm lost without looking at the source code
[4:40] <bslivka> just keep in mind that javascript has rules that are different from any other language
[4:40] <v_thunder> http://hg.mozilla.org/labs/weave/?file/2d0b1a1b84e8/modules/
[4:41] <v_thunder> looking for a good example in there...
[4:41] <v_thunder> hold on ;)
[4:41] <bslivka> I'll have a look see..
[4:41] <v_thunder> so, see Log4Moz
[4:42] <v_thunder> Log4Moz gets exported
[4:42] <v_thunder> and it contains Log4Moz.Service, a singleton of the service
[4:42] <v_thunder> (last line)
[4:43] <v_thunder> in this case, it's fine; this file doesn't depend on anything else
[4:44] <bslivka> but others ddepend on the Log4Moz.Service?
[4:44] <v_thunder> right; that code gets imported in other files
[4:45] <v_thunder> so what I think I'd like to do is
[4:45] <v_thunder> Log4Moz = { get Service() {} };
[4:45] <v_thunder> where the Service getter makes a new service the first time it is run
[4:45] <v_thunder> and caches it
[4:46] <v_thunder> that way the new doesn't actually happen until the first time the service is used
[4:46] <v_thunder> rather than on first import()
[4:47] <bslivka> you don't have to go that far, you don't need get
[4:47] <bslivka> Log4Moz.Service= function () {return new Log4MozService() }()
[4:47] <bslivka> I think...
[4:48] <v_thunder> no, that won't cache it
[4:48] <v_thunder> I need it to be a singleton :)
[4:48] <v_thunder> plus, it would add () to every call
[4:48] <v_thunder> i.e., I'd have to do Log4Moz.Service().foo()
[4:48] <v_thunder> instead of Log4Moz.Service.foo()
[4:49] <bslivka> look carefully
[4:49] <bslivka> in my code, I've already included ()
[4:49] <v_thunder> oh!
[4:49] <v_thunder> will that replace Service with the new Log4MozService the first time it's run?
[4:49] <bslivka> so nothing changes, except that since it's wrapped in a function, it's got lazy evaluation
[4:50] <bslivka> yeah, as soon as you try to access Service the first time
[4:50] <v_thunder> really.
[4:50] <bslivka> then it'll run the function to create the new Log4MozService
[4:50] <v_thunder> that would be exactly what I want
[4:50] <bslivka> I think!.
[4:50] <bslivka> I'll check it out.
[4:51] <v_thunder> I wonder if that would work for a toplevel object as well, then
[4:51] <v_thunder> Foo = function hotness() { return new Bar() }();
[4:51] <v_thunder> that looks weird
[4:51] <v_thunder> I've never seen that
[4:52] <bslivka> have you read any of doug crockford's stuff?
[4:52] <v_thunder> some
[4:52] <v_thunder> not a lot
[4:52] <bslivka> he gets pretty heavy in some of his videos
[4:55] <bslivka> I've got some sample code...
[4:55] <bslivka> I'll get it on a pastebin
[4:56] <v_thunder> about what we talked about earlier
[4:56] <v_thunder> http://pastebin.org/24539
[4:56] <v_thunder> that prints ({bar:{x:"goodbye world"}})
[4:56] <bard> hmm, trying to catch up. is this: Foo = function hotness() { return new Bar() }(); meant to run hotness() only the first time Foo is referenced?
[4:56] <v_thunder> twice
[4:56] <v_thunder> yes.
[4:56] <v_thunder> that's what I need
[4:56] <v_thunder> otherwise I'd get a new Foo() each time
[4:56] <v_thunder> er
[4:57] <v_thunder> a new Bar, sorry
[4:57] <bard> k
[4:57] <bslivka> you don't need "hotness"
[4:57] <v_thunder> no
[4:57] <v_thunder> it's just nice for debugging
[4:57] <bslivka> it's an anonymous function
[4:57] <v_thunder> since it'll show up in stack traces
[4:57] <v_thunder> I add names to all of my functions
[4:57] <bard> k but it's nice to have names if we want to talk about it ;-)
[4:58] <bslivka> you can define hotness seperately I think. I don't think that calling instantly trick works with named functions
[4:58] <v_thunder> hm
[4:58] <bard> I'm trying it interactively in firefox but it seems it's evaluated instantly
[4:58] <bard> repl> Foo = function hotness() {repl.print('hello'); return new Bar()}()
[4:58] <bard> hello
[4:58] <bard> [object Object] ? {test: 3}
[4:59] <bard> what about this?
[4:59] <bard> repl> this.__defineGetter__('Foo', function() { this.Foo = 3; return 3; })
[4:59] <bard> repl> Foo
[4:59] <bard> 3
[4:59] <bslivka> I just got an error on function hotness () {return true}()
[5:00] <v_thunder> __defineGetter__ is the same as my get foo() {...}
[5:00] <v_thunder> __defineGetter__ is how you define getters programmatically
[5:00] <bslivka> But I wrap it in paranthesis, and it works.
[5:02] <bslivka> http://helma.pastebin.com/m19e8ebcf
[5:02] <bslivka> just a sec and I'll pastebin a named function version
[5:03] <bslivka> Hrmn not working like I thought!
[5:03] <bslivka> Sorry if I'm leading you down a goose chase
[5:04] <v_thunder> it does work
[5:05] <v_thunder> http://helma.pastebin.com/m87a3ab3
[5:05] <v_thunder> (I'm running it with xpcshell, so I use dump() to print to stdout)
[5:06] <v_thunder> oh wait, need to test something else
[5:06] <bslivka> http://helma.pastebin.com/m37822a05
[5:08] <bslivka> the tricky thing is , it works fine if it's evaluated all at once
[5:08] <bslivka> what happens when this code is spanning across files
[5:10] <bslivka> It may parse a whole file, decide that hotness() isn't defined, and then throw an error even if it exists in another file
[5:10] <v_thunder> ok, I don't think it works
[5:10] <v_thunder> let me pastebin again
[5:11] <bslivka> One last idea, take it or leave it, but was used in this funky little ajax library I worked on a while ago...
[5:12] <v_thunder> http://helma.pastebin.com/m2d4759ae
[5:12] <bslivka> Hrmn late in the day, I forget how it worked. Gurhg brain crash
[5:13] <v_thunder> see, 'making a new Foo!' gets printed too early; and Bar already has the 'whee' property even before whee() is called
[5:13] <v_thunder> so I think I'll try my getter approach
[5:15] <bslivka> indeed
[5:16] <bslivka> I think the problem is that the lazy evaluator only works up to the end of a particular file
[5:16] <v_thunder> no, this is all in the same file
[5:19] <v_thunder> http://helma.pastebin.com/d21706a3a
[5:19] <v_thunder> that works
[5:19] <v_thunder> I don't think I can make it work as Bar though
[5:19] <v_thunder> only Bar.property...
[5:19] <v_thunder> (Bar itself can't be a getter, right)
[5:19] <bslivka> Don't forget that global is also an object
[5:20] <v_thunder> unless I can somehow attach a getter to the global object
[5:20] <v_thunder> right
[5:20] <v_thunder> gonna try that now
[5:22] <bslivka> odd..
[5:24] <bard> see you later folks, I'll try to catch some sleep
[5:24] <v_thunder> nite!
[5:24] <bard> eheh, it's morning here, that's part of the problem :-)
[5:24] <bard> bye
[5:28] <bslivka> Now I know that javascript supposedly has some kind of lazy evaluation, but whenever I try to understand it, it becomes an excercise like this- it looks like lazy evaluation in some cases but breaks in others.
[5:29] <v_thunder> I'll ask brendan tomorrow :)
[5:30] <v_thunder> if anyone knows it's him
[5:30] <bslivka> haha that's great.
[5:32] <bslivka> I feel like an ass for asking, but do you mind if you throw in a question of my own?
[5:32] <bslivka> I strongly suspect the answer is "no", but it's worth a try...
[5:34] <bslivka> hrmn. Basically I just need to capture property assignments on a particular object
[5:35] <bslivka> You can do this with getters and setters on specific properties that you know the names of
[5:35] <bslivka> or even use watch(),
[5:35] <bslivka> but I'd like to intercept assignments for all properties
[5:38] <bslivka> So I can catch arbitrary assignments to a particular object, and run some automatic persistance function
[5:39] <bslivka> Pretty much like helma does, but helma does it with java code
[5:40] <bslivka> seems like something for ecmascript4
[5:41] <v_thunder> sorry, wasn't looking
[5:41] <v_thunder> hmmmmm
[5:41] <v_thunder> I actually don't know
[5:41] <v_thunder> but I can find that out too
[5:41] <v_thunder> I suspect that you can't
[5:41] <bslivka> That's my feeling too
[5:42] <bslivka> and I also suspect that there's a good reason for it too, like security
[5:43] <v_thunder> hm
[5:43] <v_thunder> perhaps
[5:43] <v_thunder> I'm not sure
[5:44] <bslivka> But the fact is, the host objects in helma can do it, but I can't, so given that one of the goals of ecmascript4 is to remove those barriers..
[5:44] <v_thunder> watch will definitely not work for you
[5:44] <v_thunder> hm
[5:44] <v_thunder> I wonder if js2 will have something
[5:47] <v_thunder> wow
[5:47] <v_thunder> sweet
[5:47] <v_thunder> I made the global object one work
[5:47] <v_thunder> check it: http://helma.pastebin.com/d292f7528
[5:50] <bslivka> Neat.
[5:50] <bslivka> One pattern you might find useful is lazy function definition ( it sounds like what we've already talked about but it's different)
[5:51] <bslivka> Basically, a function can overwrite itself.
[5:51] <bslivka> So the first time you call it, it defines itself.
[5:51] <bslivka> then calls its own new definition and returns the result
[5:52] <v_thunder> hm
[5:52] <bslivka> It's kind of wanky, but fun anyway
[5:53] <bslivka> http://peter.michaux.ca/article/3556
[6:04] <v_thunder> cool
[6:05] <bslivka> It's kind of useful if you want to do something the first time you run a function, but none of the consecutive times.
[6:05] <v_thunder> I wonder if I can do something like solution #4, but with a getter
[6:06] <bslivka> or if you want to keep some variables that persist across function calls, but are hidden from the rest of the environment
[6:07] <bslivka> yeah I think I saw an example that did that
[6:07] <bslivka> just a few seconds ago, I whip through so many differnt pages it's hard to keep track.
[6:08] <bslivka> But basically you define a getter, and the getter redefines itself
[6:08] <v_thunder> hehe nice
[6:08] <v_thunder> yes
[6:08] <v_thunder> I just tested it
[6:09] <v_thunder> http://helma.pastebin.com/da30088e
[6:09] <v_thunder> works like a charm
[6:09] <v_thunder> but you have to remember to delete the property in the getter
[6:09] <v_thunder> otherwise it creates a new Foo recursively (infinitely) - not happy times
[6:10] <v_thunder> this version is better than the previous version (which caches the Foo object in this._foo)
[6:11] <v_thunder> okay, I have to go home now :)
[6:11] <bslivka> Ah yes, I thought as much
[6:11] <v_thunder> g'nite! thanks for the help
[6:11] <bslivka> that's why I pointed you at the article in the first place
[6:11] <bslivka> I remember now.
[6:11] <bslivka> Good night.
[6:12] <v_thunder> :)

 

 

In the channel now:

Logs by date: