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: