[00:06] benw: ACTION wonders if anyone actually uses EventEmitter.removeListener()
[00:07] dekz has joined the channel
[00:09] mikeal: benw: I do
[00:10] benw: Oh good, I'd better make sure I don't break it then :)
[00:11] jamiew has joined the channel
[00:15] scudco1 has joined the channel
[00:16] mikeal: what license is node under?
[00:19] benw: A very short one :) http://github.com/ry/node/blob/master/LICENSE
[00:25] mikeal: yeah, i found it
[00:25] mikeal: i wanted to put the NGI stuff under the same license
[00:27] pjb3: Hey, I'm wondering if makes sense to do this: http://gist.github.com/285544
[00:27] benw: Sorry, maybe you were asking what the license is called. Not sure.
[00:27] pjb3: This is a file reader that reads in a file in chunks
[00:28] pjb3: because posix.cat reads the whole file into memory at once, right?
[00:28] pjb3: So if I wanted to process a 1GB file, this file reader would make sense, right?
[00:28] mikeal: benw: looks like the MIT license
[00:29] benw: mikeal: Ah ok, ta
[00:31] BradleyS has joined the channel
[00:38] benw: ACTION is reading mikeal's email
[00:39] mikeal: the way you said it, it almost sounds malicious
[00:39] mikeal: you hacked my Gmail!
[00:39] mikeal: :P
[00:39] benw: :)
[00:39] mikeal: next thing you'll say is "you're wearing a nice shirt today"
[00:40] benw: ACTION is reading spec.mkd
[00:40] mikeal: ACTION plays creepy stalker music
[00:40] benw: "He's behind you!"
[00:42] JoePeck has joined the channel
[00:42] isaacs has joined the channel
[00:42] benw: mikeal: Minor - "The response object has two methods." but actually it has three, right?
[00:43] mikeal: yes, type
[00:43] mikeal: er tyop
[00:43] mikeal: fixing
[00:43] mikeal: wait, where is that
[00:44] benw: The Response section, near the bottom
[00:44] mikeal: that's not in the latest version
[00:44] benw: http://github.com/mikeal/ngi/blob/master/spec.mkd
[00:44] mikeal: yeah, doesn't say that
[00:44] mikeal: do a hard refresh
[00:44] mikeal: maybe you'll pulling from cache or something
[00:45] benw: Hmm, I'm still seeing it
[00:45] mikeal: awe crap
[00:45] mikeal: now i see it
[00:45] mikeal: i was seraching for "2" not "two"
[00:46] benw: Oh good, I was starting to get annoyed with my web proxy. :)
[00:46] mikeal: ok, fixed
[00:46] benw: Ta
[00:47] benw: I'm playing catchup here
[00:47] benw: This is a wrapper around require('http'), right? But I'm not yet clear how much it adds.
[00:47] benw: It's not trying to be a web framework
[00:47] mikeal: the reference implementation is an abstraction around that, yes
[00:47] mikeal: so
[00:48] mikeal: there are alternate http servers
[00:48] mikeal: and that will continue to grow
[00:48] jamiew has left the channel
[00:48] mikeal: the point is so that a web framework can use this spec, and the server can implement it as well
[00:48] benw: Of which node's http is one?
[00:48] mikeal: and then frameworks and applications are portable between servers
[00:48] mikeal: yes, node's http is one
[00:48] benw: Ok, getting it
[00:49] benw: I can't imagine there are too many other async javascript servers currently?
[00:49] mikeal: but, for example, there is already this http://github.com/tautologistics/nodemachine
[00:49] mikeal: well, all servers in node are going to be async
[00:49] benw: Hope so
[00:50] mikeal: well, if they block the main event machine I doubt anyone will use it :)
[00:50] benw: Yeah
[00:51] benw: I guess I was thinking of "application" as something that would sit within a web framework
[00:52] mikeal: so, Application as an actor could be a web framework
[00:52] benw: right
[00:52] mikeal: and it would just implement a single application function as a connector
[00:52] mikeal: just like WSGI
[00:52] benw: Ok, thanks for clarifying
[00:52] mikeal: but not blocking
[00:52] mikeal: and less….. crappy
[00:52] benw: :)
[00:52] mikeal: i've been dealing with WSGI for years
[00:53] benw: I've never used any of that stuff, I'm a newcomer to web frameworks
[00:53] mikeal: it has some good parts but it also has some huge warts
[00:54] isaacs: mikeal: what would you say are the worst warts of wsgi?
[00:54] isaacs: aside from the blocking synchronicity thing
[00:54] mikeal: well, that's a design choice, and it fits Python
[00:55] mikeal: it sucks for everyone who implements async, but in the Python world they are in the minority anyway
[00:55] markwubben has joined the channel
[00:55] mikeal: the wort part is that it forces you to parse the full path in to parts, but provides no original path
[00:55] mikeal: so to reconstruct the original path you have to have this like 8 line function that isn't very fast
[00:56] mikeal: the other really annoying thing
[00:56] mikeal: is that it doesn't provide hardly any access or information to any layer lower then HTTP, which means you have to write a custom server if you want to do SSL Proxying
[00:57] mikeal: it insists on maintaining compatibility with CGI, even though not a single Server bases their WSGI support on CGI
[00:58] mikeal: also, it creates a function and passes it around (start_response), which in Python actually isn't all that well optimized
[00:58] mikeal: callbacks kinda suck in Python, and closures aren't well optimized either
[00:58] mikeal: it also doesn't have a way to tell if start_response has already been called
[00:59] mikeal: ok, i'll shut up now
[00:59] benw: That was useful - you should paste it somewhere in your doco
[01:00] isaacs: mikeal: thanks
[01:00] isaacs: a lot of that is actually either trivial to fix or isn't a problem in js
[01:01] mikeal: callbacks and closures are well optimized in javascript
[01:01] isaacs: passing around a function/callback is highly optimized, and there's a lot of ways to mark that it's been called.
[01:01] isaacs: right
[01:01] mikeal: but knowing if the headers have already been sent is actually really important
[01:01] mikeal: and specifying that if you attempt to send the headers twice that you throw an exception is also important
[01:02] isaacs: suresure
[01:02] isaacs: which isn't an issue with a sync setup
[01:02] isaacs: or, is less of an issue, at lesat.
[01:03] isaacs: mikeal: so, it seems like: keep the original path intact somewhere (even in routing/mounting cases), provide a mechanism to know whether or not hte response has started and whether headers are sent already.
[01:04] mikeal: so, here is the distinction i make in the spec
[01:04] mikeal: the full path the server parsed
[01:04] mikeal: so if there is some rewrite step in front of the server, it'll modify that path and set script_name
[01:05] mikeal: isaacs: those are the biggest warts, but also just having something that feels good in node is going to be better for everyone to implement and build on
[01:05] mikeal: hopefully this week i can start on ngi-plugins
[01:06] benw: If I call http.sendHeader() twice, is the second call just ignored?
[01:06] mikeal: which is an addition to ngi to support "middleware" in a way that insures compatibility between plugins
[01:06] mikeal: benw: throws an exception
[01:06] benw: ok ta
[01:07] benw: I've been playing with writing a small web framework for my own learning.
[01:07] benw: I want to make it behave nicely in a page dispatch function (or whatever I should be calling it) throws an exception
[01:08] benw: hence the process.exceptionCatcher stuff so I can send 500 Internal Server Error.
[01:08] benw: So I need to go make sure I don't call sendHeader twice in that circumstance.
[01:09] benw: ACTION thinks everyone should use process.exceptionCatcher
[01:09] benw: ACTION is very proud of it
[01:09] mikeal: you can check the Response.headersSent attribute
[01:10] benw: Will do, once I figure out how to build my think on top of NGI instead of straight on http
[01:10] benw: s/think/thing/
[01:11] mikeal: shouldn't be too hard, it should be simpler
[01:12] benw: Will give it a go now. Will you be online for a bit?
[01:12] mikeal: yup
[01:15] benw: I think I'll imaginatively name my project "webframework".
[01:16] mikeal: hehe
[01:16] bpot has joined the channel
[01:18] isaacs: benw: sorry, i'd missed your response, i'm checking it now
[01:19] benw: isaacs: Oh, the email? No worries.
[01:19] benw: I've committed a fix to removeListener since then.
[01:20] isaacs: yeah. so it looks like your'e just creating two arrays, one for callbacks and another to trap the current exception catcher at the moment of assignment, right?
[01:21] isaacs: ACTION .oO( wow, we REALLY need a better code review tool...)
[01:21] benw: isaacs: Right
[01:21] isaacs: i don't see any problem with that... just thinking it through..
[01:22] mikeal: i just use GitHub for code review
[01:22] mikeal: have people push to a branch and comment
[01:22] isaacs: mikeal: yeah, but sometimes a change is more than just one commit
[01:22] isaacs: and there's no workflow support built into it
[01:22] mikeal: right, so you comment on the current file HEAD in that branch :)
[01:23] mikeal: it works if you aggressively use branches
[01:23] isaacs: it'd be great if folks could send a pull req or patch to ryah or the list, and then he could somehow say "this is so-and-so's dept, when they sign off on it, it gets merged in"
[01:23] BradleyS has left the channel
[01:23] isaacs: or he could do it himself, and have it go into a "review mode" kind of flow, so others could weigh in on the comments, etc.
[01:24] mikeal: all you would need is a fwd or cc line in the message reply on GitHub :)
[01:24] isaacs: ACTION wants that for lots of reasons..
[01:24] mikeal: if you follow jeresig
[01:24] mikeal: he watches his fork queue religiously
[01:24] mikeal: and comments on anything anyone is doing
[01:25] isaacs: he's also a robot with unlimited batteries whose programming is written in javascript.
[01:25] mikeal: and all the other committers follow him, so if he comments on something in an area they care about they see it
[01:25] benw: What does jeresig work on?
[01:25] mikeal: jQuery
[01:25] isaacs: benw: he's jquery
[01:25] benw: ok
[01:26] benw: Never used it, hear it's popular :)
[01:27] benw: ACTION .oO( Stunned silence...? )
[01:27] benw: ACTION is new to this stuff
[01:27] mikeal: it makes writing cross-browse javascript about 10 times easier
[01:28] benw: I've read a bit about it. I'll probably start with mootools.
[01:28] aho: and about 10 times more compact
[01:28] aho: :)
[01:28] isaacs: i've mostly used yui
[01:29] isaacs: but jquery IS very very nice
[01:29] benw: mikeal: Trying to write hello world with NGI
[01:31] benw: Does the spec say how to arrange for my function application(con, req, res) to be called?
[01:33] benw: Oh, got it: Instantiate Server. duh.
[01:34] benw: Yay, that works.
[01:36] mikeal: sorry, i was washing out my new Scooba robot
[01:36] benw: mikeal: Just out of interest, is that dependent on the NGI implementation from the point-of-view of the spec?
[01:37] mikeal: no, that argument order is required
[01:37] mikeal: when passed to the application function
[01:37] mikeal: in your framework, on the application side, you can do whatever you want tho
[01:37] benw: Sorry, I meant Server constructor and .start()
[01:37] mikeal: OH, no, that is not part of the spec
[01:38] benw: Right, yeah that seems sensible
[01:38] mikeal: servers implement their own methods of configuration and starting
[01:38] mikeal: they just need to have somewhere when you can set the application
[01:38] benw: So my framework shouldn't implement that, so it can move between NGI implementations
[01:38] benw: I should just expose an 'application' function.
[01:38] mikeal: right, you framework just needs to provide an "application" function somewhere
[01:39] mikeal: exactly
[01:39] benw: Cool
[01:40] benw: ACTION is enjoying riding this new javascript pony around, it's more fun than C++
[01:40] isaacs: benw: it's a nice pony.
[01:41] benw: Closures are cool, I never grokked them before.
[01:42] benw: And I was just about to thank isaacs for his email.
[01:53] dnolen has joined the channel
[02:01] benw: mikeal: The "webframework" stuff I've written so far is essentially a wrapper for the Response object.
[02:01] mikeal: cool
[02:01] benw: It makes cache ETag semantics convenient,
[02:02] benw: and does the '500 Internal Server Error' thing.
[02:02] benw: So, should my webframework.Response just inherit from ngi.Response?
[02:02] dnolen has joined the channel
[02:02] mikeal: that depends on how it's structured
[02:02] benw: I want clients of webframework to have access to all the ngi stuff
[02:03] benw: I was afraid you'd say that
[02:03] benw: Hmm
[02:03] mikeal: i mean, you'll at least want to pass the ngi Response object to the constructor for yours
[02:03] benw: I think I need to write the test first, my head is getting confused.
[02:06] benw: Is scriptName an attribute of request or environ? The spec is potentially ambiguous.
[02:06] mikeal: environ
[02:06] benw: I assumed so.
[02:06] mikeal: i'll add a little
[02:06] benw: Why not just have all those attributes directly on the request object?
[02:07] mikeal: fixed
[02:07] benw: yeah that's clear now
[02:07] mikeal: so, when i do the work to specify how middleware works
[02:08] mikeal: i want to have a settr structure on that object so that different middleware can listen for changes
[02:08] mikeal: and adding attributes to request would not fall under than structure
[02:09] benw: I don't even really know what middleware is in this context
[02:09] mikeal: i would describe what I'm trying to do as plugins actually
[02:10] mikeal: but interoperable plugins
[02:10] benw: Could I make my caching semantics thing a plugin?
[02:10] mikeal: most definitely
[02:10] benw: I should do that then
[02:10] mikeal: one of the top use cases will be caching scenarios
[02:10] benw: And probably the 500 Error stuff too.
[02:11] mikeal: yeah, we can work all that in
[02:11] benw: Ok
[02:11] mikeal: when i start on the spec I'll make sure those use cases are in
[02:11] mikeal: and get your input
[02:11] benw: I'm just trying to keep up here :)
[02:11] mikeal: one of the big things I want to support is some CouchDB caching semantics I like
[02:12] mikeal: so that a plugin could listen to the _changes feed and update the local cache for certain resources
[02:13] benw: Currently I just have a response.sendResponse() function which takes statusCode, contentType, etag (optional) and body, where body is either a string or a callback. If etag matches If-None-Match, body is never called.
[02:14] mikeal: very nice
[02:14] benw: So if using my cache plugin, the client of the web framework shouldn't call response.sendBody except inside the body callback.
[02:15] mikeal: yeah, i would just keep your response object the way it is and change the internals to call stuff on NGI.Response
[02:17] benw: So I think my webframework.Response will inherit from ngi.Response, and add the sendResponse method which might call the body callback etc.
[02:17] benw: I think I'm still thinking the C++ way.
[02:18] benw: My plugin should just add a method to ngi.Response, right?
[02:19] isaacs has joined the channel
[02:19] benw: And sendResponse will need the request object as an argument so that it can look at the request headers
[02:25] benw: mikeal: Why is Request.headers an array rather than an object?
[02:25] mikeal: because it's legal to have two headers of the same name
[02:25] benw: Oh, ok
[02:26] isaacs: mikeal: you see my patch on the list about that?
[02:26] benw: Just figuring out how to get hold of If-None-Match
[02:26] mikeal: isaacs: not yet
[02:26] isaacs: mikeal: check it out.
[02:27] benw: isaacs: Thanks for your email
[02:27] isaacs: basically it'd allow { foo : ["bar", "baz"] }
[02:27] isaacs: to send "foo:bar\r\nfoo:baz"
[02:27] benw: isaacs: Does that also cover request headers:
[02:27] benw: ?
[02:28] isaacs: benw: i didn't touch the req headers, no
[02:28] isaacs: but that'd be a good addition.
[02:30] deanlandolt: mikeal: isaacs's form seems a lot friendlier than the wsgi [{foo: bar}, {foo: baz}] from i think you're proposing
[02:31] deanlandolt: it's what jsgi's doing (for request and response)
[02:31] isaacs: deanlandolt: i think he's proposing node's original [["foo", "bar"], ["foo", "baz"]] style
[02:31] isaacs: which still works, btw
[02:31] mikeal: how come i don't see that yet
[02:31] mikeal: hrm....
[02:31] deanlandolt: oh...yeah, that's all wsgi..tuples are painful though :-/
[02:32] isaacs: mikeal: http://groups.google.com/group/nodejs/browse_thread/thread/76ccd1714bbf54f6
[02:32] deanlandolt: plus, the array toString's down automagically by comma-joins...which is bang-on rfc2616 (even though, yes, i know it doesn't work for Cookie)
[02:32] isaacs: you can, today, do {x : ["foo", "bar"], y : ["foo", "baz"]}
[02:32] isaacs: and that's bizarre
[02:33] deanlandolt: what's bizarre? is x a header?
[02:33] isaacs: no
[02:33] isaacs: x and y are dropped
[02:33] deanlandolt: oh, yeah -- i saw your email
[02:33] isaacs: node goes "oh, it's an array, ok"
[02:33] deanlandolt: that is bizarre
[02:33] isaacs: because the for-in works for an array of arrays
[02:34] mikeal: well.....
[02:34] mikeal: the Server should NOT be merging headers
[02:34] mikeal: it makes a Proxy nearly impossible
[02:34] isaacs: right
[02:35] isaacs: for request headers, they should be some kind of "list of tupes" style.
[02:35] isaacs: s/pes/ples/
[02:35] mikeal: the response as well
[02:35] mikeal: it's the same problem
[02:35] isaacs: really?
[02:35] deanlandolt: i don't follow by "merging headers"?
[02:35] mikeal: yeah, if you write a proxy, you want to return the headers exactly as they come from the http client
[02:36] isaacs: mikeal: sure
[02:36] deanlandolt: it's purely instructional to the server
[02:36] isaacs: but i can do that, as long as array-of-arrays is *allowed*, then that's fine
[02:36] deanlandolt: but if some middleware screws up and +='s a header it's 'technically' accurate
[02:36] isaacs: or i can construct it as an object with a few array members.
[02:37] mikeal: so, two things i'm worried about
[02:37] mikeal: one is implementation cost, because now each server needs to do some type checking
[02:37] deanlandolt: mikeal: huh?
[02:38] mikeal: and the other is that if we have multiple ways to use the same object, then everyone on the application side has to do type checking
[02:38] deanlandolt: you mean with the array of arrays, or with the properties of string or array?
[02:38] mikeal: properties of string
[02:38] isaacs: walking through an array is more expensive, and complicated, than checking types.
[02:38] deanlandolt: yeah it is
[02:38] mikeal: so
[02:38] deanlandolt: and more obnoxious IMHO
[02:39] mikeal: is there any reason this needs to be in the gateway interface?
[02:39] mikeal: it could be implemented on the application side
[02:39] deanlandolt: mikeal: if you want middleware, yeah
[02:39] isaacs: i mean, let's say my app needs to know the accept-encoding header value.
[02:39] pjb3 has joined the channel
[02:39] mikeal: so, middleware is going to use another spec
[02:39] joshbuddy has joined the channel
[02:39] deanlandolt: oh...well, nevermind me :)
[02:39] mikeal: ngi-plugins
[02:39] mikeal: which will be on the application side
[02:39] tmpvar has joined the channel
[02:39] isaacs: if we're always going to get array-of-arrays, then i have to walk down the list checking item[0]
[02:39] isaacs: that's costly, and annoying.
[02:40] isaacs: it feels like work.
[02:40] mikeal: right, that sucks
[02:40] tmpvar: hello
[02:40] mikeal: i would rather, in ngi-plugins, have something liek
[02:40] deanlandolt: i don't follow what's the problem with the jsgi approach? if it's an array the server knows to send multiple headers, if it's a string it's one header
[02:40] isaacs: i think there's too much specification involved here. jsgi works because of how small it is.
[02:40] mikeal: setHeader(name, value)
[02:40] mikeal: addHeader(name, value)
[02:40] mikeal: and have corresponding events that plugins can listen for
[02:41] deanlandolt: what is addHeader's behavior if the header already exists?
[02:41] mikeal: and something like
[02:41] mikeal: headers.asObject()
[02:41] mikeal: deanlandolt: addHeader is append
[02:41] deanlandolt: and setHeader replaces all instances of a given header key?
[02:41] mikeal: setHeader removes any headers of name and adds the new one
[02:41] isaacs: i like set/add header
[02:41] isaacs: headers.asObject() is lame, though
[02:42] deanlandolt: yeah -- that makes pretty good sense...
[02:42] isaacs: is order relevant for headers?
[02:42] deanlandolt: but it's the behavior of getHeader that's the most important (again, from a middleware perspective)
[02:42] mikeal: to HTTP, no
[02:42] isaacs: mikeal: to anyone?
[02:42] mikeal: i know that browsers don't care
[02:43] isaacs: i mean, can i just shuffle around the order of the headers willy nilly and still get the same results?
[02:43] isaacs: because, if so, why even use an array ever?
[02:43] mikeal: according to the HTTP spec
[02:43] isaacs: it's going to be slower, and more of a pita.
[02:43] deanlandolt: isaacs: technically yes, but order's "instructive" i believe
[02:43] mikeal: using the array is because you can have two headers of the same key
[02:43] tmpvar: does anyone know how difficult it would be to add line numbers to exceptions?
[02:43] isaacs: mikeal: but you can do that with an object pretty easily
[02:43] isaacs: by just having the value be an array of strings
[02:44] isaacs: tmpvar: they should already be there.
[02:44] deanlandolt: isaacs: exactly!
[02:44] mikeal: right, but then you've gotta do this
[02:45] mikeal: if (headers.name) { headers.name.push("value") } else { headers.name = [value] }
[02:45] isaacs: mikeal: sure
[02:45] mikeal: which is just as annoying :)
[02:45] deanlandolt: what's wrong with that? that's a lot shorter than a forEach
[02:45] isaacs: well, but it's faster, and easier to sugar up at the framework level.
[02:45] isaacs: MySuperFramework.addHeader("foo", "bar")
[02:46] isaacs: and then i know it won't be doing a forEach every time i do that.
[02:46] mikeal: where is it faster?
[02:46] isaacs: if there's 100 header lines already, it doesn't have to walk down them all
[02:46] mikeal: add header is just headers.push()
[02:46] mikeal: you mean setHeader
[02:46] isaacs: oh, right, setheader
[02:46] tmpvar: http://pastie.org/792991 -- no line number on a caught exception
[02:46] isaacs: also, if i want to GET the header value, then that's WAY bigger
[02:47] mikeal: true
[02:47] isaacs: tmpvar: it's in the stack string
[02:47] tmpvar: word, thanks
[02:47] isaacs: tmpvar: can you share what's in exception.js?
[02:47] tmpvar: yeah
[02:47] tmpvar: 1 se
[02:47] deanlandolt: mikeal: but performance is irrelevant -- i can /promise/ you header manip won't be the bottleneck
[02:48] isaacs: true.
[02:48] isaacs: it's not about performance
[02:48] mikeal: you're right
[02:48] mikeal: i'm less worried about performance than I am about missuse in server implementations
[02:48] tmpvar: http://pastie.org/792992 -- not the best example. but it works for this case.
[02:48] isaacs: it's about what kind of thing an array is, and what it means, and leveraging an object for key-value field sets
[02:48] mikeal: array of arrays is pretty explicit, which is it's only benefit
[02:49] mikeal: of course
[02:49] deanlandolt: mikeal: that i can buy..but an object of string or array is pretty explicit too
[02:49] deanlandolt: as far as object structures go it's pretty much how js represents these things (after all, js doesn't really have tuples anyway)
[02:50] mikeal: yeah
[02:50] deanlandolt: plus, there's that weird accidental benefit of an array joining on "," (per 2616) which to me just suggests the universe wants it that way :D
[02:50] mikeal: oh wait
[02:50] mikeal: now i remember
[02:50] isaacs: so, you'd be gaining a more elegant structure, but losing the strict order of the header lines.
[02:50] mikeal: ordering does matter for content-type
[02:50] mikeal: the first or last one wins
[02:50] mikeal: and i think content-length as well
[02:50] deanlandolt: really? it's the q that determines that
[02:50] isaacs: mikeal: but that'd stil be preserved.
[02:51] mikeal: right, we do abstract that
[02:51] deanlandolt: it's techincally not specified but i believe v8 retains order
[02:51] isaacs: because [[foo, bar],[foo, baz]] is the same order as {foo:[bar, baz]}
[02:51] mikeal: so long as we specify that content-type and content-length are removed from the headers object
[02:51] isaacs: it's only the order of instances of the same header field name that matter.
[02:52] tmpvar: thanks isaacs
[02:52] deanlandolt: but wait a minute...it's easier to control the order if your've got an object with array keys anyway -- you can slice to your heart's content
[02:52] mikeal: right
[02:52] deanlandolt: as opposed to walking your list of lists and trying to rearrange? that's kinda tough
[02:52] mikeal: i just need to specify that headers does not include content-type and content-length
[02:52] isaacs: what i'd be interested in is: is there a case where [[foo,bar][bar,baz][foo,baz]] is different thant [[foo, bar],[foo,baz][bar,baz]]
[02:53] deanlandolt: isaacs: in theory or practice? i'm sure there's some broken proxy out there that screws something up there ;)
[02:53] isaacs: deanlandolt: in practice, but reasonably.
[02:53] mikeal: hehe
[02:54] isaacs: there's a proxy out there to screw up any given thing we think up
[02:54] mikeal: maybe the thing to do, is leave it the way it is for NGI but for ngi-plugins we define an entirely new structure for manipulating headers that is nicer on the eyes and doesn't have to worry about broken proxies :)
[02:54] isaacs: tmpvar: np. you realize that "new {};" is an error, right?
[02:55] tmpvar: yeah :)
[02:55] isaacs: tmpvar: k, kewl, just checking :)
[02:58] brandon_beacher has joined the channel
[03:03] richtaur has joined the channel
[03:04] dnolen has joined the channel
[03:07] jed has joined the channel
[03:18] benw: mikeal: So, the upshot of all the above is that I should search the array for If-None-Match?
[03:18] mikeal: for now
[03:18] benw: k, ta
[03:21] eviltwin has left the channel
[03:30] r11t has joined the channel
[03:31] benw: mikeal: It seems like it would be convenient to be able to get from a Response object back to the corresponding Request object.
[03:32] benw: Is there a specific reason that there's no Response.request attribute?
[03:32] mikeal: it would be useful
[03:32] mikeal: but from the specs point of view it hands everything off to one function
[03:33] benw: the application function
[03:33] mikeal: so, if that function wants to set response.request, it can, and probably should
[03:33] benw: Ok. But as a plugin-writer, I don't write application.
[03:34] mikeal: right, ngi-plugins spec could define that
[03:34] benw: So the methods I add need to be explicitly passed req and res
[03:34] benw: Ok
[03:34] benw: I think I'm jumping the gun by trying to write a plugin before I know the plugin API
[03:35] mikeal: well, the plugin API doesn't have a spec or anything yet
[03:35] benw: right
[03:37] tmpvar: thats not quite the plugin api though, right?
[03:38] tmpvar: sorry, i mean: thats not a problem at the plugin api level, right?
[03:40] mikeal: it's on the application side
[03:42] tmpvar: so its an application level API issue
[03:46] mikeal: right, and ngi-plugins is going to specify a good API on the application side for interoperable plugins
[03:47] dnolen_ has joined the channel
[04:03] dnolen has joined the channel
[04:09] tmpvar: im not familiar with ngi-plugins.. link?
[04:09] mikeal: it's not written yet :)
[04:10] mikeal: i'll be working on it this week
[04:10] mikeal: but it's where all the "middleware" stuff goes
[04:10] tmpvar: ah, is this the noge gateway interface stuff?
[04:10] tmpvar: node even
[04:10] mikeal: yes
[04:10] tmpvar: gotcha
[04:19] kriszyp has joined the channel
[04:22] dnolen_ has joined the channel
[04:47] joshbuddy has joined the channel
[04:59] mikeal has joined the channel
[05:00] lifo has joined the channel
[05:07] isaacs has joined the channel
[05:08] kennethkalmer has joined the channel
[05:29] sudoer has joined the channel
[05:42] rictic has joined the channel
[05:47] gf3 has joined the channel
[06:28] lifo_ has joined the channel
[06:47] lifo has joined the channel
[07:01] richter has joined the channel
[07:22] zmoog has joined the channel
[07:27] joshbuddy has joined the channel
[07:39] sixtus42 has joined the channel
[07:39] sixtus42_ has joined the channel
[07:45] rictic has joined the channel
[07:45] dekz has joined the channel
[07:49] r11t has joined the channel
[07:50] dekz_ has joined the channel
[08:41] hassox has joined the channel
[08:45] hassox: Hey folkdls
[09:14] felixge has joined the channel
[09:14] olivierG has joined the channel
[09:17] olivierG: hello, does someone tried to compile node.js with gnutls support on debian Lenny ?
[09:23] sixtus42 has joined the channel
[09:42] felixge_ has joined the channel
[09:50] elbart has joined the channel
[10:15] dekz has joined the channel
[10:20] dekz_ has joined the channel
[10:23] teemow has joined the channel
[11:16] hassox has joined the channel
[11:18] jfd has joined the channel
[11:23] blackdog` has joined the channel
[11:52] jfd has joined the channel
[12:21] dekz has joined the channel
[12:35] lifo_ has joined the channel
[12:36] alex-desktop has joined the channel
[12:51] hassox_ has joined the channel
[13:04] sixtus42 has joined the channel
[13:11] sixtus42 has joined the channel
[13:28] unomi has joined the channel
[13:58] mahemoff has joined the channel
[14:01] pmuellr has joined the channel
[14:04] keeto has joined the channel
[14:09] kriszyp has joined the channel
[14:23] pjb3 has joined the channel
[14:33] lifo_ has joined the channel
[14:42] jed_ has joined the channel
[14:43] davidsklar has joined the channel
[14:50] nrstott has joined the channel
[14:56] Booster has joined the channel
[15:04] bryanl has joined the channel
[15:22] pjb3 has joined the channel
[15:39] bryanl has joined the channel
[15:46] evilhackerdude has joined the channel
[15:48] alexiskander has joined the channel
[15:53] joshbuddy has joined the channel
[16:02] hassox has joined the channel
[16:03] n8o has joined the channel
[16:03] keeto_ has joined the channel
[16:04] gwoo has joined the channel
[16:06] binary42 has joined the channel
[16:06] steadicat has joined the channel
[16:20] stevestmartin has joined the channel
[16:33] cloudhead has joined the channel
[16:39] rictic has joined the channel
[16:46] bpot has joined the channel
[16:47] isaacs_mobile has joined the channel
[16:51] felixge_: ryah_away: congratz on landing the solaris patch
[16:52] ryah: thx
[16:52] micheil: moin ryah & felixge_
[16:52] felixge_: ACTION gotta reboot
[16:53] micheil: ryah: does net2 implement any protocol helpers or anything like that?
[16:53] micheil: I notice it's lib has a buffer and stuff, although, that probably doesn't help for data sent back from a server on new lines and stuff
[16:54] ryah: no
[16:54] micheil: okay, so the project I'm almost ready to start shouldn't have anything to conflict with
[16:55] ryah: it's almost the same api - just s/receive/data
[16:58] isaacs_mobile: micheil: what's the project?
[16:58] micheil: a low-level protocol helper, to handle sockets, buffers, and parsing
[16:59] micheil: so, it'll aid in writing protocols
[16:59] micheil: it might sound a bit funny, but it's something I've been thinking of doing for a while
[16:59] isaacs_mobile: Awesome.
[17:00] ryah: micheil: how would that work?
[17:00] isaacs_mobile: No, it sounds like useful work
[17:00] micheil: ryah: well, as I only really know how to program in javascript, it'd be javascript
[17:00] micheil: but as for how it'd work, parts of it would be abstracted from my current node-smtp work
[17:01] micheil: it'd implement two sides of the story, a client and server
[17:01] micheil: for instance, my smtp stuff would be a new protocol.client
[17:01] jed_ has joined the channel
[17:02] ryah: i think it'd be nice to have something that did line buffering
[17:02] micheil: when you create a new protocol implementation, you get access to a set of "private" methods, for connecting to the server/clients
[17:02] scudco has joined the channel
[17:02] ryah: for irc or whatever
[17:02] micheil: ryah: line buffering I already have
[17:03] micheil: http://github.com/Miksago/node-smtp/blob/master/lib/vendor/Pump.js
[17:03] micheil: basically that's an evented array
[17:03] micheil: it's not the nicest code, but it worked
[17:04] RayMorgan has joined the channel
[17:04] micheil: (a c++ implementation would probably be better / quicker, although, I didn't want to compile.)
[17:05] CIA-78: node: 03Blaine Cook 07master * rcd6397c 10/ (5 files in 5 dirs): Add support for MX, TXT, and SRV records in DNS module. - http://bit.ly/6FbJ4j
[17:06] isaacs_mobile: ryah: nice
[17:06] micheil: awesome stuff!
[17:07] steadicat has joined the channel
[17:10] dnolen has joined the channel
[17:12] olivierG has left the channel
[17:22] micheil: isaacs_mobile: http://github.com/Miksago/node-protocol/
[17:25] sudoer has joined the channel
[17:27] micheil: ryah: what's the best paradigm for inheritance?
[17:27] micheil: I know of process.inherits() although, is there a better way?
[17:29] dnolen has joined the channel
[17:30] micheil: man.. I really hate this code: var Model = require("model").Model;
[17:30] micheil: then again, I'd like something were I can say, exports = something;
[17:31] ryah: yeah
[17:31] ryah: it suks
[17:31] kriszyp: yeah, I'd love exports = something too
[17:31] deanlandolt: micheil: you can always create a higher-level proxy-like object that just collects up all of that so it doesn't look so silly in app code...
[17:31] ryah: yey - http server running on net2
[17:32] kriszyp: dissappointed that we don't have that yet in commonjs modules :(
[17:32] micheil: kriszyp: I'm sure you can advocate it for me
[17:32] micheil: :P
[17:32] deanlandolt: e.g. pintura.js could also exports Model, so instead of that redundancy you could just say var Model = require("pintura").Model (or just var pintura = require("pintura"))
[17:32] kriszyp: I've been arguing for that on commonjs
[17:32] kriszyp: I just didn't win
[17:32] micheil: kriszyp: and yes, I did take that code from the blog post there
[17:33] kriszyp: yeah, I know :)
[17:33] deanlandolt: micheil: there's been a lot of advocates for it but it's an uphill battle :-/
[17:33] kriszyp: I don't always get my way in commonjs ;)
[17:33] micheil: I mean, for some things, it's awesome to build off as an object, but sometimes it's really needed to be set
[17:34] jed_: yeah, i'd really love to be able to export a single function.
[17:34] deanlandolt: but still, you can always create a simple proxy object that exposes a common public interface and eliminates that weirdness
[17:36] qFox has joined the channel
[17:36] micheil: deanlandolt: not really.
[17:36] kriszyp: is there destructuring in v8? can't remember...
[17:36] micheil: deanlandolt: if you're dealing with something like my data Pump, it's a first class thing
[17:36] deanlandolt: kriszyp: doubtful
[17:37] ryah: no
[17:37] micheil: there's nothing that sits above it, anything that uses it imports it, it's a module
[17:38] ryah: ACTION would like to get rid of exports altogether
[17:38] deanlandolt: micheil: fair enough, but you can still proxy to it from your application code, so any app depending on your app that uses Pump can grab a handle on it that way
[17:38] ryah: just add stuff to the global object :)
[17:38] micheil: no application that uses pump needs to access it, it's a "private" module
[17:39] deanlandolt: oh...fair enough, but the pattern i'm talking about would still work in a large number of cases
[17:39] micheil: I could almost say of the back of what ryan said that it's a hacked solution to keep from scope pollution.
[17:39] deanlandolt: not perfect but it'll do for now
[17:39] micheil: deanlandolt: more then likely
[17:39] micheil: deanlandolt: however, it could be better.
[17:40] deanlandolt: no doubt -- i'm in the same camp as kriszyp, kriskowal, isaacs (and quite a few others)...but no dice yet, and it's one of those things that has to have _everybody_ on board to change
[17:46] micheil: man.. I have no idea why but github isn't responding for me, anyone else getting similar?
[17:57] onar has joined the channel
[17:57] ryah: meh. first results for net2 http are not good.
[17:57] eddanger has joined the channel
[17:57] ryah: eating tons of memory and crashing
[17:59] stephenlb has joined the channel
[18:01] RayMorgan_ has joined the channel
[18:03] scudco has joined the channel
[18:04] micheil: :S
[18:04] micheil: doesn't sound good, but it should work out fine
[18:13] dnolen has joined the channel
[18:26] voxpelli-laptop has joined the channel
[18:27] micheil: what do people think so far: http://github.com/Miksago/node-protocol/blob/development/example/example-client.js ?
[18:30] micheil: (the only reason for github being in there is because I could depend on it timing out.. )
[18:35] mattly has joined the channel
[18:35] deanlandolt has joined the channel
[18:35] webben has joined the channel
[18:35] bengl has joined the channel
[18:35] wil has joined the channel
[18:35] ashb has joined the channel
[18:35] mayerbacher has joined the channel
[18:35] rudebwoy has joined the channel
[18:35] gbot2 has joined the channel
[18:35] tlrobinson has joined the channel
[18:35] FoxFurry has joined the channel
[18:36] stephenlb has joined the channel
[18:36] rictic has joined the channel
[18:36] Booster has joined the channel
[18:36] unomi has joined the channel
[18:36] sveisvei has joined the channel
[18:36] bjartek has joined the channel
[18:36] mediacoder has joined the channel
[18:36] erikcorry|away has joined the channel
[18:41] aguynamedben has joined the channel
[18:45] qFox: okay. so what are the risks of installing node.js on centOS?
[18:45] qFox: i really want to give it a spin, but i cant really afford it causing havoc on my server
[18:45] qFox: because frankly, i probalby wont be able to fix it back up
[18:45] micheil: you don't need a server in order to try node
[18:45] rtomayko has joined the channel
[18:46] micheil: try it on your local computer
[18:46] qFox: yeah well i'm running windows at home, since running it on windows is even more of a headache
[18:46] micheil: okay, fair enough then
[18:46] qFox: :)
[18:46] micheil: I'm not sure on centos support
[18:46] qFox: how much platform specific support does it need?
[18:46] qFox: isnt it dependent on v8?
[18:47] micheil: put it this way, on all of the two systems I've used node on (ubuntu and mac os x) I've never had any trouble
[18:47] ryah: qFox: should run on centos
[18:47] qFox: what are possible pitfalls when it might fail?
[18:47] qFox: could it possibly b0rk the apache/mysql setup?
[18:47] ryah: qFox: i'd install it locally in a user dir
[18:47] ryah: qFox: --prefix=$HOME/node_install
[18:47] mediacoder: qFox: just dont mess too much with python (used for node building)..besides that nothing can happen
[18:48] bryanl_ has joined the channel
[18:48] ryah: qFox: doubtful - just don't run anything sudo
[18:48] micheil: also, configure, then make, then make test
[18:50] ryah: qFox: though in general, i don't wouldn't try out stuff on a production machine
[18:50] ryah: s/don't///
[18:50] orlandov: qFox: you could use a linux vm
[18:51] qFox: it crossed my mind
[18:51] qFox: and i too am a bit hesatous (?) to run it on a production server, even when it's just my personal sites that dont attract a whole lot of attention
[18:51] orlandov: qFox: that's an instinct you should listen to
[18:52] orlandov: its just good practice
[18:54] qFox: ACTION is aware of that, dont worry :)
[18:54] qFox: but there's production and there's production. like i said, it's not like massive sites run on it. and i'm well aware of security issues
[18:55] qFox: (in fact, no sites with user content except my own)
[18:55] eikke_ has joined the channel
[18:56] mediacoder: qFox: anyways.. node wont break your existing stuff . go ahead and run configure to see if you need to install additional packages
[18:57] voxpelli-laptop has left the channel
[18:57] qFox: i'll go for a vm for now :)
[18:57] qFox: thanks
[18:58] ericflo has joined the channel
[19:00] sztanphet has joined the channel
[19:02] RayMorgan has joined the channel
[19:05] mikeal has joined the channel
[19:07] jamiew has joined the channel
[19:13] jamiew has left the channel
[19:21] mattly has joined the channel
[19:25] paulca has joined the channel
[19:28] jed_ has joined the channel
[19:37] ryah: http://github.com/bentlegen/malt
[19:37] ryah: ^-- i kind of wish we were doing this
[19:41] kriszyp: do you like RunJS? In Dojo, we are looking at moving to that
[19:42] qFox: ryah> what exactly is so special about that..?
[19:42] qFox: could in fact be easily achieved with node and a comet approach
[19:42] qFox: if not better
[19:43] ryah: kriszyp: runjs seems pretty verbose
[19:50] blackdog` has left the channel
[20:01] qFox: ryah> i didnt mean to offend you, i was really curious what you think is special about it...
[20:03] BBBB has joined the channel
[20:07] ryah: qFox: simple
[20:07] ryah: async
[20:10] mikeal: the thing i like about node.js > anything dojo related
[20:10] mikeal: is that javascript shines if you think of it first as a functional language and treat the OO features as secondary
[20:11] mikeal: if you think of it first as an OO language you'll just be disappointed
[20:11] mikeal: Dojo tries really hard to "fix" javascript as an OO language and make it look like of Java's insane interface model
[20:12] ryah: yeah, so what if we just give up on having nice namespaces
[20:12] mikeal: node.js takes advantage of the async and evented nature of javascript and the GREAT closure support
[20:12] ryah: and just let modules put themselves where they want?
[20:12] mikeal: that could get messy
[20:12] ryah: hm. although, i do very much like the securablemodules ns
[20:13] mikeal: is that documented somewhere?
[20:13] mikeal: cause i kind of need to look in to that when I get back to implementing a node.js CouchDB view server
[20:15] mikeal: i need to eval code in some kind of a sandbox
[20:22] aho has joined the channel
[20:24] _wil_ has joined the channel
[20:27] tmpvar has joined the channel
[20:27] tmpvar: hello
[20:27] qFox: ryah> async as in it uses the html5 property? or it's using a dynamic technique that doesn't tilt the browser?
[20:27] qFox: or stop, rather.
[20:29] tmpvar has joined the channel
[20:34] mikeal: qFox: node.js doesn't have a DOM
[20:35] tmpvar: not yet!
[20:35] tmpvar: :P
[20:35] mikeal: and, while some of the specifications are being implemented as modules (WebSocket) the APIs for dealing with IO are newly developed for node.js
[20:38] nefD has joined the channel
[20:40] voodootikigod has joined the channel
[20:41] ayo has joined the channel
[20:42] robrighter has joined the channel
[20:43] achew22 has joined the channel
[20:43] qFox: mikeal> no, but it could be used to serve javascripts through xhr over the same socket using some kind of comet technique. depending on the number of files, open up two or three sockets. thus circumventing the browser limit
[20:44] mikeal: there are some libraries for working with html/xml
[20:44] mikeal: but there is no document in the default namespace
[20:44] mikeal: all the socket libraries are written *for* node.js
[20:44] mikeal: and use an async callback structure
[20:45] mikeal: using EventEmitter and Promise
[20:45] isaacs has joined the channel
[20:47] mikeal: did anyone write an SMTP client yet?
[20:47] sudoer has joined the channel
[20:47] sztanpet: why not look at the node wiki
[20:47] tmpvar: there was mention of one in the works in the dns thread
[20:48] mikeal: i did
[20:48] mikeal: there is a library for parsing email messages, but nothing SMTP lately
[20:48] tmpvar: http://github.com/Marak/node_mailer
[20:48] mikeal: but i've seem people in here talking about working on libraries related to SMTP
[20:48] tmpvar: ah
[20:48] mikeal: that needs to be on the wiki!
[20:48] tmpvar: yeah, not sure if there is a full blown client lib
[20:49] rtomayko has joined the channel
[20:49] mikeal: hahaha
[20:50] mikeal: this library sets defaults for to and from fields if you don't specify them
[20:50] mikeal: and it defaults to from : obama@whitehouse.gov :P
[20:50] tmpvar: hah
[20:50] tmpvar: fail'
[20:50] mikeal: sweet, it actually writes SMTP messages and doesn't just attempt to pipe things to a sendmail subprocess
[20:52] mies has joined the channel
[20:53] jtoy has joined the channel
[20:53] Booster has joined the channel
[20:54] isaacs: micheil: re "man.. I really hate this code: var Model = require("model").Model;"
[20:54] isaacs: do module.exports = Blah;
[20:54] isaacs: and then, var Blah = require("blah")
[20:55] jasondavies has joined the channel
[20:57] jed_: isaacs: i like that! though i guess that precludes commonJS compat?
[20:57] mikeal: nope
[20:57] deanlandolt: jed_: for now
[20:57] isaacs: jed_: it's compatible with a few systems.
[20:57] isaacs: jed_: sadly, it seems that setExports kinda died on the vine.
[20:58] isaacs: i mean, *I'M* using it all over the place.
[20:58] jed_: thanks for that tip.
[20:59] jed_: though i wish modules were just vanilla js, and the returned module was whatever the code evaluated to.
[20:59] isaacs: i sorta figure that my code will be so wonderful that everyone will want to use it everywhere, and that'll encourage platform implementors to add module.exports support.
[20:59] isaacs: jed_: there are problems with using return, if you have cycles.
[20:59] jed_: what do you mean return?
[20:59] isaacs: jed_: (iow: "we've beaten that horse to a pulp, and made horse sausage, and even fried it up with some peppers.")
[21:00] jed_: isaacs: sure sure, that much i can tell.
[21:00] deanlandolt: jed_: you could always roll your own module system out of cat + eval ;)
[21:00] jed_: isaacs: though i'm sure horse sausage is a delicacy somewhere.
[21:01] isaacs: jed_: well, one of the proposals was a bit like what youer' suggesting, where the module can use the "return" statement to define the exported object.
[21:01] jed_: isaacs: sure, but i'm saying something even simpler. return assumes a function.
[21:01] isaacs: jed_: sure, but we all pretty much have to wrap in a fn anyhow to prevent leakage.
[21:02] isaacs: er, not "prevent" per se, but reduce
[21:02] deanlandolt: isaacs: hermetic eval may fix that in es-next
[21:02] jed_: isaacs: (i'm sure there are a ton of considerations i've never thought of.)
[21:02] isaacs: deanlandolt: yep. also, node's process.compile is pretty handy
[21:06] onar has joined the channel
[21:08] davidsklar has joined the channel
[21:09] isaacs: jed_: if you set module.exports make sure to do so up at the top of your file, and only once.
[21:10] isaacs: once your module has been acquired, setting module.exports is dangerous. i have a patch lying around here that'll throw an error in that case, but i figure we may as well do that once we go to Modules/1.1, if that ever happens
[21:10] mikeal has joined the channel
[21:11] jed_: isaacs: ah, okay. so if i want to set it to a function, the function needs to be defined after module exports is set?
[21:11] jed_: isaacs: aka, through the function name(){} syntax?
[21:11] isaacs: jed_: well, it just needs to be set on the first "pass" through your module.
[21:11] jed_: isaacs: so, not in a closure, for example?
[21:11] isaacs: you shouldn't set it inside of some other function that has to be called at some point later.
[21:12] isaacs: you can do it in a closure, that's fine, as long as it's a function that'll run when your module is loaded.
[21:12] jed_: ah, okay.
[21:12] isaacs: don't do it inside a setTimeout, though, for instance.
[21:12] jed_: i can't really imagine a scenario where you wouldn't do that.
[21:12] isaacs: exports.break = function () { module.exports = "blarg" }
[21:12] isaacs: that's bad.
[21:12] jspiros_ has joined the channel
[21:12] jed_: but exports.break = function () { module.exports = "blarg" }() is okay.
[21:13] isaacs: jed_: sure, but now "exports.break" wont' be exported ;)
[21:13] isaacs: when you set module.exports, then the "exports" object you had is no longer useful.
[21:13] isaacs: it's dead at that point.
[21:13] jed_: ah, of course.
[21:13] robrighter has joined the channel
[21:13] isaacs: personally, i'd like to see just module and require, and make "exports" be a member of module, and tha'ts it.
[21:14] isaacs: but commonjs disagrees with me, and i dont' feel strongly enough to keep debating the point.
[21:14] jed_: isaacs: i hear that.
[21:14] jed_: isaacs: by the way, was it you that was talking about shebang usage in node recently?
[21:15] isaacs: yeah
[21:15] isaacs: apparently, you can't shebang to a shebanged script.
[21:15] jed_: is that documented anywhere?
[21:15] isaacs: you can shebang to a compiled thing, though
[21:15] isaacs: so i wrote a little C program that just shells out to node, and then to my script, and then to the arguments.
[21:15] robrighter has joined the channel
[21:15] isaacs: jed_: http://github.com/isaacs/node-bench/blob/master/src/node-bench.c
[21:15] ryah: isaacs: ?
[21:16] isaacs: ryah: !
[21:16] isaacs: ryah: do you have a snazzier way to do that?
[21:16] robrighter has joined the channel
[21:16] ryah: why not "#!/usr/bin/env node" ?
[21:17] isaacs: bbiab.
[21:17] ryah: in a file called "node-bench"
[21:17] robrighter_ has joined the channel
[21:25] stevestmartin has left the channel
[21:26] gwoo has joined the channel
[21:35] teemow has joined the channel
[21:43] jasondavies: anyone got any best practices for writing/packaging JS modules?
[21:43] ithinkihaveacat_ has joined the channel
[21:44] jasondavies: so far I have (function() { var out = typeof exports == 'undefined' ? exports : this; /* do stuff with out */ })();
[21:44] deanlandolt: jasondavies: do you mean packing for browser deployment?
[21:45] jasondavies: deanlandolt: ideally both for browser deployment and server-side
[21:45] jasondavies: I'm writing some general-purpose parsing libraries and want them to be as usable as possible
[21:45] deanlandolt: runjs is one approach
[21:46] jasondavies: thanks, reading up on it now
[21:46] jed_: jasondavies: kris kowal had a nice approach: http://gist.github.com/281374
[21:47] deanlandolt: there's been some work in tusk to wrap a module with the kind of boilerplate you mention above...
[21:47] deanlandolt: yeah, what jed_ said :D
[21:47] jasondavies: jed_: ah, I've been looking for that, I'd forgotten to bookmark it when I first saw it, thanks :)
[21:50] paulca has joined the channel
[21:51] unom1 has joined the channel
[21:56] sixtus42 has joined the channel
[21:57] isaacs: ryah: i do that, but i want to have something like #!/usr/bin/env node-bench in a file that exports the bench test.
[21:58] isaacs: jasondavies: i think you have that code backwards.
[21:58] isaacs: var out = typeof exports == 'undefined' ? exports : this;
[21:58] isaacs: shouldn't that be var out = typeof exports == 'undefined' ? this : exports; ?
[21:58] jasondavies: isaacs: oops, that was meant to be !=, yes
[22:00] isaacs: oh, or that, sure
[22:00] jasondavies: thanks :)
[22:00] jasondavies: that gist (http://gist.github.com/281374) is what I was aiming for so I think I'll use that as a starting point
[22:01] isaacs: ryah: so, if you have a node program that you want to use as a script interpreter, then it doesn't work so good.
[22:01] isaacs: jasondavies: that's clever.
[22:04] ryah: isaacs: ah okay
[22:08] isaacs: ryah: my dumb little c hack seems to work alright, though
[22:08] mikeal has joined the channel
[22:08] isaacs: basically, it compiles a program that just calls "node /path/to/node-bench.js {args}"
[22:09] ryah: couldn't you do that with node?
[22:09] ryah: start a childproces?
[22:10] ryah: i guess then you need to pipe all the data
[22:11] mikeal: what about that bug in the stdio read event handler?
[22:11] mikeal: you can't just write to the subprocess stdio because the read events aren't firing
[22:14] isaacs: ryah: yeah, i wanted to get around the stdio issue
[22:14] isaacs: also, i rather like writing the script to just be a plain old commonjs module.
[22:14] isaacs: i really think tlrobinson's Jack does that well.
[22:23] deanlandolt: isaacs: i was thinking that it could be pretty nice to layer node's stream api onto jsgi as the request.body and response.body...with jsgi-as-is plus async stream bodies i think we can pretty well cover 100% of the async use cases
[22:23] isaacs: hm... i'm not convinced.
[22:23] isaacs: how would i filter the output? could i still do that?
[22:23] deanlandolt: filter the response body output in middleware?
[22:23] deanlandolt: sure, couldn't we just tack a listener onto response.body?
[22:24] deanlandolt: you could filter the input in the same manner
[22:24] isaacs: i see.
[22:24] dnolen_ has joined the channel
[22:24] isaacs: that's not too far from what i'm doing, actualy
[22:25] isaacs: i'm just using an EventEmitter for it
[22:25] deanlandolt: yeah, that's kinda what i figured
[22:25] deanlandolt: to me that's just an implementation detail though
[22:25] isaacs: sure
[22:25] deanlandolt: we can duck-spec the stream behavior
[22:25] isaacs: if it's functionally equivalent, and just a matter of matching syntax, i'm all about that.
[22:26] isaacs: the syntax in ejsgi sucks, and i'd much rather merge it into jsgi-as-is if there's a clean and easy way to do that.
[22:28] deanlandolt: would it acceptable to return the response as a promise with its body as a stream?
[22:28] deanlandolt: that would dovetail nicer into jsgi
[22:28] isaacs: deanlandolt: i'm not sold on promises for jsgi
[22:28] isaacs: it feels wonky
[22:28] ryah: me neither
[22:28] jed has joined the channel
[22:28] deanlandolt: fair enough...have a look at pintura...it's pretty sexy actually
[22:29] isaacs: i'd rather a "return now, but you're not getting the body until later" kind of approach.
[22:29] deanlandolt: that's a promise, ain't it?
[22:29] mikeal: NGI FTW!
[22:29] mikeal: hehe
[22:29] deanlandolt: so something like this never even needs to worry about promises: http://github.com/kriszyp/pintura/blob/master/lib/jsgi/rewriter.js
[22:30] deanlandolt: and something like this just uses "when" to make things insanely simple http://github.com/kriszyp/pintura/blob/master/lib/jsgi/pintura-headers.js
[22:30] deanlandolt: return when(nextApp(request), function(response){ ... that's all there is to it
[22:31] jed: promises seemed to be getting a little verbose for me, so i got rid of them: http://github.com/jed/fab
[22:31] isaacs: deanlandolt: not really
[22:32] jed: (fab) now handles all cases of async/streaming, with minimal added API.
[22:32] deanlandolt: i don't follow...you've effectively added one line of code and you get async headers...async streaming body is a little more complicted, sure
[22:32] okito has joined the channel
[22:32] isaacs: deanlandolt: i believe you asked for this this morning, yes? http://github.com/isaacs/ejsgi/blob/master/examples/read-body.js
[22:33] deanlandolt: pretty much, yeah
[22:33] isaacs: i gotta run.
[22:33] isaacs: network setup, weeee
[22:33] isaacs: i <3 it
[22:33] deanlandolt: just an addListener for body and finish...nice
[22:33] deanlandolt: later isaacs
[22:33] mikeal: what does http://nodejs.org/api.html use?
[22:34] mikeal: is it just static HTML or is it built with something?
[22:34] deanlandolt: asciidoc iirc
[22:34] rednul_ has joined the channel
[22:42] cloudhead has joined the channel
[22:46] felixge has joined the channel
[22:47] jed has joined the channel
[22:49] eck has joined the channel
[22:51] gwoo_ has joined the channel
[22:54] isaacs has joined the channel
[23:03] jed has joined the channel
[23:11] sixtus42: ryah: re
[23:13] gwoo has joined the channel
[23:14] ryah: sixtus42: hey
[23:14] sixtus42: ryah: gotta love you being on the west coast :-)
[23:16] sixtus42: I was wondering what the most efficient way is to read a file backwards. i.e. look for a certain pattern and read the json structure afterwards
[23:16] ryah: shrug
[23:16] ryah: :)
[23:16] ryah: i guess stat its length
[23:16] sixtus42: at least I don't have to feel stupid now :-)
[23:16] isaacs: binary search!
[23:16] isaacs: hehe
[23:16] ryah: read chunks backwards
[23:17] r11t has joined the channel
[23:17] sixtus42: isaacs: close. I am trying to implement a b+ tree
[23:19] sixtus42: ryah: ok. any idea what to use as the pattern to search for? if I use toJSON, i will never see a \n (unescaped of course) in the output, right?
[23:19] isaacs: sixtus42: unless you pass it format args
[23:20] isaacs: JSON.stringify(foo, null, 2) <-- pretty-prints "foo" with 2 space indents and no formatter function.
[23:20] sixtus42: isaacs: yes. but if I only use a single param, it will never output \n, right?
[23:20] isaacs: sixtus42: correct
[23:20] isaacs: you can put a json object on each line if you want.
[23:20] isaacs: and split on \n to stream them out.
[23:22] sixtus42: isaacs: that's what I was thinking. now, I just need an efficient algorithm to do that backwards :-)
[23:22] isaacs: why backwards?
[23:22] isaacs: but, as ryah suggested, you can stat the file, and then pull out a 1024 byte chunk starting at (length - 1024), and then continue like that.
[23:23] isaacs: keep moving back by 1kb each time
[23:23] isaacs: single byte reads would probably be dumb
[23:23] sixtus42: and then I can use a regex to look for the last \n ?
[23:23] isaacs: or just chunk.lastIndexOf("\n")
[23:23] isaacs: if it's -1, then keep looking
[23:24] sixtus42: true
[23:24] isaacs: sixtus42: you on the west coast, too?
[23:24] sixtus42: so, considering a file that's written with JSON.stringify only, which file encoding is best and fastest?
[23:25] sixtus42: isaacs: nope. berlin. ryan used to be in my timezone, but's it's past bedtime here
[23:25] isaacs: oic
[23:25] isaacs: sixtus42: probably utf16, i'd imagine.
[23:25] isaacs: but ryah could probably be more instructive there.
[23:26] sixtus42: doesn't JSON.stringify() escape everthing to 7bit and allow be to use ascii encoding?
[23:26] isaacs: oh, i think it actually uses utf8, but i'm not sure
[23:26] sixtus42: node> JSON.stringify("ä");
[23:26] sixtus42: "\"\\u00e4\""
[23:26] isaacs: i know that a lot of utf chars get through, which is actually a problem.
[23:27] sixtus42: so, I should keep the encoding at utf-8 then
[23:28] sixtus42: ryah: do you have a definite answer to the JSON.stringify encoding?
[23:28] isaacs: sixtus42: or you could call it "binary" and just have faith.
[23:28] isaacs: :)
[23:28] r11t has joined the channel
[23:29] ryah: sixtus42: not sure what you're trying to do
[23:30] isaacs: deanlandolt: still around?
[23:30] sixtus42: ryah: serialize lots of JSON into a file. use \n to find the split points between them. just wondering what encoding to use
[23:31] ryah: sixtus42: hmm. i don't know. i guess utf-16 would be good - but i don't think you can do that with node
[23:32] mikeal: isn't JSON uft8?
[23:32] ryah: is json always ascii?
[23:32] sixtus42: ryah: v8's JSON seems to be always ascii. but I don't know for sure
[23:33] mikeal: javascript is usually utf8
[23:33] ryah: yeh, probably
[23:33] ryah: so use that :)
[23:33] mikeal: Python's JSON libraries specifically set keys to unicode
[23:33] isaacs: http://json.org/string.gif
[23:33] isaacs: a string in json is "any unicode other than \ or "
[23:33] isaacs: on a "control character"
[23:34] isaacs: an issue came up recently on yql where a \u8020 (i think that was it) would break if interpreted as jsonp
[23:34] isaacs: because json allows it, but javascript doesn
[23:34] isaacs: t
[23:34] sixtus42: isaacs: I know. but it says CHARACTER, nothing about bytes
[23:34] ayo: JSON text SHALL be encoded in Unicode. The default encoding is
[23:34] ayo: UTF-8.
[23:34] ayo: http://tools.ietf.org/html/rfc4627
[23:35] sixtus42: yes to all. just wondering what v8's native JSON.stringify outputs. because it sure looks like ascii
[23:35] isaacs: there ya have it
[23:35] isaacs: encoding everything down to ascii is allowed,but not required.
[23:35] isaacs: it IS required to be utf8.
[23:35] isaacs: and ascii always is
[23:36] sixtus42: I know, but I also know that node's doc reads to avoid utf8 where possible for performance reasons
[23:36] sixtus42: JSON.stringify("\u8020") === "\"\\u8020\""
[23:39] isaacs: sixtus42: if you're going to be the only consumer of this, then does it really matter? why not just use binary, and then read it as binary, and trust that it'll work?
[23:39] isaacs: or ascii for that matter.
[23:39] isaacs: but binary feels safer to me.
[23:39] isaacs: though you'll have a bigger file
[23:40] sixtus42: isaacs: where's the difference? binary is 8bit and ascii is 7bit?
[23:40] sixtus42: or is binary 16bit with 8 leading 0?
[23:41] mikeal: when javascript was first specified unicode was 8 bit, which is why it's utf8 and does not support utf16
[23:42] sixtus42: afaik javascript ist utf16 internally
[23:43] mikeal: no, it's not
[23:43] sixtus42: but utf never was 8bit
[23:44] sixtus42: the early assumption was that utf16 will be sufficient, but that didn't hold
[23:44] sixtus42: so utf16 still might escape, which happens a lot in utf8
[23:44] mikeal: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Unicode
[23:45] mikeal: utf16 is available through escape sequences
[23:47] mikeal: "The character encoding of JSON text is always Unicode. UTF-8 is the only encoding that makes sense on the wire, but UTF-16 and UTF-32 are also permitted."
[23:47] mikeal: http://www.json.org/fatfree.html
[23:48] sixtus42: mikeal: this is getting offtopic. The question simply was, if v8's native JSON.stringify will produce ascii, because I was unable make it produce utf8.
[23:48] mikeal: JSON.stringfy will produce a "string" object
[23:48] sixtus42: the second I leave the ascii codepage, it seems to produce \u escaping
[23:52] mikeal: so
[23:52] mikeal: since JSON only supports unicode
[23:52] mikeal: stringify() will create a javascript "string" object that uses unicode escape characters
[23:53] sixtus42: mikeal: and will it do so for all characters beyond \u007F ?
[23:54] mikeal: i would imagine it depends on the implementation
[23:54] mikeal: if you pass it a string that needs to be encoded to JSON, it probably won't mess with those characters
[23:54] isaacs: sixtus42: one thing is for certain: the bytes that JSON spits out can be parsed by JSON.
[23:55] isaacs: just use binary.
[23:55] mikeal: and it may or may not convert ascii character code
[23:55] mikeal: er codes
[23:55] isaacs: mikeal: actually it definitely does, at least in v8, today
[23:55] isaacs: sys.puts(JSON.stringify("\u000A")) outputs "\n"
[23:55] mikeal: very nice
[23:56] isaacs: similarly, if you put some vanilla unicode chars like ü or é in the string, it'll \u them
[23:56] sixtus42: that's what I keep telling you people... it looks like v8's JSON.stringify is 7bit safe
[23:56] mikeal: isaacs: i'm pretty sure that the string object did that on it's own and didn't have anything to do with the JSON parser
[23:56] sixtus42: and I just wanted to know, if I am allowed to rely on it
[23:56] mikeal: node> "\u000A" === '\n'
[23:56] mikeal: true
[23:57] sixtus42: puts(JSON.stringify("ß"))
[23:57] sixtus42: "\u00df"