[00:00] erichocean: deanlandolt_: that's true, unless you're talking about linkers [00:00] deanlandolt_: node provides you plenty of room for enabling...eval away ;) [00:00] inimino: I thought it was that there are so many to choose from [00:00] deanlandolt_: inimino: that too :) [00:01] erichocean: a standard is bad not because you can't work around it, but because it turns off people's minds [00:01] erichocean: the best standard is a standard that just codifies what everyone does anyway [00:01] JimBastard: guidelines are better then standards [00:02] erichocean: it's pretty obvious at this point that we're not all linking the same way [00:02] erichocean: JimBastard: agreed, but we hardly need T39 giving us guidlines [00:02] JimBastard: guidelines get followed, standards get broken [00:02] JimBastard: lolwut [00:02] JimBastard: T39? [00:03] deanlandolt_: erichocean: how would you propose i write a simple module that could be used in multiple libraries without a standard? [00:03] JimBastard: CommonJS? [00:03] kriskowal: ecma technical committee 39 is the ecmascript committee [00:03] deanlandolt_: commonjs /is/ guidelines [00:04] JimBastard: got ya [00:04] erichocean: deanlandolt_: I wouldn't at this point [00:04] deanlandolt_: it just so happens that we can (and hopefully will) test for conformance against those guidelines [00:04] erichocean: I don't consider that a bad thing [00:05] deanlandolt_: erichocean: really? i consider that an /awful/ thing [00:05] erichocean: and for that you can limit yourself to CommonJS [00:05] erichocean: :_) [00:06] deanlandolt_: erichocean: i'm totally cool with that...and i hope not everyone does [00:06] inimino: it's a pretty unfortunate thing for people who want to write libraries [00:06] JimBastard: brb there is a spirtual healer in my house [00:08] tlrobinson: i'm not sure i see how CommonJS is limiting. it only defines what you should do, not what you're not allowed to do [00:09] bentomas has left the channel [00:09] JimBastard: CommonJS is good enough imo [00:09] tlrobinson: if elliott wants to implement his own module system, he can, which he's doing [00:10] JimBastard: at least for me so far [00:14] aurynn: commonJS seems fine to me [00:15] isaacs: tlrobinson: the great thing about FOSS is that, if his is better, we can all benefit. [00:15] isaacs: and since it's not like he's my employee, i get to encourage all his endeavors, even if i doubt they'll be of any value [00:16] isaacs: (tic, mostly, he seems like a bright guy, and it'll probably be at least a learning experience for him, and likely a benefit to the commonjs/node communities) [00:16] JimBastard: you hiring isaacs? [00:16] JimBastard: :-D [00:16] isaacs: JimBastard: haha, not atm [00:17] tlrobinson: yeah for sure. he could dial down the hostility though [00:20] mattly has joined the channel [00:21] isaacs_ has joined the channel [00:22] logicuce has joined the channel [00:24] isaacs: tlrobinson: agreed [00:27] mahemoff has joined the channel [00:27] aguynamedben has joined the channel [00:29] alex-desktop: speaking of modules and commonjs and all that... [00:30] alex-desktop: the problem I have is, it seems like, to include another JavaScript file, you have to use require, right? [00:30] alex-desktop: (I haven't used it yet, so don't really fully understand it) [00:34] deanlandolt_: alex-desktop: nothing stops you from loading js over fs or http and eval()'ing it in [00:34] alex-desktop: I suppose... [00:34] inimino: alex-desktop: that is the recommended way, sure [00:34] inimino: but ... right [00:34] deanlandolt_: there's just no mechanism to keep modules from pissing in your global pool [00:34] inimino: I have code that does this, it's about 8 lines [00:35] alex-desktop: Well, my issue is that something I consider a single "module" may span a few files... [00:35] alex-desktop: two or three, or so [00:35] alex-desktop: Although I use Python, this bothers me about that language, too... [00:35] alex-desktop: (except it is a language-level thing, there) [00:35] inimino: well, read, concatenate, eval() [00:35] inimino: if that's what you want [00:36] alex-desktop: That is probably what I should end up doing; actually, if it is all part of one module, that would only need to occur in development [00:36] alex-desktop: have it all concatenated for production. [00:36] deanlandolt_: absolute madness AFAIC but commonjs doesn't take this primitive away [00:36] inimino: but why can't you put your modules in a nice hierarchy and have each one include its dependencies? [00:37] alex-desktop: I only like to have one class (if I'm doing "class"-oriented things) per file... [00:37] alex-desktop: So I usually think of a module more like a folder. [00:37] alex-desktop: It's because I lose track of my position in long files too easily. [00:37] deanlandolt_: alex-desktop: that's fine, but what about require semantics stops you from doing that? [00:38] alex-desktop: doesn't stop; just makes it a tad inconvenient at times [00:38] deanlandolt_: because you can't replace the exports object with the class itself? [00:38] inimino: deanlandolt_: which primitive? [00:38] deanlandolt_: (that's my /only/ gripe about require) [00:38] deanlandolt_: inimino: eval [00:38] alex-desktop: My issue is that the module itself cannot export a class [00:39] alex-desktop: that is, I cannot modify exports [00:39] alex-desktop: although... [00:39] deanlandolt_: alex-desktop: heh, yeah, that's my issue [00:39] alex-desktop: I suppose a super module could say exports.whatever = require(whatever) [00:39] inimino: deanlandolt_: eval lets you do things you can't do any other way, it would be insane to remove it without a better alternative [00:39] alex-desktop: What I don't like is: var myClass = require("myClass").myClass [00:40] deanlandolt_: inimino: agreed...i didn't suggest it should be removed (just that you shouldn't use it as your module loader) [00:40] alex-desktop: deanlandolt_: heh; I didn't notice you said that before me :) [00:41] deanlandolt_: alex-desktop: while it's technically against the spec some require implementaitons allow it [00:41] trevor has joined the channel [00:41] alex-desktop: I wrote one once (before actually looking at the spec; just taking the general idea of require) [00:41] deanlandolt_: inimino: though hopefully harmony will have hermetic eval! [00:41] inimino: deanlandolt_: ok, I misread you [00:41] inimino: yes, that would be nice [00:42] alex-desktop: Would this super-module idea work? because that might _almost_ be ideal... [00:43] alex-desktop: exports.ClassA = require("classA").classA; [00:43] alex-desktop: exports.ClassB = require("classB").classB; [00:43] alex-desktop: and then, that module is a namespace; [00:43] inimino: that works now. [00:43] deanlandolt_: alex-desktop: that's all legit [00:43] alex-desktop: Yeah, exactly [00:43] alex-desktop: that helps [00:44] alex-desktop: Makes me think that this will be a lot easier :) [00:44] deanlandolt_: alex-desktop: have a look at this: http://github.com/280north/jack/blob/master/lib/jack.js [00:44] alex-desktop: (though I _still_ wish I could just edit exports) [00:44] deanlandolt_: that's the top level jack obj...then if you follow the middleware include... [00:44] deanlandolt_: it's just like what you're talking about: http://github.com/280north/jack/blob/master/lib/jack/middleware.js [00:45] alex-desktop: Neat :) [00:45] isaacs: alex-desktop: in nodejs, you can. [00:45] deanlandolt_: so effectively you can build one really useful superobject [00:45] isaacs: module.exports = blarg [00:45] isaacs: but, of course, then the "exports" object is lost, so if you do that, you should also change the exports object. [00:45] isaacs: module.exports = exports = blarg; [00:45] alex-desktop: isaacs: but I guess that will not be compatible with other implementations? [00:46] isaacs: alex-desktop: not sure. [00:46] deanlandolt_: isaacs: it wouldn't work in narwhal [00:46] deanlandolt_: (but would work in persvr) [00:46] isaacs: deanlandolt_: yall should fix that then ;) [00:46] alex-desktop: 3. modules must use the "exports" object as the only means of exporting. [00:46] deanlandolt_: isaacs: i tried...it's a feature, not a bug it turns out [00:46] inimino: I think that should be removed from node [00:46] mattly has joined the channel [00:46] isaacs: inimino: why? [00:47] isaacs: it's super handy to be able to export a specific object. [00:47] isaacs: what harm does it cause? [00:47] inimino: there's no need for it, and it constrains implementation [00:47] deanlandolt_: isaacs: i'll try to dig up the thread where i suggested it -- kriskowal gave a very clear explanation of why it's harmful [00:47] tlrobinson: deanlandolt_: yeah bad idea [00:48] inimino: extend(exports, whatever_you_want) [00:48] tlrobinson: you'll run into problems with circular depedencies [00:48] isaacs: inimino: but that doesn't let you do things like returning a new FooBar() [00:49] isaacs: module.exports = new FooBar("baz"); [00:49] dnolen has joined the channel [00:49] inimino: isaacs: exports.foobar = new FooBar() [00:49] inimino: ACTION doesn't see the hardship [00:50] alex-desktop: inimino: makes this annoying thing: var fooBar = require("my/module").foobar; [00:50] alex-desktop: which, if the module is _named_ foobar: [00:50] alex-desktop: var fooBar = require("my/foobar").foobar; [00:50] alex-desktop: is repetitive, annoying, and looks silly. [00:50] inimino: ...I just don't see it [00:51] deanlandolt_: inimino: compatibility with current apis is one hardship [00:51] alex-desktop: (joking) What part of "Don't Repeat Yourself" don't you understand? :P [00:51] logicuce has left the channel [00:51] alex-desktop: Python does the same thing, though... [00:51] alex-desktop: is Kevin Dangoor the one who came up with this originally? Or am I way off? [00:52] deanlandolt_: for instance porting the thousands of lines of qunit code over to commonjs...also, it forces bikeshedding on the name of the thing to hang on exports :) [00:52] deanlandolt_: alex-desktop: he's the one that brought the group together originally [00:52] inimino: deanlandolt_: that I can buy, but that's how standardization goes [00:52] alex-desktop: (he's also a Python guy, isn't he? would explain where some of this came from) [00:53] tlrobinson: alex-desktop: a bunch of debated modules for a couple months [00:53] deanlandolt_: actually i believe the securable modules proposal is mostly the brainchild of kriskowal (and ihab of the caja team -- can't remember his last name)...but that was a little before my time [00:53] isaacs: inimino: you might not see it as a problem, which is fine. you dont' have to use that pattern. but unless you can say that something IS a problem, it seems that an spec should fall on the side of adding flexibility rather than reducing it. [00:53] tlrobinson: http://www.blueskyonmars.com/2009/01/29/what-server-side-javascript-needs/ [00:54] deanlandolt_: isaacs: okay, i'll dig up that thread now -- there is a legit problem associated with it [00:54] isaacs: if there is a legit problem, i'm curious about it, because that problem would exist in node today. [00:54] inimino: isaacs: there are problems [00:54] isaacs: and persvr, yes? [00:55] inimino: isaacs: node allows you to do all sorts of things that will completely hose require() [00:55] inimino: that's not new, and that's more or less the spirit of node [00:55] isaacs: inimino: yeah, we like hosing in node ^_^ [00:55] deanlandolt_: isaacs: true, but the issue is related the "Securable" aspect of SecurableModules [00:56] deanlandolt_: IIUC persvr and nodes implementations just aren't securable [00:56] isaacs: what makes that less securable? [00:56] isaacs: it's not as if a module gets access to anything it shouldn't have. [00:59] deanlandolt_: isaacs: The module must use the exports object that the implementation provided to the module scope. That way the implementation can keep a reference to the exports object before the module has finished executing, mainly in order to handle potential cross dependencies between modules. [01:00] isaacs: so if A requires B and B requires A, you give B the same exports object that's already in process from A? [01:00] deanlandolt_: from: http://groups.google.com/group/commonjs/browse_thread/thread/7c69484abc8a560/183cecf5aca0a31a [01:00] isaacs: if so, that's not about security, per se, but about dependency order [01:01] deanlandolt_: isaacs: it's about dependency order, but IIRC there was a security implication in there [01:03] elliottcable: ohai peeps [01:03] elliottcable: so, what’d I miss [01:03] deanlandolt_: isaacs: also http://groups.google.com/group/commonjs/browse_thread/thread/6a6a4fe4ce4c0200/0673da702ddfc50d?#0673da702ddfc50d [01:04] deanlandolt_: elliottcable: not much, just some back and forth about not being able to replace a module's exports object (the primary complaint re: require, it seems) [01:04] elliottcable: heh [01:04] elliottcable: primary, indeed [01:05] elliottcable: I have a shitton, but that’s certainly the biggest deal. [01:05] elliottcable: I don’t write standard JS; I hate the new keyword, and refuse to use it. I use a prototypal system layered on top, which *absolutely requires* that I have control of my objects from creation time. [01:05] elliottcable: And `require('something').theActualSomethingObjectLolTooBadIHadToPutItInASubKey` is not a serious option. [01:06] elliottcable: I also dislike how require handles paths, but that’s not as big a deal. I’m just happy I get to make those decisions over again with `from` [01:08] isaacs: deanlandolt_, tlrobinson: so, the circular dependency issue is an issue, but imo, it's resolvable. [01:08] isaacs: i'm not convinced by kriskowal's message here: http://groups.google.com/group/commonjs/browse_thread/thread/7c69484abc8a560/183cecf5aca0a31a#msg_5caf402865038391 [01:09] isaacs: returning the exports object would only be necessary if you wanted to be able to do "exports = blah" [01:09] isaacs: but that doesn't work in node, and shouldn't work, imo. [01:09] isaacs: if you want to overwrite the exports object, then the style is: "module.exports = blargh" [01:09] deanlandolt_: isaacs: so what was this module.exports you mention? [01:10] isaacs: deanlandolt_: node exposes a "module" object to modules. [01:10] isaacs: module.exports is the thing that's eventually returned by the require() fn [01:10] deanlandolt_: and presumably it's a node-specific extension? [01:10] isaacs: deanlandolt_: node does its thing, and then bends a little to fit thorugh the commonjs door. [01:10] isaacs: it's not an extension, it's just a node feature. [01:10] deanlandolt_: that could certainly be proposed as an extension to SecurableModules [01:11] deanlandolt_: well, it's an extension of securablemodules...and could be proposed as standard [01:11] isaacs: the circular dependency issue can be solved by the fact that require() returns module.exports, not exports. [01:11] deanlandolt_: it may solve that problem [01:11] deanlandolt_: tlrobinson: ^^ [01:11] elliottcable: hm [01:11] elliottcable: well, again, interesting conversation, but I have a resume to finish *now*. [01:12] isaacs: and anyway, the circular deps issue is an edge case, and one that is easily avoided. [01:12] elliottcable: and I don’t see module.exports as exactly solving the problem; to me, the only solution is a solution wherein I use the `return` keyword to *tell* the system getting my code what I want it to get. [01:12] kriskowal: it's not as edgy as you might think. [01:12] isaacs: the security implication is more relevant, and adding a hack whereby the exports object must be tracked through its changes, that's rough. [01:12] kriskowal: there was a shout out that almost everyone had used cyclic dependencies at least once. [01:13] kriskowal: assigning to module.exports is intriguing. [01:13] isaacs: kriskowal: i'm tno saying that circular deps is an edge case. i'm saying that circular deps in such a way that module.exports doesn't solve the problem, that's edgy. [01:13] isaacs: ie, file.js does "module.exports = new SomethingErOther();" and path.js does "file = require('file')" [01:13] kriskowal: it does still introduce a safety hazard [01:14] kriskowal: it makes it possible for different modules to have a non-identical exports object for some common dependency [01:14] isaacs: kriskowal: if you can demonstrate that, i'll be very intrigued. [01:15] kriskowal: sure. you say this is possible in node? [01:15] isaacs: kriskowal: yep [01:15] isaacs: module.exports = "blah" [01:15] isaacs: once you do that, of course, your "exports" is orphaned, and hanging stuff on it will have no effect. [01:17] trevor: Is there a way I can get true inheritance to work? [01:17] kriskowal: define "true" :P [01:18] trevor: I am trying to use process.inherits to inherit from process.tcp.Server, but it doesn't work because when I do "(new MyTCPServer()).listen(port, host)" I get an error [01:19] trevor: The process.tcp.Server supercall doesn't get init'd I think [01:19] trevor: superclass* [01:21] trevor: function A(){}; process.inherits(A, process.tcp.Server); (new A()).listen(80, 'localhost'); [01:21] trevor: That should work, no? [01:21] isaacs: trevor: afaik, yeah, that should work [01:21] trevor: try it in node-repl and see what happens [01:22] isaacs: post to mailing list [01:22] trevor: Will do [01:23] trevor: For sake of discussion, anyone have an idea why it doesn't work? [01:24] isaacs: kriskowal: http://github.com/isaacs/node-playground/blob/master/circ-1.js [01:25] RayMorgan has joined the channel [01:25] isaacs: trevor: off the top of my head, i'd guess that there's some sort of illegal invocation. [01:25] isaacs: maybe somewhere around line 953/949 of node.js [01:25] isaacs: ;P [01:25] trevor: profound [01:25] trevor: :) [01:26] elliottcable: Interesting claim. [01:26] elliottcable: @wycats is saying that evented programming, a lá Node.js and client-side JS, precludes OOP. [01:26] trevor: My guess is the super class isn't initialized, but I'd have to dig deeper into the code base to be sure [01:27] kriskowal: isaacs http://gist.github.com/255712 [01:27] elliottcable: (see http://tau.pe/6646617472, and the tweet chain it’s in reply to) [01:27] elliottcable: oh, and http://tau.pe is running on Node.js. Just in case anybody was interested. [01:28] isaacs: kriskowal: well, derp [01:28] isaacs: the caveat is simply, if you set module.exports, you do it first thing. [01:28] isaacs: and if you don't, then you're a jerk. [01:29] kriskowal: it's pretty hard to know you're a jerk. [01:29] kriskowal: i think it's more intuitive to do it last; more like return exports [01:29] deanlandolt_: kriskowal: isn't it just as opaque to have to know not to replace exports? [01:29] isaacs: kriskowal: what's intuitive is a personal question. [01:29] kriskowal: the problem could be fixed with a setter, but that's not viable for browser-side [01:29] isaacs: it's intuitive to think exports = "bar" will work. [01:29] elliottcable: what’s intuitive is to *use the fricking constructs baked into the language* [01:30] elliottcable: `myThing = {}` … do stuff … `return myThing;` [01:30] elliottcable: readysetDONE. [01:30] isaacs: elliottcable: it's not so obvious. [01:30] elliottcable: semantic, clean, and no stupid exports object. [01:30] kriskowal: yeah, that works great for more than one developer [01:30] elliottcable: ACTION  [01:30] kriskowal: [01:30] elliottcable: kriskowal: … so the focus is only on single developers? [01:30] elliottcable: kriskowal: oh, sarcasm. I see absolutely no way that works less well for more than one dev. [01:31] isaacs: you both realize you're arguing over a religious question, not a practical one, right? [01:31] kriskowal: i'm not going to engage a subjective argument. [01:31] elliottcable: isaacs: it’s a practical one, for me [01:31] elliottcable: kriskowal: *shrug* [01:32] isaacs: elliottcable: i'm very curious about what you come up with for acquire() [01:32] elliottcable: isaacs: dropped acquire, as a matter of fact. Going with an API somewhat based on Python’s import. [01:33] isaacs: in particular, i like the idea of using return, since it feels "right" in a way, but there are issues that that style brings up, and i personally would rather just use what's working now. [01:33] deanlandolt_: elliottcable: what you're describing sounds like it could just as easily be done with read/eval...what am i missing there? [01:33] elliottcable: isaacs: still working on it; I had to put my Node.js infrastructure projects on hold to work on my resume and get packed (moving to NC soon), but I’ll be working on them again soon. [01:33] isaacs: elliottcable: oh, you're coming to the contiguous states, then? [01:33] elliottcable: deanlandolt_: what I’m describing *is* done with read/eval (well, cat/compile, but whatever) [01:34] kriskowal: ihab and the caja folks would have preferred a system where every module returned its exports or a promise for exports [01:34] deanlandolt_: elliottcable: then what's stopping you from continuing to do that? [01:34] elliottcable: deanlandolt_: as long as cat and process.compile aren’t removed from Node.js, I’ll be fine. I’m only arguing against require() for ideological reasons; I’m not going to have to use it, so it doesn’t directly hurt me. [01:34] isaacs: kriskowal: so, my point is, having to put your module.exports set on the first line is no less intuitive than not being able to overwrite exports at all. [01:34] isaacs: kriskowal: in fact, i was very surprised when i learned that this was impossible. [01:34] elliottcable: deanlandolt_: not to mention that I don’t *like* having to break away from the pac and build my own competing solution, it’d be a lot nicer to see something baked *into* Node.js that I, and those similar to me, can enjoy. But, y’know, whatever works. [01:34] elliottcable: isaacs: I’m actually in Seattle right now [01:35] kriskowal: i don't disagree. my point is that if you pick a developer off the street, there's a 50/50 chance they'll break something [01:35] isaacs: elliottcable: why did i think you were in AK? am i on the crack? [01:35] deanlandolt_: elliottcable: but...compile's already baked in, so you're good to go ;) [01:35] isaacs: kriskowal: i'm not sure i'd take those odds ;) [01:35] isaacs: more like 90/10 [01:35] elliottcable: deanlandolt_: Yes, good to go in that I *can* build my own, alternative solution. I just, like I said, dislike the fact that I sort of have to break away from the pack to do that. [01:36] kriskowal: i know how you feel. [01:36] deanlandolt_: elliottcable: as i understand it the alternative you're proposing is that there /is/ no pack [01:36] elliottcable: deanlandolt_: Essentially, I’m having to write my own fork of Node.js; and my code will be incompatible with normal Node.js to some extent. People wanting to contribute to / use my system will now be separated from people wanting to use the ‘securable modules’ system, which is distasteful. [01:36] kriskowal: i've been writing "commonjs" modules all by myself for three years. [01:36] elliottcable: deanlandolt_: and leads to code duplication/wasted time [01:36] kriskowal: yep [01:36] kriskowal: not wasted if you believe in it and prove something tho [01:37] isaacs: elliottcable: code duplication is wasted time, but explorations of different directions, even if those directions end up being dead ends, is never wasted. [01:37] elliottcable: isaacs: I’m an Alaskan. I’m bouncing all over the country right now, I was in San Francisco, Wilmington, Washington/DC, Seattle, Greensboro… all in the past half month or so. [01:37] deanlandolt_: elliottcable: why do you have to roll your own fork? node.js has compile -- you're golden [01:37] elliottcable: deanlandolt_: Not a true fork, hence ‘essentially.’ [01:37] isaacs: elliottcable: why not build this on top of node as it stands today, and then if people want to use it, they can, and if it makes sense to fold into the core, it can be [01:37] elliottcable: deanlandolt_: My system will run on top of what you get from `brew install node; etc`, but it is ideologically incompatible with normal Node. [01:38] elliottcable: deanlandolt_: code written in/for my ecosystem will be essentially incompatible, without OMGHAX, with code written in/for the CommonJS ecosystem, even though both will run on top of Node.js happily [01:38] elliottcable: deanlandolt_: does that make sense? [01:38] kriskowal: that's the trouble with ideology [01:38] isaacs: kriskowal: so, the issue is that module.exports opens the door for breakage... what about module.setExports(newObject)? [01:38] elliottcable: isaacs: yeah, that’s exactly my current point of view. I’d love to see this all go back into Node.js, but I’ve learned to be okay with the idea that it might not. (-: [01:38] kriskowal: isaacs, same problem. there's no way to replace a reference that has already been acquired in the local scope of another module. [01:38] kriskowal: in E there. not so much for javascript. [01:39] isaacs: kriskowal: well, but in that case, you could throw an error. [01:39] deanlandolt_: elliottcable: i see...that makes sense -- i thought you were just writing this module system for your own code (hence, it would not really be incompatible at all) [01:39] kriskowal: by tracking whether you've given anyone a reference to a module's exports? [01:39] isaacs: if the exports had already been acquired by another require() statement, you could throw "Sorry, can't set it, someone already has a ref to it." [01:39] isaacs: kriskowal: exactly [01:39] elliottcable: isaacs, deanlandolt_: It’s sort of similar to the RubyGems thing. The problem is that, to solve some of the problems in this system, I *absolutely have* to have complete control over the system of filepaths, from the moment node is launched. Therefore, my system plays fine on top of Node, as long as the first file run uses my code. You can even use ‘securable modules’ through `require()`, once that’s set up. [01:39] kriskowal: yeah. you could do that. [01:40] elliottcable: isaacs, deanlandolt_: However, as with RubyGems, it would be dirty to have every project include a line akin to `require 'rubygems'` at the top of their files (which is essentially what you have to do, to play nice with ‘securable modules’)… and I dislike that dirtiness [01:40] kriskowal: that might be an important discovery. [01:40] isaacs: kriskowal: it's amusing that you feel that way. my first crack at overwriting the exports object in node was to expose a setExports function, but i was overruled by ryah, who said that it would be better to not add another pseudo-global [01:41] isaacs: i agreed with him, and since the "module" object was already there, he just had it use that. [01:41] elliottcable: I completely agree with ryah on that. [01:41] isaacs: kriskowal: important discovery? [01:41] elliottcable: ACTION is trying to get @wycats in here [01:42] kriskowal: that module.setExports and require could be wired to detect and prevent exports non-identity hazards [01:43] elliottcable: oh, who had asked about acquire() earlier, by the way? [01:43] isaacs: elliottcable: i just referred to it, i think, since i thought you were working on that. [01:43] elliottcable: I’m essentially ging for ‘Your file is a bigass function with its own scope,’ so you can `return` whatever you want; then, whatever you give me, I will give to the person asking for your file, barring some other wishes on their part [01:43] isaacs: kriskowal: it would also avoid the var Foo = require("foo").Foo silliness. [01:44] elliottcable: (for instance, they can ask for particular properties, if they are defined, a lá Python) [01:44] kriskowal: yeah, the ability to make modules callable or instanciable without conflating the type system is a pretty big deal [01:44] isaacs: kriskowal: you could instead do something like var myFoo = new (require("foo")) [01:44] deanlandolt_: kriskowal: /huge/ deal for backward api compat! [01:44] kriskowal: yeah, i know [01:44] kriskowal: we looked into it a long time ago [01:45] kriskowal: the reasons for wanting it are obvious, but ways to make it hazard-free didn't pop up [01:45] isaacs: i'm gonna look into making a fork of node that exposes module.setExports, and we can test that out. [01:45] elliottcable: oh, as for forking Node [01:45] elliottcable: I’m actually probably going to have to do that [01:46] elliottcable: as I said, my `from` very much necessitates having control of the path handling from the very start; `require()` has the same requirement for the same reasons [01:46] elliottcable: so I think I’m going to try to abstract out that bit, and make it so Node.js can hand it to `require()` *or* `from`, or really, any other system as well [01:47] deanlandolt_: elliottcable: perhaps there could be a way to make them work together [01:49] elliottcable: deanlandolt_: yea, that’s exactly what the goal is [01:50] elliottcable: deanlandolt_: the path handling stuff is not complex, it could easily be abstracted away from the requires of require() and from [01:56] noxa has joined the channel [02:02] kriskowal: eliottcable, you're looking for "from module import a,b,c" as a style? [02:04] elliottcable: kriskowal: mmhm [02:04] kriskowal: we're projecting that future-es will have destructuring that will take care of that [02:04] elliottcable: kriskowal: http://github.com/elliottcable/poopy.js/blob/new-acquire/lib/from.js#L80-82 [02:05] kriskowal: without breaking lexical scoping [02:05] kriskowal: yeah. var {a, b, c} = require("module"); [02:05] kriskowal: very much looking forward to destructuring [02:06] elliottcable: It’s not a *big* requirement, just a lice little thing that takes me no time to provide, so… [02:06] elliottcable: and it works well when your ‘library’ is just an unstructured collection of little things [02:06] elliottcable: i.e. what ‘securable modules’ assume *all* libraries are [02:07] elliottcable: I’m also providing export(), which is the opposite [02:07] kriskowal: right, __all__ semantics [02:07] elliottcable: and fairly evil, and I’m not sure why I’m providing it… probably going to leave it undocumented [02:07] elliottcable: but it does the opposite; injects things into the scope of the file you’re requiring, instead of injecting things from the file you’re requiring into your scope [02:08] kriskowal: so, that's another thing about hermetic eval… [02:08] kriskowal: we're shooting to provide the ability to do that kind of thing, except safely [02:08] elliottcable: heh [02:09] kriskowal: free variable injection. [02:09] elliottcable: the way I implemented it is ridiculously simple: [02:09] elliottcable: http://github.com/elliottcable/poopy.js/blob/new-acquire/lib/from.js#L225-229 and http://github.com/elliottcable/poopy.js/blob/new-acquire/lib/from.js#L261-263 [02:09] ashb: and dangerous to boot? [02:09] kriskowal: eliottcable, yep [02:09] elliottcable: ashb: eh>? [02:10] kriskowal: eliottcable http://github.com/kriskowal/narwhal/blob/refactor/engines/rhino/bootstrap.js#L46-62 [02:11] elliottcable: yeah seems pretty similar [02:11] elliottcable: unfortunately, normal-JS is about the most unreadable language I know of, so I’m not *entirely* sure what’s going on there [02:11] kriskowal: the "hermetic evaluator" will have the same behavior, which opens the possibility of sharing compilation [02:11] kriskowal: evaluate(text, fileName, lineNo)(scope) [02:13] kriskowal: load(id) => id = resolve(id, baseId), text = fetch(id), evaluate(text, id, 1) [02:14] elliottcable: *whoosh* [02:14] kriskowal: require(id) => load(id)({require…}) [02:14] kriskowal: the abstract design of require is: evaluate + fetch + resolve = load. load + resolve + injection = require [02:15] elliottcable: again, *whoosh* [02:15] kriskowal: perhaps too much detail is lost. [02:15] elliottcable: I learned programming by typing stuff into a text editor until it worked. ‘sharing compilation,’ ‘hermetic evaluator,’ ‘abstract design of require,’ all go *whoosh*. [02:15] elliottcable: So, what *is* Narwhal? [02:15] kriskowal: hey, me too! [02:16] elliottcable: Seeing as you linked me into its source… [02:16] elliottcable: If you want to explain things so I’ll understand them, use phrases like ‘So the bit will go into the thingie and get run with that argument set to the thingie!’ [02:16] elliottcable: lol [02:16] kriskowal: ah. narwhal's a prototype impl of commonjs that does package management and stuff [02:16] kriskowal: so. code. [02:17] kriskowal: it's tlrobinson's project. i use it as a test-bed for ideas. [02:17] kriskowal: it's designed to work with multiple engines. [02:18] elliottcable: so, like Node.js, but non-async, and built to be v8/sf/etc agnostic? [02:18] elliottcable: and with package management? [02:18] kriskowal: it's not strictly non-async, but it doesn't have the anti-sync ideology [02:18] kriskowal: and yes. package management. [02:19] deanlandolt_: elliottcable: i look at narwhal as a js stdlib [02:19] kriskowal: i'm trying to get node running on it. [02:19] deanlandolt_: it's certainly been my stdlib for the past months [02:19] elliottcable: Been thinking about writing one of those. Will have to see how Narwhal fits into my ‘hermit ecology.’ [02:21] elliottcable: See, my overall eventual goal is a web framework, on the scale of Rails, but split into a ton of tiny pieces. Node.js is the perfect POSIX wrapper/low-level infrastructure; I want a very light packaging system (`from`), a test-bed (grizzly), a set of light libraries to gloss over the more semantically painful bits of JS (enumerators and such), a set of heavier libraries to provide convenience tools ... [02:22] elliottcable: ... (ActiveSupport-esque), a precompiler to get rid of the parts of JS’s syntax I can’t stand (JESS), and finally a client/server system for syncing the two environments so I can ship code back and forth [02:22] elliottcable: the goal being that all of these could work together. [02:22] elliottcable: Did I seriously just write a message so long that irssi decided to split it up? o_O [02:23] kriskowal: might want to look at my chiron for the iterator stuff [02:23] deanlandolt_: elliottcable: that's a pretty substantial effort [02:23] hober has joined the channel [02:24] kriskowal: http://github.com/kriskowal/chiron/tree/master/lib/chiron/ [02:24] elliottcable: kriskowal: primary requirement is that it is light (things like jQuery, Underscore, MooTools… all provide a lot of what I listed, but they all try to be Godsystems that provide (and control) *everything*) [02:24] elliottcable: kriskowal: if your chiron is light and focuses on one aspect of all that, and plays well with my sort of systems… I’m totally down with that. d-: [02:24] kriskowal: yeah, underscore might be your win [02:25] kriskowal: chiron's a bit heavier than those [02:25] elliottcable: kriskowal: I took a look at Underscore; I *might* make use of it, but only after bastardizing it. I *really hate* how Underscore and jQuery make you turn JS objects into specialized ‘Underscore (or jQuery) objects’ with their sneaky _() or $() functions before doing anything with them. [02:25] elliottcable: I feel that a proper system will just build on top of JS itself, not try to circumvent it with sneakiness. [02:26] kriskowal: type, Set, Dict, List, a bunch of basic operators. essentially provides python's builtins adapted to js [02:26] elliottcable: deanlandolt_: I’m an ambitious person, and an *absolutely prolific* coder. It took me about two years, but I built my own Ruby infrastructure from scratch, including every library I might need for anything. I’m obsessive that way [02:26] elliottcable: kriskowal: github me [02:26] kriskowal: already did [02:26] kriskowal: http://github.com/kriskowal/chiron/tree/master/lib/chiron/ [02:26] elliottcable: woah [02:26] elliottcable: #fail on my part [02:26] elliottcable: ACTION pokes at type.js [02:27] elliottcable: iojs? [02:27] kriskowal: old idea for the commonjs name. [02:27] kriskowal: had some special behaviors an old loader respected. [02:27] kriskowal: i had a loader that had from module import * semantics that i wanted to suppress opt-in [02:28] kriskowal: for the transition. i still have a backlog of modules to port to commonjs which involves removing a lot of include() calls [02:52] mattly has joined the channel [03:03] inimino: ACTION sees huge backscroll [03:09] elliottcable: lol [03:09] inimino: "`require('something').theActualSomethingObjectLolTooBadIHadToPutItInASubKey` is not a serious option." does not strike me as a serious objection. [03:10] kriskowal: so, how good is waf-light? [03:11] kriskowal: does it detect changes in dependencies? [03:11] kriskowal: or do i have to run something like configure every time they change? [03:11] elliottcable: inimino: why not? [03:12] inimino: ACTION is still reading epic backscroll [03:12] elliottcable: you actually bother to read it all? [03:12] kriskowal: oh. i see. [03:13] elliottcable: kriskowal: I couldn’t figure out waf stuff. http://groups.google.com/group/nodejs/browse_thread/thread/cf5ae41c5add16ac [03:15] kriskowal: i found where i have to explicate the dependency. [03:15] kriskowal: shame that's not automatic. [03:17] inimino: elliottcable: I read most of what goes by, yeah [03:18] inimino: elliottcable: the reason I don't see it as a serious requirement is because it seems petulant to build your own system over a minor syntactic annoyance that has no practical side effects [03:19] fictorial has joined the channel [03:20] mahemoff has joined the channel [03:20] elliottcable: … [03:20] elliottcable: it’s not syntactic, and it’s far from minor. [03:20] elliottcable: The problem is semantic. [03:20] elliottcable: There is a *hack*, that allows you to work around it, and that *hack* has minor syntactic side effects. [03:20] inimino: you want to get an object out a module [03:20] elliottcable: But the problem that the hack works around, is neither syntactic, nor minor. [03:20] elliottcable: No, I don’t. I want to give somebody an object. [03:21] elliottcable: I don’t want anything to do with modules, *period*. [03:21] elliottcable: My package is not a module, in the way that CommonJS talks about them. [03:21] elliottcable: And yet I am given no way to distribute code that *isn’t* one of those modules. [03:21] inimino: you can do it by attaching it to the exports object, which requires you to add an extra property access to your code where the module is imported [03:21] inimino: that's minor [03:21] elliottcable: Not everything in the world is utils.js; not everything is simply an array of useful functions. [03:21] elliottcable: Yes, it is, and it’s a hack. [03:21] inimino: everything in the world can be precisely that [03:21] elliottcable: It doesn’t solve the underlying problem at all, it works around it. [03:22] rictic has joined the channel [03:22] alex-desktop: inimino: everything in the world can be an array of useful functions? [03:22] elliottcable: yeah, that’s totally not true. at all. [03:22] alex-desktop: because that isn't exactly an object-oriented statement... [03:23] alex-desktop: but on the other hand, I don't see the serious problems in the module pattern, either [03:23] alex-desktop: some annoyances, but I wouldn't _yet_ call them serious... [03:23] elliottcable: Yes, the entire module system says ‘screw you’ to the entire JavaScript method of object orientation, and that’s what I hate. [03:23] alex-desktop: It does? [03:23] alex-desktop: How? [03:23] inimino: alex-desktop: sure [03:23] alex-desktop: exports.myObject = function(){ this.whatever='whatever'; } [03:23] elliottcable: There is *absolutely no way* (other than aforementioned *hack*, keyword *hack*) to be protypally object-oriented inside the framework of ‘securable modules’ [03:23] deanlandolt_: elliottcable: i'll buy that, but that doesn't really dispute inimino's point that it's largely syntactic [03:23] alex-desktop: exports.myObject.prototype.whatever = 'whatever'; [03:24] elliottcable: deanlandolt_: I don’t care that much about syntactics; I can work around them all in JESS anyway (speaking of hacks… hehehe) [03:24] elliottcable: deanlandolt_: my problem is the semanticity of it. [03:24] inimino: "hack" is subjective [03:24] alex-desktop: elliottcable: I'm still not seeing it... but maybe that's just me. [03:24] elliottcable: deanlandolt_: `require('foo').bar` says ‘I want the bar bit of foo.’ [03:25] elliottcable: deanlandolt_: when, in reality, what you want, is bar. yet you can’t `require('bar')`, because require is broken. [03:25] fictorial: ftlog ppl [03:25] fictorial has left the channel [03:25] elliottcable: ACTION is a huge, huge obsessee of semantic codes [03:25] inimino: whatever you want to return from your file, attach it to exports [03:25] inimino: read the property [03:25] inimino: end of story :-) [03:25] alex-desktop: elliottcable: an annoyance, but I wouldn't call it a big problem [03:25] deanlandolt_: elliottcable: it sounds as though there may be a way around that that we could actually standardize on though [03:25] inimino: unless you want to go mucking about in global scope, or something like that [03:26] elliottcable: inimino: how is that discoverable, pray tell? Normal modules go, to a user, `I want foo. I suppose I should try `require('foo')`!’ [03:26] elliottcable: inimino: unfortunately, *my* code, because I decide to work *with* the principles of JavaScript instead of against them, doesn’t work that way. [03:26] inimino: elliottcable: documentation? [03:26] alex-desktop: elliottcable: I'm still not seeing the with/against structure of JavaScript... [03:26] elliottcable: inimino: instead, unlike *every other module*, I’m stuck with either A) explaining to my users that they have to use an ugly hack (`require('fooModule').foo`), or B) telling them to install my alternative, un-broken system. [03:27] elliottcable: alex-desktop: I use a truely prototypal system; i.e. objects in my libraries all inherit from other objects, and you are intended to create your own objects that inherit yet further from the objects I provide. [03:27] elliottcable: alex-desktop: there’s no way to control the inheritance of the object returned from the require() system for you. [03:27] inimino: elliottcable: don't take this the wrong way, but I think your criteria for what is "an ugly hack" are a little out of alignment [03:28] elliottcable: inimino: I’m blowing it way out of porportion on purpose; really, it’s not that big a deal, and I’m writing my own solution, so I don}t even *have* to worry about it. [03:28] elliottcable: inimino: it just bothers me that people seem to think there’s no problem here, when there is. Hence, blowing out of porportion, to help people see it. [03:28] alex-desktop: I'm inclined to agree... but exports.myFunction.prototype = new require("whatever").baseClass? [03:28] inimino: it's writing your own solution that I think is blowing it out of proportion ;) [03:28] inimino: just put up with it, there are bigger fish to fry, surely [03:28] elliottcable: alex-desktop: no myFunction.prototype in my system; we don’t use the `new` keyword nor traditional constructors [03:29] alex-desktop: so how does that go "in the structure of JavaScript"? [03:29] elliottcable: alex-desktop: it’s prototypal [03:29] elliottcable: alex-desktop: 100%, true, purist prototypal. No silly psuedo-classes. [03:30] inimino: alex-desktop: 'new' isn't terribly in-the-spirit-of-JavaScript, at least from some perspectives [03:30] elliottcable: yeah. [03:30] elliottcable: See, I’m not talking ECMAScript 3.1 [03:30] alex-desktop: ok... care to explain to me how it works, brief overview-ish? [03:31] elliottcable: I’m talking JavaScript, as I see it, as many see it: A very specific subset of ECMAScript 3.1 [03:31] elliottcable: A language that includes ‘objects’ that are just hashes of other objects; a language where functions are objects; a language with closures and great scoping; a language with true prototypal inheritance. [03:31] alex-desktop: I get everything except the last one... [03:31] elliottcable: All that clusterfuck with the constructor invocation pattern is best ignored. [03:32] alex-desktop: haven't come across the last bit before (unless I forgot, which has been known to happen). [03:32] elliottcable: alex-desktop: http://github.com/elliottcable/poopy.js/blob/master/lib/poopy.js [03:32] elliottcable: alex-desktop: `var yourCoolobject = myCoolObject.beget();` [03:32] elliottcable: alex-desktop: the `new` is necessary due to the implementation of ECMAScript; however, I do my best to abstract it away from the user, with beget() [03:32] alex-desktop: ok, I get this, I suppose... [03:33] elliottcable: beget() is really just a little bit more complex/powerful version of ECMAScript 5’s Object.create() [03:33] alex-desktop: actually, I think I've done a couple things like this before, but I can't really recall... [03:33] elliottcable: probably, it’s fairly popular [03:33] elliottcable: mine is just one of many implementations [03:34] RayMorgan has joined the channel [03:34] alex-desktop: Yes, I'm certain I've implemented something to this effect before... huh. [03:34] alex-desktop: actually, SproutCore might even work like this [03:34] alex-desktop: never looked at its SC.Object.create, but it seems roughly like what it would do [03:34] alex-desktop: it I had to guess [03:34] elliottcable: ditto [03:35] elliottcable: never looked at SproutCore at all, but I expect so [03:35] alex-desktop: Anyway, what prevents it from working in require (since I am too lazy at the moment to think of the implications here) [03:35] elliottcable: ‘securable modules’ means you don’t have control over the object returned from the `require()` function. [03:36] elliottcable: the obvious hack being either A) user-side (using `require('thingModule').thing`), or B) implementor-side (`module['exports'] = thing`) [03:37] alex-desktop: Well, it is all a matter of how you think of it... [03:37] alex-desktop: I'm not against a module pattern [03:37] alex-desktop: what I'm against is how the require specifically treats every file as a module [03:37] elliottcable: yep [03:37] alex-desktop: See, I might have an "alex" module, that has pieces in many files [03:37] alex-desktop: I'm not against using alex = require("alex"); alex.thing1, alex.thing2 [03:38] alex-desktop: The problem is that then thing1 and thing2 would both need to be in the file "alex.js" [03:38] rictic: Or alex.js could require them from its submodules and then re-export them [03:38] alex-desktop: But my objection is lessened given that I can make alex.js just do: exports.thing1 = require("thing1"), etc. [03:38] alex-desktop: in short, what rictic said [03:38] alex-desktop: hold on, brb [03:40] alex-desktop: back [03:40] elliottcable: ACTION shrugs [03:40] alex-desktop: rictic: Can you do that in Python, because that would help a lot... [03:40] elliottcable: I’ve said it a few times, I should probably stop arguing this. I’ve got my own solutions. [03:40] elliottcable: I guess it just bugs me that this bothers *nobody but me*, while I see it as a big issue. [03:41] elliottcable: … so I argue in hopes that somebody will pop out of the woodwork who actually agrees d-: [03:41] alex-desktop: elliotcable: It bothers me slightly, but not much. Sorry :( [03:41] elliottcable: ACTION shrugs [03:41] elliottcable: no biggie [03:41] rictic: alex-desktop: I think so, more or less. instead of alex.js you create a directory named alex, then you create alex/__init__.py where you export what you want [03:41] alex-desktop: hm... I guess it should work. Would potentially warm me up to Python; [03:42] elliottcable: rictic: yeah, I also disliked that __init__/index thing. I use packagename/packagename.js in `from` [03:42] alex-desktop: elliottcable, rictic: I made a package loading system in JavaScript awhile back for my own scripting environment... [03:42] alex-desktop: had overly complex path management and a few other things [03:42] alex-desktop: s [03:43] elliottcable: obvious problems being that A) have to rename the file when you move it (no biggie), and B) that if you have a lot of subpackages, you have a lot of tabs in your editor all named ‘index.js’ (big biggie, as I know well coming from websites with fifty disparate index.xhtml’s) [03:43] rictic: The __init__.py stuff is a pretty ugly hack. I also can never really wrap my head around how relative paths work in python import statements. I really really prefer require("./alex.js") in node [03:43] alex-desktop: I don't; I prefer relative. [03:43] alex-desktop: but then I also have some more weird relative path likings [03:43] elliottcable: rictic: did you see the writeup on the `from` system I’m working on? I think it’s fairly clean [03:44] rictic: elliottcable: no, link? [03:45] elliottcable: rictic: http://github.com/elliottcable/poopy.js/blob/new-acquire/lib/from.js [03:45] rictic: alex-desktop: I'd probably like python's import path stuff more if I went and learned all about it, but as it is I find that I'm surprised by how it works. node's require is intuitive to me, I haven't had to read anything about it and nothing has surprised me yet [03:46] alex-desktop: there's just one major issue I have with it... [03:46] alex-desktop: Say I make a module "mymodule" [03:46] alex-desktop: And I guess I'd put it in the "libs" directory of whatever I'm working on (node-based, perhaps?) [03:47] alex-desktop: or modules directory [03:47] alex-desktop: or something [03:47] alex-desktop: anyway, then I say, you know, I should use this in more projects, so I put it in some "standard" directory [03:47] alex-desktop: now I have to go change the other code from "./mymodule" to "mymodule" [03:47] alex-desktop: Or something similar to that, anyway [03:48] alex-desktop: Might not be bad, however, if a "modules" directory existed in the node.js, etc. [03:48] alex-desktop: kind of like "frameworks" directory on SproutCore [03:48] elliottcable: yep, `from` solves that too (#justsayin) [03:48] elliottcable: d-: [03:48] alex-desktop: where it would treat it like a path [03:48] alex-desktop: (I think this is possible in the require system... don't know) [03:49] elliottcable: I have `from.file()` and `from.package()` [03:49] elliottcable: and both support relative paths (to the executing file), absolute paths (duh), and `process.paths` [03:49] elliottcable: so moving something from a local directory to one of the `process.paths` directories works fine, or should [03:50] alex-desktop: I think I'm looking for "require.paths"... [03:50] elliottcable: `require.paths === process.paths` [03:50] alex-desktop: yeay [03:50] alex-desktop: *yeah [03:51] elliottcable: oh, is there an identity operator in JS? Not just if two objects are truely equivalent, but if they’re the same actual object ID in the JS system? [03:51] elliottcable: or does that even make sense? o_O [03:51] rictic: elliottcable: === does that for objects [03:51] elliottcable: rictic: what about strings and such? [03:51] rictic: var a = {}; var b = {}; var c = a; a === c; a !== b; [03:52] inimino: that's also what == does [03:52] inimino: for objects [03:52] elliottcable: yah, but I meant for *everything* [03:52] elliottcable: Strings *are* mutable, right? iirc? [03:52] alex-desktop: So my server could just require.paths.unshift("wjatever")... good to know [03:52] elliottcable: ACTION is getting his languages confused at this point, tooo manyyy [03:52] deanlandolt_: elliottcable: no they are not [03:52] inimino: there is no such concept for anything else [03:52] rictic: Strings are immutable [03:52] inimino: no, they are not [03:52] inimino: nothing but objects is mutable [03:52] elliottcable: alex-desktop: process.paths! process.paths! [03:52] elliottcable: ah, damn. thanks guys. [03:53] alex-desktop: sticking with pure node for now, but I'll take a look :) [03:53] alex-desktop: one new thing at a time :) [03:53] elliottcable: alex-desktop: what? o_O [03:53] elliottcable: alex-desktop: `process.paths` is pure Node [03:53] alex-desktop: require and require.paths is built-in... [03:53] alex-desktop: is process.paths too? [03:53] elliottcable: alex-desktop: http://github.com/ry/node/blob/master/src/node.js#L714 [03:54] elliottcable: I have no idea why it’s listed as require.paths in the docs o_O [03:54] rictic: === works for strings and such, with one place that might be a bit counter-intuitive, or surprising [03:54] alex-desktop: weird... [03:54] elliottcable: ryah: any particular reason? (process.paths is listed as require.paths in the docs) [03:54] alex-desktop: you know, that's very confusing [03:54] rictic: There are object types for all of the primitive types. So while "abc" === "abc", new String("abc") !== new String("abc") [03:54] alex-desktop: and require.paths is set to process.paths [03:54] alex-desktop: very odd [03:54] elliottcable: oh! since ryah is not ryah_away… this has been on my Things.app todolist for like a freaking month: [03:55] elliottcable: ryah: Ask @ryah why NODE(1) specifies the posix.stat return object to have *functions* instead of *properties*. [03:55] alex-desktop: maybe it is just another name? [03:55] elliottcable: ryah: why don’t we simply have static values in the posix.stat return object? it’s not like they’re dynamic. [03:55] elliottcable: rictic: yeah, that much I was aware of [03:59] alex-desktop: wait; so require("dobby") would match dobby.js OR dobby/index.js? [04:01] alex-desktop: elliottcable: Look like process.paths is node; require.paths is CommonJS [04:01] alex-desktop: but they mean the same [04:02] inimino: elliottcable: most of them are just integers or bitmasks, the functions are just a convenience [04:05] rictic: The functions could be properties though, they'll always return the same value, and none of them look like they'd be expensive to calculate [04:05] elliottcable: inimino: yeah, that’s my point, why not put them in properties instead of functions? [04:06] elliottcable: rictic: or even getters that replace themselves with the values, heh [04:06] rictic: Making them functions makes them feel more dynamic, might make someone think that they're up to date with the filesystem [04:06] elliottcable: rictic: to remove that bit of performance issue [04:06] elliottcable: rictic: exactly my problem with them. [04:06] inimino: because they are not /in/ functions [04:06] inimino: sure, you could do that, if v8 had getters [04:06] soveran has joined the channel [04:07] elliottcable: oh, v8 doesn’t have getters? o_O [04:07] elliottcable: I’m not a huge fan of them; in fact, I avoid using them in the same way as the new keyword. I just thought they were appropriate for something so low-level. [04:07] elliottcable: (and preformant-conscious) [04:07] inimino: they are working on them if they don't bet they are a new feature in the language [04:07] inimino: I think the functions are fine [04:07] rictic: v8 is pretty strictly EcmaScript v3 at this point as far as I know [04:07] inimino: I assume anyone using stat() will know what it does [04:08] elliottcable: inimino: perhaps, but it’s not a question of which is okay—both are okay—it’s of which is better [04:08] elliottcable: inimino: *now*, before the API is officially stabilized, is the time to work all this out, and get the best API possible [04:08] inimino: the confusion issue can be cleared up by having higher-level libraries for files [04:09] inimino: I prefer the node API be as low-level as possible and everything else be in higher-level libraries [04:09] inimino: in general [04:09] inimino: so if fs.stat() looks exactly like an async stat(2) that's fine with me :) [04:10] elliottcable: agreed [04:10] elliottcable: very agreed [04:11] elliottcable: don’t htink that precludes using the more semantic value in the slot instead of a less semantic function d-: [04:12] elliottcable: see, the docs are misleading, which is what bothers me. The describe exactly what I would expect: http://cld.ly/00rw9 [04:12] elliottcable: they say what I get is an object, a hash of keys to values. Instead it’s an object with some methods to *get* values. Y’see? [04:13] rictic: Well that's what you get if you do JSON.stringify on the stats object [04:13] rictic: So no functions, and the dates have been turned to strings [04:13] inimino: but that is what you get [04:13] inimino: the functions are on the prototype [04:13] elliottcable: oh wait, seriously? [04:14] elliottcable: see, my problem is that when I went to use it, I was using things like `myFile.mode` all over the place, and it blew up [04:14] elliottcable: maybe since then, the values actually *are* set on the return object. In that case, I have no problem with redundant accessor functions on the prototype. [04:52] micheil has joined the channel [05:06] micheil has joined the channel [05:10] isaacs has joined the channel [05:30] isaacs: kriskowal: oh, i don't think I mentioned this, but setting the exports object directly really becomes relevant (as in, "the only way to solve a problem") if you want to have a module that proxies another module. [05:34] elliottcable: Hey all. [05:34] elliottcable: What’s up? [05:36] rictic: I'm looking into the easiest way to re-parse dates that have been JSON.stringified [05:38] aguynamedben has joined the channel [05:39] aguynamedben has joined the channel [06:06] micheil has joined the channel [06:20] hassox has joined the channel [06:21] hassox has left the channel [06:27] mikeal has joined the channel [06:27] mikeal: I'm trying to sandbox an eval [06:27] mikeal: i just need to eval in a different context than the global one [06:28] mikeal: i can't do eval.call({}, 'code') [06:28] mikeal: is there a way to create a new execution context in node.js [06:37] simoncpu has joined the channel [06:38] simoncpu: hi [06:38] simoncpu: anyone seen ryan? [06:39] simoncpu: he seems to be busy... haven't received feedback on my patch yet... =) [06:50] JimBastard: lol [06:50] JimBastard: http://www.youtube.com/watch?v=TCtKUSb2Xmc&feature=player_embedded [06:50] JimBastard: thats me [06:50] JimBastard: sup binary42 [06:51] binary42: JimBastard: Looking. [06:51] binary42: Yes it is. Yes it is. [06:53] micheil has joined the channel [06:55] binary42: ACTION laughs at the "active NY lifestyle" line. [06:58] binary42: "I would take what I need to survive" [06:58] binary42: So NYC. [07:02] JimBastard: ahaha you like the footage of my robbing the bodega [07:03] JimBastard: you break the rules you going to apartment jail [07:03] JimBastard: its a bit silly [07:03] sveimac has joined the channel [07:03] binary42: Yeah. Random but some funny stuff that some wouldn't get outside of city life. [07:04] elliottcable: lol [07:04] elliottcable: binary42: where do I know you from o_O [07:04] binary42: Ruby land? [07:04] binary42: JS land? [07:04] binary42: IRC? [07:05] binary42: Probably twitter. [07:05] binary42: ACTION can't keep track of who is who on twitter anymore. [07:06] elliottcable: JimBastard: what the fuck is that video [07:07] JimBastard: elliottcable this is what you do on friday nights when you are unemployeed [07:07] JimBastard: im the one making the prank phone cals [07:08] elliottcable: >,< [07:08] elliottcable: lol [07:08] elliottcable: binary42: Ruby and Twitter, I suppose. [07:17] JimBastard: i hate twitter so much [07:17] JimBastard: ill never use it [07:17] binary42: JimBastard: Ha! Grumpy old bastard. [07:17] JimBastard: lolz [07:17] JimBastard: my twitter account is the best [07:17] binary42: I actually find it quite useful but I wouldn't argue that there are plenty of idiots. [07:17] JimBastard: http://twitter.com/jimbastard [07:18] elliottcable: plenty. [07:18] JimBastard: i think my account sums up twitter pretty well [07:18] elliottcable: lol. [07:18] elliottcable: I tweet ~464 times a day, on average. [07:18] elliottcable: ACTION is an addict [07:18] binary42: Hmmm. "report for spam" [07:18] binary42: =D [07:19] elliottcable: d-: [07:19] elliottcable: Feel free, you wouldn’t be the first. [07:19] binary42: Not you. [07:19] elliottcable: I generally find one new person or so has blocked me every day. /-: [07:19] binary42: Mr JimBastard. [07:20] jtaby has joined the channel [07:20] elliottcable: jtaby! [07:20] aurynn: Just assume everyone is on twitter. [07:20] JimBastard: apartment jail [07:20] JimBastard: for using twitter [07:20] elliottcable: everyone except JimBastard [07:20] binary42: Anyway.... done doing what I stayed up for. 2:19 EST == ugly early morning. [07:21] Nailor: elliottcable: Has anyone over coined you a phrase "less is more"? ;) [07:21] Nailor: s/over/ever/ [07:21] elliottcable: Nailor: Indeed, and in design and code I’m a minamalist. I just tend to tweet a lot. [07:21] elliottcable: fuck, minimalist* [07:31] jtaby: elliottcable: ? [07:33] elliottcable: jtaby: just waving, familiar nick [07:35] jtaby: hah [07:40] isaacs: kriskowal: still here? [07:41] kriskowal: aye [07:41] isaacs: i got an implementation in a node branch that lets you call require.setExport(), but not once the module has been acquired. [07:41] isaacs: it's a bit of a kludge, though [07:41] isaacs: i just hopped in where we're pulling out of the cache, since that means that the module is being loaded a second time [07:42] kriskowal: aye [07:43] isaacs: however, that also means that a second require() wouldnt' refer to the same object anyhow, if it fell out of the cache. [07:43] isaacs: atm, that's impossible, of course. [07:44] isaacs: but i'm just thinking, if we ever want to make the module cache not be unlimited in size. [07:46] isaacs: http://github.com/isaacs/node/commit/157a39376729890e3969059321257747c3a7790b [07:47] kriskowal: wes and i argued about that a long time ago. [07:48] kriskowal: keeping modules indefinitely was a real problem since spidermonkey doesn't have generational garbage collection and the collector rate is directly proportional to the memory footprint. [07:49] kriskowal: i'm of the opinion that it would not be correct, by policy, for different objects to be served, but that on a module-by-module basis, you might be able to make some optimizations [07:49] isaacs: i think you can basically have either one or the other. [07:49] isaacs: either require("a") *always* refers to the same thing, no matter when you do it, and that's assured, or it doesn't. [07:49] isaacs: if it doesn't, then you can expire parts of your cache. [07:50] kriskowal: re o.hasOwnProperty(k) http://askawizard.blogspot.com/2009/12/object-container-or-type.html [07:50] isaacs: and if it doesn't, then having a "broken" setExport() isn't really a problem. [07:51] kriskowal: if you don't make a proposal to commonjs, i'll get around to it. [07:51] isaacs: hm, i guess that does break on require("hasOwnProperty") [07:51] kriskowal: yeah. i test for that in the suite. [07:51] kriskowal: because i'm a jerk [07:51] isaacs: ACTION grumbles... [07:51] isaacs: ok, i'll fix. [07:51] isaacs: jerk. [07:51] isaacs: ;) [07:53] logicuce has joined the channel [07:57] isaacs: kriskowal: http://github.com/isaacs/node/commit/42048068c7c12a0bf371fde30314b9b6f10cfeb2 [07:57] kriskowal: neat [07:57] kriskowal: i hope my stuff gets pulled too [07:58] elliottcable: wat [07:58] elliottcable: what’d I miss? [07:58] isaacs: elliottcable: i just added a require.setExport() function that doesn't unsecure securable modules. [07:58] kriskowal: module.setExports [07:58] isaacs: singular. [07:58] kriskowal: oh. [07:58] kriskowal: that's confusing [07:58] isaacs: but i guess it should probably be exportS, huh? [07:58] isaacs: yeah. [07:59] isaacs: debating over the name is always the last thing i do, so i try to write the code first. [07:59] kriskowal: sounds like a good plan. [07:59] isaacs: ACTION changing... [07:59] isaacs: and this way, we remove the reference to the module object from the module code. [08:00] kriskowal: i study with kurremkarmerruk [08:00] isaacs: kriskowal: is that some kind of martial art? [08:00] kriskowal: no, literary reference. my gift to you. [08:01] kriskowal: and self-deprecating, really, in context. [08:02] isaacs: http://github.com/isaacs/node-playground/blob/master/kriskowals-gist/c.js [08:03] kriskowal: i've got four commits lined up. node.js argument injection, and factored node_static.cc and node_encodings.cc out of node.cc, and added a the framework for a narwhal entry point. [08:04] isaacs: sounds interesting. [08:04] kriskowal: aight, zzz time. [08:05] isaacs: g'nite [08:11] michaelk^ has joined the channel [08:33] johan-s has joined the channel [08:45] rtomayko has joined the channel [09:00] micheil has joined the channel [09:01] cmlenz has joined the channel [09:05] Nailor: http://twitter.com/defunkt/status/6656464604 :) [09:06] elliottcable: Nailor: http://tau.pe/ that shit, I say [09:26] teemow has joined the channel [09:38] fynn has joined the channel [09:38] fynn: Yo, is it possible to harness Worker threads under in node.js? [09:39] elliottcable: fynn: what, exactly, do you mean? [09:40] fynn: elliottcable: using something like Worker threads, in node.js.., :) [09:40] fynn: for example, say I have an intense calculation [09:41] fynn: elliottcable: if there's support, I can start a Worker thread to perform that calculation in the background, while the main application keeps responding to requests. [09:41] fynn: then the Worker-thread would call back with the result. [09:42] bry has joined the channel [09:42] elliottcable: Are you talking about server-side, in Node itself? Or client-side, somehow relating to Node.js? [09:42] elliottcable: server-side, AFAIK, there was prelim support for ‘server-side workers’ implemented a version or two ago, though I haven’t used it. [09:42] elliottcable: client-side, that’s irrelevant to Node.js, really. [09:43] fynn: elliottcable: yes, talking about the server, the machine responding to requests. [09:43] fynn: (the clients already have support independently of node.js) [09:44] elliottcable: yes, I wasn’t sure. We ocassionally see questions irrelevant to Node.js in here, forgive me for assuming the worst (-: [09:45] elliottcable: fynn: well, I’m certain ryah has plans for that; somebody had mentioned that 0.1.21 had such functionality, but I can’t find it for you right now. Either way, it’ll be here soon. [= [09:47] elliottcable: hah. [09:47] fynn: elliottcable: http://github.com/cramforce/node/blob/master/lib/worker.js [09:48] elliottcable: Bluebie’s swearing at me that she saw `require('workers')` the other day; but it’s not in ry/node/tree/master/lib/ [09:48] fynn: and http://groups.google.com/group/nodejs/browse_thread/thread/25f43e73b8efd7f3/14368bfd29faecf9?lnk=gst&q=web+workers#14368bfd29faecf9 [09:48] elliottcable: ahhah! fork’d. Well, you beat me to it (-: [09:48] fynn: yeah, just not sure after reading all that what's the official support status of it :) [09:55] elliottcable: “Not implemented yet.” [09:56] fynn: elliottcable: right, but can one just take that library and use it? [09:56] elliottcable: I’m guessing no. [09:56] fynn: i.e. "require('worker')"? [09:56] fynn: hm, why not? [09:56] elliottcable: If @ryah hasn’t cherry-picked it yet, I suspect he will want to change the API, possibly heavily, when he does [09:56] fynn: it requires changes in the underlying VM then? [09:56] fynn: the node.js vm that embeds V8? [09:57] elliottcable: o_O no? [09:57] elliottcable: I doubt it, anyway. [09:58] elliottcable: I mean the API that *you* use. If you’re not afraid to rework your code when ryah officially merges it, I see no reasons not to use it now. [09:58] richardb has left the channel [09:58] fynn: elliottcable: cool, so it is just "require('worker')" :) [10:00] elliottcable: ACTION stabs NginX [10:00] Connorhd_ has joined the channel [10:04] scudco has joined the channel [10:05] fynn has left the channel [10:12] hassox has joined the channel [10:22] mahemoff has joined the channel [10:29] malkomalko has joined the channel [10:34] webben has joined the channel [11:04] micheil has joined the channel [11:21] malkomalko has joined the channel [11:51] sveimac has joined the channel [11:53] the_undefined has joined the channel [12:02] soveran has joined the channel [12:07] micheil has joined the channel [12:19] olivvv has joined the channel [12:23] hassox: hullo [12:24] hassox: anyone about and up for a chat on stacking components together? [12:24] sveimac has joined the channel [12:35] martyn_: @hassox sounds interesting [12:35] hassox: hey martyn [12:35] hassox: just getting a pic of what I mean [12:37] hassox: http://skitch.com/hassox/nmx9q/stackedapps [12:37] hassox: k [12:37] hassox: so martyn_ [12:38] hassox: my question is, is it better to use events to trigger the next piece of the request [12:38] hassox: so that each part stops execution at each boundary [12:38] hassox: or is it better to run it straight through and only use async stuff internally if required? [12:39] martyn_: are you thinking of some kind of chain of processing on the input? [12:39] hassox: both on the input and the output [12:40] hassox: so you can process it on the way in through a chain... and then again on the way out [12:40] martyn_: probably the simplest pattern is to use a chain of deferrables [12:40] hassox: I've been reading up on those [12:40] hassox: ACTION is a bit of a n00b at js [12:40] hassox: :( [12:40] alex-desktop has joined the channel [12:41] hassox: so how would using chaned deferrables be different to this? [12:41] hassox: deferrables are based on callbacks also right? [12:41] hassox: so each piece is run in sequential loops through the event loop yes? [12:42] martyn_: exactly - they're just a specialized type with only on success and on error events [12:42] hassox: I guess that's the heart of my question [12:42] martyn_: most problems seems to work well with just those, and if you can use a convention for the events it simplifies code a lot [12:42] hassox: is there an issue doing that? [12:43] hassox: I guess the main thing I'm wondering [12:43] hassox: is, if there are many many concurrent request coming through [12:43] hassox: does that make each request take a relatively long time? [12:44] martyn_: I wouldn't worry that events make things slow - you're _supposed_ to use them and the event loop makes it very fast [12:44] hassox: sorry not quite what I mean [12:44] hassox: events are cool [12:44] hassox: I'm wondering if I have the setup in the pic (or deferrables) [12:44] hassox: and say I have 1000 concurrent requests [12:45] hassox: does that mean each request will take 1000 times as long? [12:45] hassox: all requests being equal [12:45] hassox: sorry if these are the wrong questions [12:45] hassox: trying to wrap head about this [12:45] martyn_: well if you're cpu bound then yes, but the usually you'd use node if you're io bound [12:45] martyn_: not at all! [12:46] hassox: and u'd be io-bound from files / db / external services? [12:46] martyn_: Another interesting question which I'm still trying to answer is how to write maintainable code with lots of asynchronous steps - without getting into callback hell [12:46] hassox: yeah [12:47] hassox: it's not simple, but it so tantilising [12:47] hassox: ;) [12:47] martyn_: This is a ruby experiment I was playing with http://github.com/mloughran/noodler/ [12:47] hassox: so... when a request comes in and there's a bunch of callbacks added [12:47] martyn_: I think I remember you from merb days? [12:47] hassox: indeed [12:47] hassox: :) [12:47] hassox: glad to see another rubyist :) [12:48] hassox: so if there's a bunch of callbacks [12:48] hassox: and then there's an error and a response is returned [12:48] martyn_: I'm not calling myself a javascritist yet ;) [12:48] hassox: do the callbacks prevent the GC from picking it up? [12:48] hassox: :) [12:49] martyn_: yes [12:49] hassox: hrm so you've gotta try and remove all the callbacks [12:49] hassox: or [12:49] hassox: use js as a functional language [12:49] hassox: with long standing callbacks and state passed as args [12:50] hassox: ? [12:50] martyn_: Well eventually you loose the reference to the promise (deferrable) [12:52] hassox: thanx martyn_ [12:52] hassox: I've gotta get going but I appreciate the chat [12:53] martyn_: I don't understand the details internally, but my understanding is that once the event has fired the callbacks are ran and then you're done [12:53] malkomalko_ has joined the channel [12:53] martyn_: yes good talking to you [12:54] malkomalko__ has joined the channel [12:55] malkomalko___ has joined the channel [12:56] malkomalko____ has joined the channel [13:12] michaelk^ has joined the channel [13:13] micheil has joined the channel [13:43] simoncpu: ei [13:43] simoncpu: http://6node.mooo.com.ipv4.sixxs.org/ [13:51] pmuellr has joined the channel [14:02] n8o has joined the channel [14:04] bryanl has joined the channel [14:05] jtaby has joined the channel [14:27] johan-s has joined the channel [14:27] erikcorry|away has joined the channel [14:27] voodootikigod has joined the channel [14:27] brandon_beacher has joined the channel [14:27] onar has joined the channel [14:27] mies has joined the channel [14:28] Sinjo has joined the channel [14:28] cloudhead has joined the channel [14:28] soveran has joined the channel [14:29] simoncpu has joined the channel [14:30] jbowman has joined the channel [14:42] malkomalko has joined the channel [14:46] webben has joined the channel [14:46] quirkey has joined the channel [14:57] lmorchard has left the channel [15:01] jtaby has joined the channel [15:02] alexiskander has joined the channel [15:05] Yuffster has joined the channel [15:05] the_undefined has joined the channel [15:06] soveran has joined the channel [15:06] the_undefined: ryah: I answered you on the mailing list, let me know what you think [15:07] Connorhd__ has joined the channel [15:08] dnolen has joined the channel [15:31] michaelk^ has joined the channel [15:42] quirkey has joined the channel [15:44] rolfb has joined the channel [16:02] binary42 has joined the channel [16:21] aurynn has joined the channel [16:24] rictic has joined the channel [16:24] sveisvei has joined the channel [16:42] Sembiance: :) [16:57] bentomas has joined the channel [16:57] jazzychad: hi all [16:57] Sembiance: yo jazzy chad :) [16:57] jazzychad: i've just pushed a templating module to github [16:57] jazzychad: http://github.com/jazzychad/template.node.js [17:02] sztanpet: seems familiar [17:02] sztanpet: http://github.com/jed/tmpl-node [17:04] jazzychad: oh... darn.. [17:05] jazzychad: well, good exercise anyway :) [17:06] sztanpet: now you just need to write a web framework :D [17:07] jazzychad: well, i know those exist already :) [17:08] soveran has joined the channel [17:08] sztanpet: theres a few :D [17:08] jazzychad: yes [17:08] jazzychad: i've linked jed's tmpl-node to the wiki so other's don't repeat my actions [17:08] jazzychad: *the node wiki [17:08] aurynn: woo, templating [17:09] soveran has joined the channel [17:11] jazzychad: i also did a console logging module, which hopefully was not done before... [17:11] jazzychad: http://github.com/jazzychad/consolelog.node.js [17:15] scudco has joined the channel [17:16] johan-s has joined the channel [17:18] jtaby has joined the channel [17:18] dnolen has joined the channel [17:25] aguynamedben has joined the channel [17:26] JimBastard: sup jazzychad [17:26] JimBastard: good works man [17:26] JimBastard: hang around here and the mailing list and you'll get an idea of what other people are working on [17:26] jazzychad: yeah... i need to do that. i just started hacking on node in the last week [17:27] JimBastard: mustache.js is currently the best templating solution imho [17:27] JimBastard: ive been working on a web console debugger maraksquires.com/node_debug/ [17:27] JimBastard: there is a shitty screencast up, new version coming soon [17:27] aurynn: so I got an idea on how to handle my .close/.commit/.rollback statements [17:28] aurynn: look for a new postgres-js from me soon. [17:28] aurynn: :) [17:28] jazzychad: cool [17:28] jazzychad: where is mustache? [17:30] mediacoder: jazzychad: http://github.com/janl/mustache.js [17:30] jazzychad: mediacoder: thx [17:30] mediacoder: there might be an optimized version in express [17:30] jazzychad: JimBastard: ah, i think i saw node_debug on hacker news, yes? [17:32] mattly has joined the channel [17:32] Connorhd: JimBastard, adding anything interesting to the next version? [17:35] qFox has joined the channel [17:41] jazzychad: are there any current solutions for a webframework with something like redis-backed user sessions? [17:44] JimBastard: jazzychad there is session code floating around [17:44] JimBastard: and the session code has a stub for seralizization to disk / db [17:45] JimBastard: Connorhd mostly style updates / snippets / session tracking / and auth support [17:45] JimBastard: ill be adding new features as i need them for my front-end app [17:45] RayMorgan has joined the channel [17:46] jazzychad: hmm, http://github.com/Miksago/node.js-sessions perhaps [17:48] JimBastard: i would recommend inimino's [17:48] JimBastard: http://github.com/Marak/session.js [17:48] JimBastard: i havent cleaned it up / promoted it / blogged about it yet [17:48] JimBastard: but its solic [17:48] JimBastard: solid [17:48] jbowman: http://github.com/mediacoder/node-sessions has different storage backends, found it over the weekend [17:49] JimBastard: snall, easy to use [17:49] JimBastard: http://github.com/mediacoder/node-sessions/blob/master/session.js looks just like iniminos [17:49] JimBastard: kinda [17:49] JimBastard: it would be nice to consolidate all the session code [17:50] jbowman: I'm also working on one, but for an app so not really writing it to function as a real pluggable library.. it uses memcached as a backend using node-memcache, still real early in development [17:51] jbowman: only reason i'm writing my own is I still haven't found any publically released one that has rotating session tokens, so they're all pretty much replayable if you're on the same NAT as your victim if you're trying to spoof [17:51] jbowman: except for https encrypted cookies of course [17:52] jazzychad: hmm interesting [17:52] jazzychad: it does look like mediacoder's allows for custom sotrage modules... i could write a redis one [17:52] inimino: that is a feature I should add [17:53] mediacoder: jbowman: my implementation is far not done and currently i have not much time unfortunately [17:53] JimBastard: ill be working on the session code a lot in the upcoming weeks [17:53] JimBastard: im trying to find the right balance of application development versus framework development [17:53] mediacoder: kool.. ill keep watching the different approaches [17:54] JimBastard: you gotta be careful not to get too unbalanced or nothing will get done [17:54] jbowman: oh, sorry for linking to it then mediacoder... I didn't get a chance to plug it in or play with it [17:54] mediacoder: yea, same here.. i just needed very basic sessions, which work for me, thats why currently the "modulisation" is on hold [17:54] JimBastard: Connorhd have you looked into setting up breakpoints at all? ive been discussing it a bit with some people, i think some C modifications will have to be one [17:54] JimBastard: be done [17:54] mediacoder: hehe, np .. if i feel something to be used publically id post it to the /Home on node :-) [17:54] JimBastard: and possible running your app with --debug [17:55] mediacoder: atm its on your own risk :-P [17:55] jbowman: I'm bouncing between working on my approach to sessions in node.js, and working on Jsondra... and bouncing between python and javascript is giving me a headache [17:55] JimBastard: eeeek [17:55] inimino: jbowman: git://boshi.inimino.org/sessions/ is mine [17:55] Connorhd: JimBastard, of course, you can't do it in javascript as the server won't work while you're at a breakpoint [17:55] aurynn: I need to start thinking about exceptions and try/catch in JS. [17:55] inimino: it also doesn't do serializing or rotate SIDs [17:56] JimBastard: Connorhd i guess the idea would be to only freeze up the one thread / request which is on a breakpoint [17:56] JimBastard: not the entire server [17:56] inimino: and I also haven't had a lot of time to work on it [17:56] zimbatm has joined the channel [17:56] Connorhd: node only has one thread though? [17:56] zimbatm: hi [17:57] JimBastard: this is where i lack a bit of knowledge [17:57] JimBastard: im not too familiar with the C side of node [17:57] zimbatm: Connorhd: I think so [17:57] jbowman: Well, using memcached as a backend which is just a key/value hash store at best. I'm taking the same approach I did for sessions on appengine for the gaeutilities project. [17:57] Connorhd: zimbatm, not really a question ;) [17:57] Connorhd: JimBastard, have you looked at the v8 debugger stuff? [17:57] aurynn: json serialization of sessions would be pretty easy [17:57] JimBastard: not really..... :-\ [17:57] JimBastard: ive been meaning to though [17:57] mediacoder: jbowman: yea, i have a memcache storage module, using my node-memcache client (which is also maybe borked a bit :-)) [17:57] zimbatm: Connorhd: no, I mean nodejs is one thread [17:58] jtaby has joined the channel [17:58] Connorhd: zimbatm, I know, I wasn't really asking that question, it was in response to something said before you joined [17:58] zimbatm: oh.. [17:58] JimBastard: if i had a solid approach to making breakpoints where i could try to implement it, but i still havent figured out how i would do it [17:59] jbowman: SID = static, Token = changing. Use the SID for the key, then keep the token as an array inside the session data. Compare the token you get from the cookie with what's in the array to validate it. I found a 5 second lifetime on a token, with keeping 3 as valid, gave about 15 second lifespan on any token while allowing multiple async requests to still work. [17:59] JimBastard: that was almost a setnence [17:59] Connorhd: use the v8 stuff for it I think [17:59] jbowman: mediacoder: your memcache module is the one i'm using, huge time saver, thanks :) [17:59] Connorhd: I think ry did look into it a bit before, not sure how far he got though [17:59] JimBastard: he sent me to the v8 debugger docs [17:59] mediacoder: jbowman: i think the sid should be regenerated on every request.. this isnt currently working on my implementation [18:00] JimBastard: honestly id rather focus on UI myself then the server aspects, but i do want the functionality [18:00] JimBastard: i guess i gotta setup a v8 env [18:00] JimBastard: with the debugger and a c compiler [18:01] jbowman: mediacoder: I tried that way back when with gaeutilties session. I found that adding tokens to the mix, while keeping the sid static, made things much more manageable, and also translated better to different backends. [18:01] zimbatm: I wish sys.inspect on a function would give file and line number instead of [Function] [18:02] mediacoder: jbowman: currently im using the sid as a key, that way storage mdoules can retrieve the session-data. how would you request the data based on a token? [18:03] zimbatm: I implemented WebSocket on top of the http.Server but it's hard to debug with all those events [18:03] jbowman: mediacoder: store both the sid, and the token, in the cookie. Either as separate cookies (_mysid, _myst) or one cookie _mys={"_mys": "session id", "_myst": "token"} [18:04] mediacoder: jbowman: hm, i dont udnerstand the benefit from that (instead of saving just the random fresh sid) [18:04] jbowman: mediacoder: get the cookie by sid, then validate it by the token [18:04] mediacoder: ah, i see [18:05] jbowman: mediacoder: a brower could make multiple connections at about the same time to your server depending on your front end code. So you keep the sid static, and multiple tokens. That way if one request sets a new token, before the other request uses it for validation, both requests can still work. [18:06] mediacoder: yea.. now i got it :-) [18:06] inimino: JimBastard: it will require some support from v8/node [18:07] eddanger has joined the channel [18:07] jbowman: mediacoder: the security benefit is say you have 3 tokens allowed with a 5 second lifetime for each. You got about 15 seconds to sniff and use those cookies to hijack a session. It could probably be lower, I just haven't had time to fine tune it. [18:08] inimino: JimBastard: I suspect you would need to create a new execution context in v8 and run the web-facing part of the debugger there while the JavaScript context that is being debugged is at a breakpoint [18:08] mediacoder: yea, that makes much sense.. also makes storage easier, cause you dont have to chenge the key frequentl [18:08] mediacoder: y [18:09] jtaby_ has joined the channel [18:09] inimino: jbowman: 15 seconds is more than enough, though [18:10] jbowman: It worked great on appengine, except that I needed to use bigtable for the backend because the memcache on appengine isn't reliable. And, bigtable for appengine is pretty unreliable too. I think others had some luck with it, but my app was just too heavy over all and I ended up dropping it to write my own elsewhere (hence my interest in node.js) [18:10] inimino: jbowman: I'm not sure I understand yet why this is a security benefit [18:10] jbowman: inimino: Yea, probably 1 or 2 seconds would suffice, I just never got around to tweaking it. [18:12] jbowman: inimino: Say you and I are at a coffee shop, so when we hit a website, we both have the same IP. All I need to do is sniff your http requests to get your user agent, and the cookie data which includes your sid. I spoof your user agent, set the cookies as my own, I now have control over your session. [18:12] JimBastard: yep [18:12] JimBastard: he's only using one id right? [18:13] JimBastard: i think you need token / key [18:13] jbowman: inimino: the sessions token create an extra layer, where at some point even if you do manage to hijack in the window where the token is usable, at some point the tokens will diverge and your victim will either be logged out, or you will be. [18:13] JimBastard: the idea is one persists and one changes every request right? [18:14] JimBastard: one persists per session, one persists per request? [18:14] mediacoder: yea [18:14] JimBastard: i was talking about this before [18:14] JimBastard: voodootikigod was talking about node's built in session stuff too [18:14] jbowman: JimBastard: not every request... I tried that a while back and found that it breaks heave ajax based sites. So you allow the token to exists x amount of time, and keep x amount of back tokens that can still validate. [18:14] JimBastard: at nyc.js [18:14] JimBastard: got ya [18:15] jbowman: *breaks heavy [18:15] JimBastard: im pretty sure coldfusion works like that [18:15] JimBastard: with cfid and cftoken [18:15] JimBastard: which are glorified J2EE sessions [18:15] the_undefined has joined the channel [18:16] inimino: jbowman: so what you're describing doesn't defend against the attack? [18:17] jbowman: Most opensource solutions i've seen ( for python, which is what i writing in at the time ) really only session id's, no form of token. A lot of hashing to secure the value of the cookie, but not the cookie transport itself. [18:17] jbowman: inimino: It deters the attack. You have x seconds to sniff and use the cookie before it's not valid anymore [18:17] inimino: jbowman: I can still hijack your session, right? [18:17] inimino: I'm not sure it's worth adding complexity to the session code just for that [18:18] jbowman: inimino: Also, after x amount of seconds, once you are in... the token rotation will break for one or both clients (as tokens only get written to the browser once, key security point for any coding this solution btw) [18:18] JimBastard: its a good deterant [18:18] inimino: my opinion is that if session hijacking is a concern SSL should be used [18:18] JimBastard: agreed [18:18] JimBastard: also, if you have enough things seeding the hash it helps as well [18:19] JimBastard: creating a session "fingerprint" [18:19] jbowman: inimino: agreed 100%, I primarily wrote this for appengine, where ssl wasn't an option at the time [18:19] JimBastard: hijacking non-ssl sessions would be pretty easy [18:19] JimBastard: quick sniff and cookie edit [18:20] jbowman: inimino: but, I also know the overhead ssl can create on a server, so am working on a similar solution for my node.js app, and I don't want to ssl encrypt everything [18:20] JimBastard: most web apps are like that though [18:21] jbowman: I also have found that writing session libraries is a great way to learn a web framework and language. And my javascript is admittedly pretty weak. I learned python writing the stuff for appengine, so why not learn javascript/node.js the same way :) [18:22] inimino: :) [18:23] inimino: I always recommend http://eloquentjavascript.net/ [18:23] inimino: ACTION should try to plug that more often in this channel [18:26] jbowman: inimino: bookmarked... O'Reilly releases some of their books for Android, and I've been reading Douglas Crockford's Javascript: The Good Parts in my spare time. [18:26] jtaby has joined the channel [18:26] inimino: Crockford has some funny ideas but some good ones too [18:28] jbowman: Right now I'm just noticing that a lot of stuff I am currently doing seems to be do something that does a callback that does a callback that does a callback... and sometimes things get lost in scope. But I'm slowly figuring it out. Bouncing back and forth back to python while I work on Jsondra isn't helping me much either. [18:41] sudoer has joined the channel [18:47] rolfb has joined the channel [18:53] jed_ has joined the channel [18:57] rbranson has joined the channel [19:02] jazzychad: mediacoder: where/what is that crypto module you have in your session manager code? [19:03] ericflo has joined the channel [19:03] mediacoder: jazzychad: its node-crypto http://github.com/waveto/node-crypto [19:03] jcrosby has joined the channel [19:04] jazzychad: mediacoder: thx. [19:05] quirkey has joined the channel [19:05] mattly has left the channel [19:05] mediacoder: np [19:11] aurynn: we need something like CPAN. [19:13] ericflo has joined the channel [19:14] mediacoder: aurynn: there was something started called node-package-manager (npm) not sure about its status tho [19:14] jazzychad: mediacoder: so to use this in my app is something like: var sessions = require("./path/to/session_manager"); [19:14] jazzychad: and then something like: var sess = new sessions.Session_Manager({}); [19:14] aurynn: mediacoder, it definitely needs to be worked on :) [19:16] mediacoder: jazzychad: http://pastie.org/742992 [19:16] mediacoder: but as i said..its very experimental and tied a bit to my app [19:16] saikko has joined the channel [19:17] teemow has joined the channel [19:17] jazzychad: ok, cool. thanks for the paste [19:17] isaacs has joined the channel [19:18] mediacoder: feel free to fork and fix/improve :-) ill have time in a few days and aroud christmas to work more on the projects :-) [19:18] jazzychad: i'll see what i can do :) [19:18] ericflo has joined the channel [19:26] nefD: hrm.. if (using apache and .htaccess) I want to redirect a request to a given file/folder to a different address (in this case, a diff. port on localhost, where a node server would be running), what would the .htaccess rewrite rule look like? [19:27] Connorhd: RewriteRule ^(.+)\.htm$ http://corz.org/$1.php [R,NC] [19:27] Connorhd: (with a quick google) [19:28] nefD: ah, thanks! [19:29] rictic has joined the channel [19:29] nefD: i'm guessing I can specify a specific port after the target (.php) address, as well? [19:29] Connorhd: that would be RewriteRule ^(.+)\.htm$ http://corz.org:8080/$1.php [R,NC] [19:30] Connorhd: where 8080 is the port [19:30] nefD: suweet [19:30] nefD: thanks muchly [19:30] nefD: i googled as well but I suspect I either overlooked the answer or used the wrong keywords [19:32] jbowman: http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html -I'd just read through it, rewrite is an awesome tool [19:33] inimino: +1 to reading the docs [19:33] the_undefined_ has joined the channel [19:34] nefD: hrm.. actually, I dont think this method will help with my 'same origin policy' dillema.. [19:35] jbowman: ah.. for that you want apache to proxy [19:35] nefD: looks like what I actually need is to proxy [19:35] nefD: yea [19:35] jbowman: http://httpd.apache.org/docs/2.2/mod/mod_proxy.html [19:36] jbowman: apache can do anything... it's the swiss army knife of web servers... proxybalancer is pretty cool too [19:36] jbowman: as a sysadmin I've solved more problems with apache, that probably should have been solved with code, than I can count :p [19:36] nefD: hehe [19:37] nefD: i'll be using JSONP for the majority of my back-and-fourth.. but theres a few areas where i'd prefer to keep a persistant (long polling, i spose) connection, which is where the proxy would be needed [19:37] nefD: does using mod_proxy slow down the request/result process? [19:37] jbowman: squid is turning into the 2nd tool of choice (it's great for ldap authentication against active directory for example) [19:38] jbowman: Depends on the load.. technically, yes, there is a slow down because apache will need to make a new connection to the server it's proxying... Also, don't think it will help you with long polling. Check out nginx [19:40] jbowman: We use apache proxies in front of our google search appliances, using proxy balancer as an automatic failover system, and have never had an issue with performance problems introduced by this setup... however, there's not a ton of search requests per day either [19:40] nefD: hrm [19:41] nefD: i bet i could use a php script as a go between [19:41] jbowman: nginx can emulate long polling to even simple apache processes now... haven't played with it myself, but looks interesting. http://www.igvita.com/2009/10/21/nginx-comet-low-latency-server-push/ [19:41] nefD: ah cool, thanks for the linkage [19:42] jbowman: you'd more than likely put nginx in front of your apache and node.js servers, having it proxy both. Simplest solution. [19:44] nefD: it appears as though I can do long polling with JSONP, so I might be ok without needing to proxy at all [19:45] nefD: although, jsonp is certainly less secure [19:49] erichocean: one hundred members on IRC [19:50] erichocean: ACTION makes me happy [19:50] jbowman: awesome... and they were taking bets yesterday when you all would reach it... congrats [19:51] alexiskander: erichocean: might want to turn off "Detect natural language actions"... unless you really do make yourself happy :) [19:52] jbowman: I guess with all the talk about changes for promise vs. deferred, I should put more time on the server portion of jsondra, and come back to the client after that's all worked out, huh? [19:54] inimino: jbowman: the changes from an API user perspective aren't likely to be too huge [19:55] jbowman: I thought I read that the syntax would be backwards compatible, but would eventually move to using the deferred syntax instead of promise? [19:56] jbowman: oh wow... the threads been updated since I last read it [19:57] erichocean: has anyone proposed a better callback API that doesn't require closures? [19:57] erichocean: .notify("event", target, function) [19:57] erichocean: and then function.call(target) [19:57] erichocean: plus whatever args are needed [19:57] inimino: what do you mean? [19:58] erichocean: addListener("event", functionClosure) is what we use now [19:58] rictic has joined the channel [19:59] erichocean: I'd like to be able to pass in an object (the "target") and a function (the "action") and have it do action.call(target) instead [19:59] inimino: oh, you just want some kind of .bind [19:59] erichocean: that's exactly what I don't wan [19:59] erichocean: bind is stupid [19:59] inimino: get Function.bind from a library of your choice [19:59] inimino: why? [20:00] erichocean: because it's slow and wastes memory [20:00] isaacs: erichocean: you just described Function.bind [20:00] isaacs: ...slow and wastes memory? [20:00] erichocean: I described the behavior, not the implementation [20:00] RayMorgan: I think it would be a good idea to have: addListener('foo', func, [target]) [20:00] RayMorgan: where target is optional [20:00] isaacs: erichocean: but... that behavior is exactly what Function.bind does... [20:00] erichocean: if you do target-action style, you can also pass a string and then do target[action]() [20:00] alexiskander: isaacs: Function.bind does it in a closure [20:00] RayMorgan: it is the same, but way more efficient [20:00] alexiskander: a closure is not necessary [20:01] richtaur has joined the channel [20:01] isaacs: so... you want the addListener to do context setting for you? [20:01] isaacs: i'm not convinced that an extra function wrapper is expensive enough to justify making the api even a little less terse. [20:01] erichocean: yes, I think that it would be great if a variation was available that did that [20:02] erichocean: Ry should go for it; it's demonstrably faster at runtime and uses less memory [20:02] isaacs: erichocean: you have a demonstration of this? [20:02] erichocean: I'm one of the core developers of SproutCore [20:02] inimino: I think it's an edge case [20:02] erichocean: we test all this stuff [20:02] inimino: lots of people don't use 'this' at all, which I find much cleaner [20:02] isaacs: inimino: agreed. [20:03] isaacs: erichocean: well, that's nice. but i'm saying, on v8, in node, can you demonstrate that function.bind is noticeably slower? [20:03] erichocean: of course [20:03] isaacs: or even, just in raw v8? [20:03] isaacs: what's the %ge difference? [20:03] inimino: show benchmarks please :) [20:03] erichocean: between two function calls and one? [20:04] erichocean: seeing as functions are the slowest part of JavaScript, it's substantial [20:04] isaacs: ACTION suspects that the difference is around the "rounding error" level of relevance. [20:04] isaacs: erichocean: they're not, though [20:04] isaacs: with(){} is slower than function(){}, and I/O is the only relevantly slow thing in most systems. [20:04] inimino: no, they're not [20:04] inimino: that hasn't really been true for quite a while in most new interpreters [20:04] inimino: function call overhead is /extremely/ low [20:04] isaacs: on a web page, DOM is slower than almost anything else. [20:04] erichocean: no it's not [20:05] erichocean: value++ is far, far faster than val.incr() [20:05] isaacs: i'm not convinced that 1ms is "far far" faster than 2ms [20:05] inimino: ACTION would like to see some numbers [20:05] isaacs: especially when you're dealing with http and filesystem io. [20:05] erichocean: twice as fast? [20:05] isaacs: erichocean: maybe. [20:06] isaacs: or maybe your processor hiccuped. [20:06] erichocean: I'm not suggesting that we take away the current approach [20:06] isaacs: erichocean: you're suggesting that we add another argument to the addListener() signature. [20:06] isaacs: or another method that does the same thing, but differently. [20:06] inimino: by the way, Function.prototype.bind is in ES5 so it will be native at some soonish future point in V8 [20:06] erichocean: yep [20:07] erichocean: that doesn't really change anything re: what I'm asking for [20:07] isaacs: either of those are a cost in terms of API complexity. if it's truly "demonstrably faster", and a common enough use case that it's relevant, then i'd say maybe it's worth it. [20:07] erichocean: well, I can add it in my copy of node.js so this is all academic [20:07] inimino: it does, because it makes the performance argument even less compelling than it already was [20:07] isaacs: but a) i don't think the use case is all that common, and b) i don't think that the speed diff is enough to matter in this case. [20:07] erichocean: open source FTW [20:07] isaacs: erichocean: yes, please do. then provide a demonstration of your speed increase. [20:08] erichocean: dude [20:08] isaacs: if it's a relevant difference, and the community decides that it's a useful use case, it'll probably be accepted [20:08] erichocean: yeah, I'll get right on making that all happen [20:08] isaacs: open source FTW :) [20:09] inimino: ^.^ [20:10] isaacs: ACTION is not thrilled at the prospect of optimizing the 1% [20:14] jbowman: Where's the best place to find all the javascript functions that V8 supports? [20:14] inimino: the ES3 spec, plus the V8 documentation, plus the source? [20:15] isaacs: jbowman: that's a great question. [20:15] isaacs: i don't know of a single convenient list... [20:15] inimino: plus a few things from ES5 like JSON [20:15] jbowman: I was looking for the V8 documentation that covered that, and wasn't finding it. I checked - http://code.google.com/apis/v8/intro.html and am still googling. Did search before i asked :) [20:16] isaacs: you could check http://code.google.com/p/v8/issues/list to find out what it DOESNT support... [20:16] isaacs: (yet) [20:16] jbowman: isaacs: thanks [20:16] inimino: V8 allegedly has documentation but I gather it's pretty inchoate [20:17] isaacs: inimino: yeh, it sorta limps by by saying "we ape webkit, if webkit can do it, we can too" [20:17] inimino: yes, the JSC documentation would be good too [20:17] isaacs: and, to the v8 team's credit, when jsc can do something that v8 can't, it's a critical bug. [20:18] isaacs: if you want a feature added to v8, contribute to jsc [20:18] jbowman: sorry... jsc = http://jsc.sourceforge.net/ ? [20:19] erichocean: JavaScriptCore [20:19] jbowman: got it, thanks [20:19] erichocean: part of WebKit [20:19] isaacs: http://webkit.org/projects/javascript/index.html [20:19] isaacs: http://www.webreference.com/javascript/reference/core/ [20:19] isaacs: oh, wait, that's not for jsc... hehe [20:19] isaacs: that's a "how to learn javascript hurrrrr" [20:20] jbowman: yea, I got 2 sources for how to learn, now looking for reference material. :) Got those links bookmarked now, thanks [20:25] rakeshpai has joined the channel [20:25] rakeshpai: Hello, #node.js... clearly, we've breached the 100 mark [20:25] jazzychad: what's the best way to get the POST params/variables from an http.ServerRequest? seems like req.uri.params isn't it... [20:26] jazzychad: do I need to get the body and then just parse the string? [20:27] mikeal: yup [20:27] inimino: yes [20:28] jazzychad: bummer [20:29] aurynn: seriously? Need a lib for that. [20:29] jazzychad: yeah, that just seems.... clunky. esp since the query string is already parsed into uri.params for GETs [20:30] inimino: sure, it should be a lib [20:30] inimino: if someone hasn't already written it [20:31] inimino: parsing www-urlencoded-formdata is just .split('&'), .split('='), and decodeURIComponent() [20:32] rictic has joined the channel [20:38] isaacs: inimino: if only that was it. [20:38] isaacs: i have a lib for that. i wrote it for narwhal and yui. [20:38] cmlenz has joined the channel [20:39] inimino: hm, Firefox has a direct Unicode input mode, who knew? [20:40] isaacs: jazzychad: imo, node shouldn't be giving you uri.params. [20:40] isaacs: that's a job for a higher-level lib. and node's query string parsing is laughably bad. [20:40] isaacs: ?foo&bar&baz ==> no params [20:40] jazzychad: hmm [20:41] jazzychad: i just wrote a quick and dirty "handlePOST" function which listens for all body chunks and then parses it out on "complete" [20:41] isaacs: that's clever. [20:41] rakeshpai has joined the channel [20:41] isaacs: i'll wrap up my querystring parser tonight for node. [20:42] jazzychad: http://pastie.org/743119 [20:42] isaacs: if you wanna get it now, though, take a look in narwhal, or http://github.com/isaacs/yui3/tree/master/src/querystring/js [20:42] jazzychad: cool thanks [20:42] isaacs: you'll need to remove the Y.stuff, of course. [20:43] jazzychad: right [20:44] jtaby has joined the channel [20:45] inimino: I have an API that can return either a successful or unsuccessful result [20:46] isaacs: inimino: if only node provided some kind of paradigm for objects that can either emit success or failure... ;P [20:46] inimino: I'm returning [true, ] or [false, ] [20:46] inimino: isaacs: it's synchronous :-) [20:46] isaacs: yikes, ok [20:47] inimino: just wondering if anyone has seen an API like that before [20:47] quirkey has joined the channel [20:47] isaacs: inimino: doesn't sound like a bad expression of success/failure. [20:47] inimino: an API with a return value like that [20:47] inimino: I use it extensively internally but have never exported an API like that before [20:47] inimino: alright [20:48] isaacs: hm... why not { success : true, data : {blerg} } or { success: false, data : {blorp}} [20:48] isaacs: or even return a new Error("message") on error, so that you'll get a stack trace. [20:48] inimino: I'll probably have a throwing version of the API too [20:49] inimino: but a stack trace isn't likely to be useful to the caller [20:49] isaacs: i see [20:50] isaacs: i generally prefer returning an object if it's just a "bag o data" kind of thing [20:50] jbowman: question, what, if any database calls should be synchronous? ie: for jsondra should it be result = jsondra.get("key"). or something more like r = {}; jsondra.get("key", function(result) { r = result; }) [20:50] isaacs: in js, arrays sort of imply a list of somewhat like items. [20:50] jbowman: and then something similar for put and delete? [20:50] inimino: I'm not sure, the {success:, data:} seems a little heavyish [20:50] isaacs: jbowman: make it async. [20:50] isaacs: inimino: it looks heavier, but from the pov of the interpreter, it's actually not. [20:50] inimino: isaacs: basically what I want is a tagged union [20:51] isaacs: consider this: return {0:true, 1:{blerg}, map:function...., reduce:function..., length:2, ...} [20:51] inimino: isaacs: sure, I mean more from a syntactic perspective [20:51] inimino: I guess it's not much of a big difference [20:51] isaacs: right [20:51] isaacs: no, it's not a big diff at all. [20:51] isaacs: i just feel like doing [true, data] is less javascripty [20:52] isaacs: trying too hard to be lisp or python at that point. [20:52] isaacs: it's an aesthetic question. all the practical concerns are extremely minor. [20:52] inimino: well, {0:true; 1:blerg; __proto__:...}, but yeah [20:52] inimino: hm, ok [20:52] inimino: right [20:52] inimino: I was looking for an aesthetic reaction, now I guess I'll ponder that :) [20:53] isaacs: { ..., length : { getter: function () { for var i in this...}}}} [20:53] isaacs: hehe [20:54] jbowman: so ( sorry, still wrapping my head around this programming methodology)... jsondra.get("key"), callback) doesn't really make it async... the proper thing to would have jsondra.get("key") fire an event that can be listened to such as "complete" which would also pass the returned value to the method configured as a listener? [20:54] isaacs: we had that discussion at length in #narwhal and #commonjs over moving from return [200, headers, body] to {status:200, headers:{}, body: body} [20:54] isaacs: jbowman: yes! [20:54] inimino: length is O(1) ;-) [20:54] inimino: ah, interesting [20:55] isaacs: jsondra.get("key").addCallback(function (data) { doSomething(data) }).addErrback(function (err) { fail! }) [20:55] isaacs: then jsondra.get returns a promise [20:55] aurynn: Promises are nice. [20:55] isaacs: jsondra.get = function (key) { var p = new process.Promise; somethingAsync.addCallback(function () { p.emitSuccess(data) }); return p } [20:56] isaacs: if you WANT it to be sync, you can then do var data = jsondra.get("key").wait(); [20:56] isaacs: but the lib itslef shouldn't force you to be sync, since i might have 1000 keys to look up, and i'd rather not wait for all of them. [20:57] jazzychad: jbowman: you could take a look at the redis module... it works async that way [20:58] jbowman: awesome.. looks like I got some tests to code against now. Thanks! [20:58] dnolen has joined the channel [20:58] malkomalko has joined the channel [20:58] jazzychad: hooray, i finally got POSTs, Nerve, Sessions, and Redis modules glued together to start this toy webapp i want to make [20:59] jazzychad: oh, and templates [21:01] rtomayko has joined the channel [21:02] jazzychad: my goal is to use 100% non-{apache, php, mysql} to crate it.. only keeping the L in LAMP. Seems like it will be quite doable [21:04] jbowman: I'm going for the 100% horizontally scalable approach myself. tornado or node.js (still leaning towards node.js) behind a load balancer to run multiple instances, memcached for caching and sessions storage, and cassandra for persistent storage. [21:05] jbowman has left the channel [21:06] jazzychad: cool.. i've been messing with tornado as well [21:13] JimBastard: tornado is pretty good if you need to implement a lot of protocols [21:16] ericflo: if you need to implement a lot of protocols, you really can't beat Twisted [21:19] JimBastard: errr you are right ericflo i always mix those two up [21:19] JimBastard: durrrr [21:19] ericflo: :) [21:27] jtaby has joined the channel [21:35] logicuce has joined the channel [21:38] bryanl has joined the channel [21:41] trevor has joined the channel [21:54] sudoer has joined the channel [22:02] micheil_ has joined the channel [22:02] erichocean: jazzychad: this fixes a startup bug in the redis client: http://pastie.org/743235 [22:02] erichocean: feel free to get it back into the main distro, just haven't had a chance yet [22:04] JoePeck has joined the channel [22:04] jazzychad: erichocean: ah, thank you [22:07] kriskowal has joined the channel [22:07] jazzychad: erichocean: what does this fix, exactly? [22:07] erichocean: there's a race condition at startup [22:08] erichocean: because any redis call will do an implicit connect call [22:08] jazzychad: ah yes, i noticed that [22:08] erichocean: and because the 'opening' state was not handled, multiple event listeners would get added [22:08] jazzychad: there also seems to be some weird connection tear-down stuff... need process.exit(0) to 'force' quit [22:08] jazzychad: is that related? [22:08] erichocean: which then screwed up the response handling, causing it to process each response twice (but the buffer pointer would move, so it was all screwed up) [22:08] jazzychad: oh nice [22:09] erichocean: jazzychad: I haven't see that, but I always use exit() [22:09] erichocean: are you catching signals now? [22:09] RayMorgan_ has joined the channel [22:10] jazzychad: not really... i just noticed my app would 'hang' after everything was done. i looked through the redis test.js file and saw it was forcibly exiting when everything was done [22:10] erichocean: http://pastie.org/743254 [22:10] erichocean: that's what I do [22:11] jazzychad: i see [22:11] erichocean: the fsync() call is for a group commit I do against redis, so that no matter how many connections I have, they can all "commit" together [22:11] jazzychad: the redis client would also throw an error on .close(), so i got frustrated [22:11] jazzychad: ah ok [22:11] erichocean: I'm getting about 1000/req sec with group commit on, twice that with it off [22:12] erichocean: yay for node.js [22:12] jazzychad: yeah, it's awesome [22:12] erichocean: are previous push server did all of this in C, using many of the same libraries node uses [22:12] aurynn: 1k req/sec? not bad. [22:12] aurynn: :) [22:12] erichocean: those are persistent too, with a full fsync to disk [22:13] erichocean: redis is pretty nice [22:13] jazzychad: yeah, i just started learning about redis last night. impressive. [22:14] erichocean: that's fsync: http://pastie.org/743264 [22:14] erichocean: and the previous pastie shows how to use it [22:14] erichocean: so when a connection comes in, do all you redis work, and before you send req.finish(), wrap it in the fsync callback [22:15] erichocean: you'll be guaranteed to have everything committed at that point [22:15] erichocean: the 50ms is tunable [22:15] erichocean: so turn off fsync and benchmark [22:15] erichocean: whatever your 50% average request time is, set the fsync interval to that [22:15] erichocean: eventually, I'd like to have it tune itself dynamically [22:16] erichocean: storage is my connection to redis [22:16] ryah: everytime i login here there are more people.. 103.. [22:16] erichocean: http://pastie.org/743268 [22:17] jazzychad: erichocean: cool, thanks for those [22:17] jazzychad: ryah: yeah, seems to be growing :) [22:18] jazzychad: gotta go for a bit... meeting w/ a developer friend. spreading the word about node :) [22:18] ryah: kriskowal: haven't had a chance to look at your patch yet, but i will tomorrow or the next day [22:18] kriskowal: np. it's not burning. [22:19] kriskowal: let me know if they're not consistent with your direction. [22:19] ryah: isaacs: haven't had a chance for your patch either [22:19] kriskowal: and they progress from benign to perhaps more contentious with the last one. [22:19] isaacs: ryah: wait what? [22:19] isaacs: which one? [22:19] ryah: uri parser? that wasyou or ? [22:19] isaacs: oh, yeah, that was me [22:19] mikeal has joined the channel [22:19] kriskowal: i'm trying to work my way up to providing a narwhal engine. [22:20] erichocean: ryah: how can I write a custom C++ function to send data on a tcp.Connection object (that I call from JavaScript)? [22:20] isaacs: i also sent an idea to commonjs and nodejs today to talk about require.setExports() [22:20] erichocean: the Send() member function is protected [22:20] erichocean: for now, I just extended connection directly [22:20] erichocean: but that seems...hacky [22:20] ryah: erichocean: if you can wait until the end of the week, it will become much easier [22:21] ryah: i'm rewriting the whole tcp server in js [22:21] isaacs: ryah: w00t!! [22:21] erichocean: can you send binary? [22:21] isaacs: ACTION is thrilled by more js [22:21] erichocean: I had to write the C++ to write a correct message for APNS [22:21] erichocean: (iPhone push) [22:22] ryah: going to add a new binary type "Buffer" which will probably help that too [22:22] kriskowal: my last patch factored a lot of the body of node.cc into a node_static.cc module that could be shared by node_narwhal.cc. not sure how well that jives. [22:22] ryah: kriskowal: i just scanned it but it seems to be okay [22:23] kriskowal: i think ideally a lot of node.cc should be parted out to other modules, but i can see there's tension about what to do with statics like shared symbols [22:23] ryah: well, anyway the new tcp sserver will probably live along side the old one for a while [22:23] kriskowal: i look forward to seeing your Buffer type. [22:24] ryah: yeah the buffer is pretty v8 specific. it has things like asciiSlice() [22:24] ryah: but it will be fast [22:24] kriskowal: i've unfortunately been relegated the responsibility for writing proposals for binary types in narwhal, something which i have ideas for, but it needs more practice [22:24] kriskowal: fast is good. [22:25] ryah: well. i /think/ it will be fast :) i don't it running yet [22:25] kriskowal: i meant commonjs (prays someone didn't notice that slip) [22:28] ryah: isaacs: regarding setExports(), sounds fine to me [22:29] isaacs: great [22:29] micheil has joined the channel [22:29] kriskowal: i'll get setExports in narwhal too at some point [22:29] isaacs: i get the impression that you and me (and most nodejs folks) don't much care what it's called or where it goes. [22:29] isaacs: otoh, the commonjs crowd cares a lot about that. [22:29] ryah: yeah, which is good :) [22:29] isaacs: so, my idea is, let's let #commonjs fight over it, come up with the provably correct place to hang that function, and then settle on that as a standard. [22:29] kriskowal: sometimes they complain harder than they work [22:30] isaacs: kriskowal: one way to handle that is "they complain so i don't have to" [22:30] kriskowal: as long as we keep the work/complain ratio high, it's good [22:30] kriskowal: yeah [22:30] ryah: isaacs: very reasonable. i was going to suggest that [22:30] isaacs: #commonjs is the place for complaining. narwhal and node and persvr and flussperfdjsfenxyzlolwtfbbq should be about implementation. [22:31] kriskowal: pferd menas horse. joins phenolphthalein for weird consonant clusters. [22:32] kriskowal: *means [22:32] kriskowal: hah [22:32] rictic has joined the channel [22:32] isaacs: i thot it was perfd? [22:32] kriskowal: would make sense for a performance daemon [22:33] isaacs: yeah... [22:33] isaacs: is it flusspferd? [22:33] kriskowal: yeah [22:33] isaacs: whoa, it is. [22:33] isaacs: i've been pronouncing it wrong!! [22:33] kriskowal: the final d is like a t [22:33] isaacs: it's german for hippo [22:33] isaacs: wow. [22:33] kriskowal: flooss-pfert [22:34] kriskowal: river horse. hippopotamus is also literally translates as river-horse from latin. [22:34] kriskowal: i think. might be greek [22:34] kriskowal: no, latin. -us [22:34] kriskowal: ryan, thought experiment: how could we get the Stats object symbols into the node_stats.*? [22:34] kriskowal: i presume they're in node.cc just because it's a hard thing to fight [22:34] isaacs: kriskowal: it's romanized greek. [22:35] kriskowal: ah. [22:35] isaacs: hippos potamios [22:35] kriskowal: i play a tuba-like-instrument called euphonium. same deal. [22:35] isaacs: was there already an OSS project called Hippo? [22:35] isaacs: ACTION .oO( javascripters like animals ) [22:35] ryah: kriskowal: Stats - yeah i just put things that i can't find a better place for into node.cc [22:36] ryah: kriskowal: it could probably be in its own file even. shrug. [22:36] kriskowal: i tried putting it in node_stats and ran into trouble [22:37] kriskowal: static linkage. been a while since i did c. [23:02] kriskowal: ryah, tom and i have a sort of arrangement where we share the responsibility for integrating contributor work, which takes new development time away from both of us. you might consider encouraging one of your more trusted lieutenants to assist with integration. [23:03] kriskowal: the node community appears to be about five times bigger than narwhal at the moment; you might need a lot of help with integration :P [23:04] RayMorgan has joined the channel [23:06] isaacs: the curse of popularity, it seems :) [23:08] JimBastard: http://uncyclopedia.wikia.com/wiki/Narwhal [23:12] sveisvei has joined the channel [23:12] sveimac has joined the channel [23:17] isaacs: JimBastard: lolz: "The traditional language of the Narwhal is Haskell, an obscure yet functional dialect based on C++ templates and gonads. As a result, to human ears, Narwhals appear to speak in gibberish. " [23:17] JimBastard: GONADS [23:17] JimBastard: classic [23:18] inimino: heh [23:23] micheil: hmm.. only one error on the mac.. [23:39] malkomalko: aww yah baby [23:40] voodootikigod has joined the channel [23:44] trevor has joined the channel