Re: non-self referencial cyclical promises?
With Mark’s direction, the v2 branch of Q handles "vicious cycles" through the WeakMap that maps promises to their underlying handler. Whenever a promise is resolved with another promise, it walks forward through the chain of promises that the promise handler "became" through resolution. The first promise’s initial handler is a "vicious cycle" rejected promise handler, so if the walk forward through the resolution returns to itself, it remains resolved to the vicious cycle. https://github.com/kriskowal/q/blob/v2/q.js#L181-L204 On Wed, Feb 24, 2016 at 11:38 AM Bradley Meckwrote: > I was doing some recursive data structure work and ended up with a > cyclical promise that did not use a direct self reference. It can be > reduced down to: > > ```javascript > var af, a = new Promise(f=>af=f); > var bf, b = new Promise(f=>bf=f); > > af(b);bf(a); // the problem > > a.then(_=>_) // some env/libs need this to start checking status > ``` > > According to https://tc39.github.io/ecma262/#sec-promise-resolve-functions > it looks like this should cause a recursive and infinite set of > `EnqueueJob("PromiseJobs",...)` > > This code currently does strange things in stable browsers, but doesn't > seem to always cause infinite loops in the nightly builds of some things. I > was wondering what the expected behavior is here because I am having > trouble making sense of things. > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: `await null` to stay in the same tick?
Await yields to the event loop unconditionally. This is useful for spreading CPU-bound work across multiple events. You can explicitly await conditionally. ``` if (guard) { await guard; } ``` On Sun, Feb 7, 2016 at 1:39 PM /#!/JoePeawrote: > I'm not sure where's the best place to ask, but if I > > ``` > await null > ``` > > in an async function does that guarantee that the following code will > execute immediately (control flow will not go anywhere else)? > > - Joe > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Return value of forEach
forEach should return undefined. Array-like methods for iterators solve the problem of building unnecessary memory pressure for intermediate maps. The return value of forEach is special. True, for arrays it is always undefined. However, the forEach method on an iterator returned by a generator function should be the return value of the generator. Consider this range generator that returns the number of visited values. ```js function *range(start, stop, step) { for (var index = start; index < stop; stop += step) { yield index; } return (stop - start) / step; } var iterator = range(0, 10, 1); var iterations = iterator.forEach((x) => console.log(x)); console.log(iterations); ``` Kris Kowal On Fri, Oct 16, 2015 at 7:30 AM, Andrea Giammarchi < andrea.giammar...@gmail.com> wrote: > That's usually a made-up issue ... the example code is using two maps > instead of computing the entire thing once in a composed function **and** > it already creates multiple copies of the initial Array. > > Anyway, having `var log = DEBUG ? x => console.log(x) || x : x => x` in > means you could do this: > > ```js > const a = log([1, 2, 3] > .map(square)) > .map(plus1) > .reduce(add); > ``` > > but again, we are using multiple maps and a reduce so if we want to be > realistic, and it's for debugging purpose only, I think using map would be > just fine. > > Regards > > > On Fri, Oct 16, 2015 at 3:17 PM, Eric Devine <devin...@gmail.com> wrote: > >> Array#map does the non-trivial operation of copying the entire array. In >> the example for loging to the console, this behavior is unintended. Perhaps >> an underscore-like tap method should be considered to be added to the Array >> prototype for these cases. >> >> >> On Fri, Oct 16, 2015 at 9:32 AM, Andrea Giammarchi < >> andrea.giammar...@gmail.com> wrote: >> >>> Like I've written before, if you need to return an array you can use map >>> instead of forEach >>> >>> `arr.map(x => console.log(x) || x)` >>> >>> forEach has been like this since ever so while you wonder what kind of >>> code would look like based on the fact forEach doesn't return anything, I >>> actually wonder how come there are still people expecting forEach to return >>> something. >>> >>> So, it would be a breaking change and actually it's not needed since you >>> have map. >>> >>> If the new Array, and for debugging purpose, is not desired, use `var >>> log = DEBUG ? x => console.log(x) || x : x => x` and abuse it as much as >>> you like. >>> >>> Would any of this work? >>> >>> Regards >>> >>> >>> >>> On Fri, Oct 16, 2015 at 2:23 PM, Niloy Mondal <niloy.monda...@gmail.com> >>> wrote: >>> >>>> > That'd be a compatibility break. >>>> >>>> Ugh... you mean people actually depend on `forEach` returning >>>> `undefined` (which it always does) to do further task? >>>> >>>> I wonder what that kinda code would look like >.< >>>> >>>> On Fri, Oct 16, 2015 at 6:08 PM, Frankie Bagnardi <f.bagna...@gmail.com >>>> > wrote: >>>> >>>>> That'd be a compatibility break. >>>>> >>>>> If we end up getting :: though: >>>>> >>>>> ```js >>>>> function logEach(){ >>>>> this.forEach((x) => console.log(x)); >>>>> return this; >>>>> } >>>>> >>>>> >>>>> const a = [1, 2, 3] >>>>> .map(square) >>>>> ::logEach() >>>>> .map(plus1) >>>>> .reduce(add); >>>>> ``` >>>>> >>>>> You could make that a global variable so you can sprinkle it around >>>>> your code in development. >>>>> >>>>> Having some developer tools in the language would be nice though. I >>>>> don't even think console.log is in the spec. A global like Debug.logThis >>>>> for example would be a more general ::-able. >>>>> >>>>> >>>>> On Fri, Oct 16, 2015 at 5:32 AM, Andrea Giammarchi < >>>>> andrea.giammar...@gmail.com> wrote: >>>>> >>>>>> ```js >>>>>> const a = [1, 2, 3] >>>>>> .map(square) >>>>>> .map(x => console.log(x) || x ) >>>>>> .map(plus1) >>>>>> .reduce(ad
Re: RegExp.escape
I believe you need to champion the issue. Create a Github repository and start editing the fragment of the spec. I do not believe that the issue is contentious. The color of the shed is obvious. The only thing missing is a champion willing to do the writing. On Fri, Jun 12, 2015 at 10:52 AM, Benjamin Gruenaum benjami...@gmail.com wrote: Reviving this, a year passed and I think we still want this. We have even more validation than we had a year ago (added by libraries like lodash) and this is still useful. What would be the required steps in order to push this forward to the ES2016 spec? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Integrating the Webs' dependency systems
This is a great observation, often shared. I recall a related conversation about a year ago, that echoed a proposal from Yehuda a year prior yet (to which I hope Yeuhuda can exhume a link). https://twitter.com/kriskowal/status/400703578605486080 And James Burke brought up some ideas on the topic. https://gist.github.com/jrburke/7455354 It would be lovely if HTML could be trained to resolve URL’s through the module system. The module system may provide a level of indirection, so x/y.css might follow x into another package. Resolving ultimately to URL’s allows, as Alex Russel insists, keeps the issues of resolution, packaging, caching, bundling, web components, and service workers all orthogonal. The issue of how to implement packaging and module identifier resolution can, as John J. Barton points out, be left as a community exercise in custom implementations of System, e.g., one compatible with npm. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Integrating the Webs' dependency systems
On Tue, May 27, 2014 at 3:04 PM, Ian Hickson i...@hixie.ch wrote: On Tue, 27 May 2014, Kris Kowal wrote: It would be lovely if HTML could be trained to resolve URL's through the module system. By HTML here I presume you mean the underlying Fetch mechanism. Could you elaborate on exactly how this would work? Would this be in the layer before or after Service Workers? Supposing that a page has both a service worker and a custom loader, I would expect all requests for URL’s in the page (href, src, etc) to 1. pass through the page’s loader 2. pass through the browser's fetch mechanism 3. pass through the service worker 4. pass through the browser's fetch mechanism again 5. possibly arrive at the true service 6… proxies all the way down? Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.prototype.last()
I am in favor of last() and first() particularly because other collections like queues and sorted sets can implement it and grow the common interface of ordered collections. I also favor the last() and first() bike-shed colors. I wrote a query and binding language that already uses these forms. http://documentup.com/montagejs/frb/#tutorial/last Kris Kowal On Tue, May 13, 2014 at 11:54 AM, Dmitry Soshnikov dmitry.soshni...@gmail.com wrote: Hi, Exactly at the moment I'm writing too many of entries[entries.length - 1] where `entries` is an array (with of course moving to a helper function/prototype method). Will it make sense to add it now to ES6? For consistency with Object.keys(), it could be exactly a function, not a getter: entries.last() For correlation with entries.length, it could be the getter, yes entries.last Both work well, just need to peek more practical. The pop() is similar, but removes the element. (the issue was discussed before, not sure whether it was decided not to include it, or was it's just forgotten - don't see it in the draft, but seems the useful thing: if not for ES6, probably for ES7) (Alternative: entries.peek()) Dmitry ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: RegExp.escape
Continuing a 2 year old thread. http://esdiscuss.org/topic/regexp-escape ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise.cast and Promise.resolve
In this case, a half pursuit of type purity is a side quest at the expense of users. Having two ways to resolve and two ways to observe a promise is unnecessarily confusing. In my experience, one method like then, that unwraps recursively, and one function, like Promise.cast, that automatically lifts if necessary, and then handlers that return into the waiting hands of Promise.cast are coherent and ergonomic. Having a choice between cast and resolve and a choice between then and chain, will leave developers unnecessarily confused and worried all the while they use or abandon Promises as too subtle. For quite some time, grammarians have been losing a war to impose Latin purity on English, in the case of split infinitives. Not long ago, the famous phrase, to boldly go, were a racy departure from convention because in Latin, the infinitive verb to go, is a single word, and you simply would not break the word in half to put a poetic adverb between the syllables. English is not Latin, and JavaScript is not Haskell. Auto-lifting/unwrapping promises are beautiful. Purely monadic promises are beautifully captured by type theory. But, I would pick one or the other over one with multiple personalities. I would pick Promise.cast and then, let complexity melt off the spec, and stop worrying. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Weak callbacks?
One of the concerns with promises is that they consume exceptions that may or may not be handled. I have been looking forward for WeakRef as one of the avenues available to mitigate this problem. A post-mortem finalizer would be able to surface an error that was trapped by a promise or promises that were eventually garbage collected, and therefore provably never-to-be-handled. It is true that this problem can be decisively mitigated in other ways, like requiring a promise to forward to a terminal done() in the same turn of the event loop, but I find this particular solution unpalatable. I do find a promise inspector compelling, one that will show an error until it is handled, but even in this case, I think it is compelling to visually elevate an unhandled error to a provably never-to-be-handled error, and this is not possible, at least outside chrome-space, without WeakRef. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promises: final steps
My colleagues and I are working on an extension for Chrome Web Inspector that can communicate with promise libraries, particularly Q, over the window message port. The tool, which will be renamed and rewritten before it is ready for general use, adds a Promises tab to Web Inspector that shows all currently pending and unhandled asynchronous errors, as well as stack traces for both, and also progress information, albeit determinate, indeterminate, or indeterminate but lively. There is a video accompanying for demonstration. https://github.com/montagejs/continuum https://www.dropbox.com/s/2h68ax9j5mj7i6c/continuum.mov The promise client broadcasts when a promise is deferred, when a deferred promise is resolved, when a deferred promise makes progress (through the `deferred.notify` interface), when a fulfilled promise is created, when a rejected promise is created, and when a rejection is handled. As such, the inspector can reconstruct whatever portion of the program’s promise history it elects to retain. In time, I intend to formalize a protocol. Ideally this system would be useful for both “primordial” and library promises, and combinations of both. Of course, any assistance would be valuable. Also, ideally this would approach the functionality available to Causeway and perhaps even *become* a manifestation of Causeway. https://code.google.com/p/causeway/wiki/CausewayIntroduction It would certainly be possible to show promises in multiple contexts, including cross-origin iframes, and even show time sequence / Stevens graphs for message passing between promises in multiple JavaScript contexts, when promises are used as proxies for remote objects through a facility like Q-Connection https://github.com/kriskowal/q-connection Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Optionally ignoring case in String.prototype.contains()?
Perhaps the second argument of `contains`, `startsWith`, and `endsWith` should be consistent with the second argument of the `RegExp` constructor. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Optional Strong Typing
On Fri, Aug 23, 2013 at 1:20 PM, J B por...@gmail.com wrote: https://mail.mozilla.org/pipermail/es-discuss/2008-August/006837.html This is depressing. J B, You’re entitled to a dissenting opinion. However, this archives one of the best moments for the evolution of the language. It was a commitment to focus on deliberate, consistent, incremental change. We are realizing the rewards for the Harmony agenda today with property descriptors (which formalized and exposed an existing concept), new collections, and Proxies. The cesura on namespaces have provided an opportunity for much much more deliberately designed modules. Innovation has returned and the pace is good, neither hasty nor stagnant. That said, note that your sentiment has been graciously heard. What you are asking for is well-represented by rigorous research going into TypeScript, which is very closely aligned with work and proposals that came out of these discussions. I believe it is fair to interpret Brendan’s last sentiment, “This again puts unsound warning types outside of the standards track for a while. But carry on with TypeScript etc. — TC39 is tracking”, not as “no”, but as “not yet”. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: July notes: copySlice -- copyWithin ??
The name `copy` matches my intuition for the behavior described, as informed by the shell command `cp source target` and other precedents. I would expect `clone` to return a deep copy, as in `Object.clone(object, depth=Infinity, memo=Map())`, informed by the Java precedent, and I would not be perturbed by `copy` and `clone` coexisting as such. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: SortedArray in JavaScript?
On Sat, Aug 10, 2013 at 3:19 AM, Forbes Lindesay for...@lindesay.co.uk wrote: I doubt you want to let it be indexed using `[]` and I see little reason why it would need to be built into the language. It would make far more sense as a nice little library, which creates a much smaller maintenance burden. For example, https://github.com/montagejs/collections/blob/master/sorted-array.js ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: [Map/Set] Add an .update() method, a la Python?
I’ve found it satisfyingly idiomatic to call this `addEach` (for both maps and other collections) in my work on Collections[1]. [1]: https://github.com/montagejs/collections ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Where'd Promise#done go?
As Domenic mentions, there will be no place for done in our bright promise debugger future. It will however be necessary for promise users to keep on ending their chains with done() until promise debuggers are ubiquitously available. This is a simple problem. If you are writing code that targets both old and new engines, the promise polyfill will simply have to patch a no-op done onto the engine’s Promise.prototype. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: The Paradox of Partial Parametricity
Tab’s proposal as I understand it is to standardize Q-like promises and add a chain method that is then but with behavior tailored for monadic composition. This sounds like a good compromise. The only downside I can contrive is that it gives users, particularly novices, a subtle choice. Would it be more clear that it is intended for monadic composition if the name were literally bind? Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Do futures represent a pipeline? (was Re: Future cancellation)
On Wed, May 1, 2013 at 9:13 AM, Tab Atkins Jr. jackalm...@gmail.com wrote: The reasoning behind promises/futures is explained in more detail in my blog posts A while back, I also wrote up an explanation of promises starting from base principles. https://github.com/kriskowal/q/blob/master/design/README.js Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: WeakMap better than Private Symbols? (was: direct_proxies problem)
As an aside, Irakli Gozashvili and I independently realized that you could use a WeakMap for parallel objects with inheritance. Very similar to Brendan’s createStorage, we put together a parallel universe constructor. function Parallel(root) { var parallel = new WeakMap(); root = root || null; function get(object) { if (!parallel.has(object)) { parallel.set(object, Object.create(get(Object.getPrototypeOf(object; } return parallel.get(object); } return get; } Irakli’s was a Namespace constructor that appeared somewhere in the Mozilla Add-on toolkit, but the links have gone stale. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Designing a MultiMap (in DOM, would like to be consistent with ES)
Perhaps consider .push(key, …values) instead of .append(key, value) and .appendAll(key, values). I’ve seen this kind of MultiMap around, so I presume people like the heterogenous range type. I’ve gone a different way in my work, where MultiMap was a Map that would set the value for a missing key to an empty array. Then, extended Array to have a one or only method. getAll(key) ~ get(key) get(key) ~ get(key).one() setAll(key, values) ~ set(key, values) set(key, value) ~ set(key, [value]) append(key, value) ~ get(key).push(value) appendAll(key, values) ~ get(key).push(...values) For the URL use case, this loses information about interleaving of keys, which is usually unimportant except (perhaps) in making round trips between parse and stringify. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: [Bug 20019] Support subclassing ES6 Map
On Tue, Nov 20, 2012 at 10:57 AM, Mark S. Miller erig...@google.com wrote: Since Map and Set will be in ES6 and MultiMap is trivially implementable from these, we can wait until we see some experimental implementations before standardizing. Hence the ES7 target. Here’s my experimental implementation, in terms of my Map shim. https://github.com/kriskowal/collections/blob/master/multi-map.js ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Map.prototype.clear method
On Mon, Oct 22, 2012 at 10:58 AM, Yehuda Katz wyc...@gmail.com wrote: What about copying of these new data structures? The polyfills I have also do .clone(depth_opt, memo_opt), where memo is a map that breaks cycles and depth defaults to Infinity, 0 means return this, and 1 is a shallow copy. https://github.com/kriskowal/collections Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: global object in strict mode
On Fri, Aug 24, 2012 at 10:41 AM, Brendan Eich bren...@mozilla.org wrote: I'm not sure what the problem is -- I read the old thread, and noticed the solution: var global = Function(return this)(); This is good for any code mode, strict or non-strict. Does CSP ban Function as well as eval? CSP does forbid the Function constructor, by the edict “Code will not be created from strings”. http://www.w3.org/TR/CSP/ Section 4.2 “If unsafe-eval is not allowed…” Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Protected Protocol
On Tue, Apr 3, 2012 at 1:49 AM, David Bruant bruan...@gmail.com wrote: Le 02/04/2012 17:59, Irakli Gozalishvili a écrit : I remember that one of your complaints about namespaces was that inheritance was not supported. Do you think there is a workable middleground between namespaces and what I've showed here that would have the benefits of namespaces and inheritance? Yes, prototypical namespaces are a slight revision away, and I believe Irakli has already integrated that change in Jetpack. https://gist.github.com/2047799 This gist illustrates parallel prototype chains between namespaces, and how a namespace can have a common ancestor prototype for each instance. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array#sort(prop)
This is all pretty straightforward library work. With Narwhal’s util module and with my previous work on Chiron, I made some small composable tools, in much the same spirit as Jeremy Ashkenas’s work on Underscore. Consider two higher order functions. by(relation) accepts a relation (a function that accepts a value and returns a related value) and returns a comparator. get(name) returns a relation function that retrieves the named property of an object. These compose like: points.sort(by(get(x))) points.sort(by(distanceFrom({x:10,y:20}))) So that much can be done in libraries. What can’t be done without shimming the sort function is a Schwartzian transformation. This is where you do a map/sort/map to reduce applications of the relation, which can double the performance of a sort in the most degenerate case: large completely unsorted array and a costly relation. Some years ago I found that the optimization was beneficial for arrays longer than 3 for a getter relation. function schwartzianSort(values, relation, compare) { return values.map(function (value) { return [relation(value), value]; }).sort(function (a, b) { return compare(a[0], b[0]); }).map(function (pair) { return pair[1]; }); } To facilitate this and the above notation, the comparator returned by the by function was annotated with compare and by properties which were the original relation and comparator. (by accepted an alternate comparator as a second argument; the default had sensible semantics for all same-type pairs of primordials and did not coerce strings to numbers, a noteworthy wart of the existing specified default comparator). The alternate sort (in-place) and sorted (sorted copy) functions would accept any object with a by property (and optional compare property) would invoke the Schwartzian transform. Adding support for this optimization to Array#sort would be interesting, and the interface might provide an opportunity to allow users to opt-in for a more sensible default comparator. If sort receives an object with compare or by properties, it could go through the new code-path. Passing a non-function object would guarantee the more sensible default compare. A more sensible default compare would sort strings lexically, and sort arrays with left-to-right precedence and recurse on each element. Sensible invocations: values.sort({by:relation}) values.sort({by:relation,compare:altCompare}) values.sort({compare}) // if default compare is added in global scope values.sort({}) // default comparator Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Set polyfill with a has method more efficient than O(n)
I think it is fair, for the shimming crowd, to ask objects to implement a `hash` method to return a consistent string. Collection types can degrade to O(n) in the absence of a provided consistent hash, but enhance to O(1) in the best case. This would involve having a two layer internal datastructure, an object that maps consistent hashes - to array buckets - to values for Set or [key, value] pairs for Map. I would also implement Map in terms of Set, just overriding the hash and equals functions to operate on the key portion of each pair in the set. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: simpler, sweeter syntax for modules
On Wed, Mar 21, 2012 at 4:05 PM, Axel Rauschmayer a...@rauschma.de wrote: Honest question: Are nested modules really needed? There is a chance that they would be useful for bundling. Modules can’t be concatenated. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: How about replacing | with -
On Fri, Mar 2, 2012 at 2:30 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: Some examples of this usage of - include: MyObject.prototype - {a:1,b:2} appArrayBehavior-[0,1,2,3,4,5] let subclass = superclass - function () {}; var p = newRegExpMethods - /[a-m][3-7]/ What do you think? Do you like - better than | ? Is it ok to not have it available for some possible future function shorthand? I’ve been contemplating a + symbol. prototype + {a: 1, b: 2} arrayExtras + [1,2,3] let sub = super + function () {}; var p = regexpExtras + /[a-m][3-7]/ There may be little precedent for abusing operators in JavaScript, but in other systems, I would expect adding collections to produce the union of those collections, with precedence given to the right hand operand. In a world where [1,2,3] + [4,5,6] = [1,2,3,4,5,6] and {a:10, b:20} + {b:30} = {a:10, b:30}, I think that + would make sense as an alternative to +, where the result shadows instead of snapshots the left hand side for the same effect until it changes. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: RegExp.escape()
On Sun, Jun 13, 2010 at 7:50 AM, Jordan Osete jordan.os...@yahoo.fr wrote: Hello everybody. How about standardizing something like RegExp.escape() ? http://simonwillison.net/2006/Jan/20/escape/ It is trivial to implement, but it seems to me that this functionality belongs to the language - the implementation obviously knows better which characters must be escaped, and which ones don't need to. +1 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: WeakMaps question ?
On Fri, Nov 11, 2011 at 3:28 PM, Irakli Gozalishvili rfo...@gmail.com wrote: I really need to know why WeakMaps don't accept primitives as keys, can anyone please reply ? It’s because WeakMaps are intended to drop values if the key is garbage collected. A WeakMap guarantees that it will drop its value if it becomes provably inaccessible. This works for non-primitive keys because we can guarantee that once an object has been garbage collected, no future object can be created that would have been identical to it, making the value inaccessible. Once a primitive value like 1 or the string abc has been garbage collected, it is trivial to construct a new value that is identical to the original key, so we could never implicitly garbage collect the value corresponding to a primitive key. Mark Miller has proposed a strong variation of WeakMap, simply Map, that would serve well in cases where items are explicitly collected. http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets As I recall, a variant of Map was considered in the ES4 timeline as well. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Minimal type guards?
On Thu, Oct 13, 2011 at 11:51 AM, Quildreen Motta quildr...@gmail.com wrote: Contracts would be interesting, but perhaps too expensive? fib :: (Number) - Number function fib(n) { return n == 0? 0 : n == 1? 1 : fib(n - 1) + fib(n - 2) } or function fib(n Number) - Number { } Not particularly proposing any syntax though. Not particularly keen on using fixed types though -- as JS is not statically typed and types are not particularly well defined, definitely not something I'd check for is-a relationships --, I'd rather go with a predicate functions, but then that's even more expensive. Quildreen, Your proposal resembles Waldemar’s guards and trademarks. http://wiki.ecmascript.org/doku.php?id=strawman:trademarks http://wiki.ecmascript.org/doku.php?id=strawman:guards You might consider building on these to make a contracts proposal, separating the signatures from the declarations. Alex’s question is whether some subset of these ideas is suitable for rapid consensus. I will refrain from speculating. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: That hash symbol
On Fri, Mar 25, 2011 at 11:24 AM, Brendan Eich bren...@mozilla.com wrote: No problem -- just don't provoke Zeus to unleash the Crock-en ;-). https://mail.mozilla.org/pipermail/es-discuss/2011-February/012761.html Perhaps there needs to be a venue where non-experts can bounce ideas and discuss points of pain with volunteering committee members to reduce noise in this venue. There is little room here for light-hearted discussion and mentoring for members of the community who have less than full-time commitment and years of experience in language design. It's disappointing to be ostracized, but it is true. I also want to see careful and well-wrought steady progress. I remember a former decade when this discussion was impossible to follow, too many bad ideas were too thoroughly discussed, and much time was wasted. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Harmony as a Compilation Target of my Dreams
This is a half-baked idea. Harmony of Brendan's Dreams makes extensive use of new octothorp syntax. There is perhaps another use for octothorp prefixes: to annotate generated JavaScript with line numbers from the source. source.cs: number -= 42 if opposite square = (x) - x * x target.js: var opposite, number, square; #1 if (opposite) { number -= 42; } #2 square = function (x) { return x * x; } This would require some form of annotation to connect the line numbers with the corresponding source code. The connection could be inferred easily given the tacit strawman for Module(text, fileName, lineNo) and I imagine that some similar annotation would be possible on or around a module keyword. It might even be useful to implicitly increment the annotation line number on line breaks to reduce the verbosity so that minifiers can provide similar annotation at little cost. A third use-case would be annotating the sources of statically bundled Simple Modules or whatever succeeds them. I imagine that there would be a need for tools that transform load directives into inline modules, so it would be handy to annotate sources for debugging in that case too. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Harmony as a Compilation Target of my Dreams
On Tue, Feb 8, 2011 at 1:39 PM, Mark S. Miller erig...@google.com wrote: Much better IMO is the tack taken by Java http://blog.csdn.net/dollyn/archive/2009/09/01/4506156.aspx#sourcemapfile, Caja, and ClosureCompiler of generating separate source mapping tables that map from generated text position back to original text position. And I find HOBD's use of # much more valuable. I do not think we should have both uses of # coexist in one language. Ah. With these givens, I agree. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: idea: try/catch and rethrow...?
In Narwhal, we wrote something like this: var thrown = true; try { // something done that might throw thrown = false; } finally { if (thrown) { // exception observed but not caught } } If I recall correctly, and I'm sure it's been noticed that I often don't, this was necessary since we didn't want to baffle Rhino's stack-trace. I don't think this would have been necessary on V8 since stack traces are garnered by the Error constructor, not by decoration at the point of throw. This both illustrates that the feature is not necessary and that the workaround is ugly. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Simple Modules: lazy dependency evaluation
On Thu, Jan 27, 2011 at 7:27 AM, David Herman dher...@mozilla.com wrote: We thought for a while about demand-driven evaluation of modules. There are a couple reasons why I believe it would be too problematic. First, we'd really like to make the act of throwing your code into a module as transparent as possible; changing the control flow would make modules more heavyweight. But more importantly, since as you mentioned, module evaluation can contain arbitrary side effects, evaluating them lazily means laziness with side effects. This makes for really hard-to-understand and hard-to-debug initialization errors, where you end up having to write mysterious top-level imports to force evaluation of modules in particular orders. Laziness + side-effects: bad scene, man. On the opposite side of the argument, I presume that this means that modules are evaluated when their transitive dependencies are loaded. This would imply that the order in which the modules are delivered, possibly over a network using multiple connections, would determine the execution order, which would in turn be non-deterministic. Non-determinisim + side-effects is also a bad scene. Is there an alternate method proposed in Simple Modules for deterministically linearizing the evaluation order? Non-determinism is definitely a greater evil than providing developers a means to explicate the order in which they would like their side-effects to be wrought. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Simple Modules: lazy dependency evaluation
On Thu, Jan 27, 2011 at 9:14 AM, David Herman dher...@mozilla.com wrote: …but it is required to evaluate them in their declared order, deterministically. Would you explain how declaration order is inferred from the contents of the unordered of files? It's clear that the order is at least partially knowable through the order of module declarations within a single file, and that load directives would be replaced with a nest of modules, which is similar in effect to loading on demand if the load directive is considered a point of demand at run-time. And we're guaranteed that there are no files that would be loaded that are not reachable through transitive load directives. I suppose I've answered my question, if all my assumptions are correct. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: New private names proposal
On Thu, Dec 16, 2010 at 1:53 PM, David Herman dher...@mozilla.com wrote: function Point(x, y) { private x, y; this.x = x; this.y = y; ... } than function Point(x, y) { var _x = gensym(), _y = gensym(); this[_x] = x; this[_y] = y; } I tend to disagree with most developers, so take it with a grain of salt that I find the latter form, with all the implied abilities, easier to understand. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: simple shorter function syntax
On Fri, Jul 23, 2010 at 10:08 AM, Trans transf...@gmail.com wrote: [0, 1, 2, 3].map( f(x) {x * x} ) [0, 1, 2, 3].map( fn(x) {x * x} ) [0, 1, 2, 3].map( y(x) {x * x} ) Any of these seem a much nicer choice than '#', IMHO. While I agree on principle, the real challenge here is to find syntax that will not break existing programs by promoting an existing variable name to a keyword. Otherwise, you'd have to look ahead to the curly brace block to distinguish the variable name from the function keyword. It's been a long time since I wrote a parser of this kind, but as I recall, looking ahead is generally hacky. function expression: name, argument list, block Of course, if that approach were taken, the spec might as well forgo having a function keyword at all and use the name or absence of a name to distinguish a named and anonymous function expression. But again, I expect there would be resistance to looking ahead. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Composition of Uncoordinated Working Sets of Modules
On Mon, Jun 7, 2010 at 8:37 AM, Sam Tobin-Hochstadt sa...@ccs.neu.edu wrote: On Sun, Jun 6, 2010 at 2:00 PM, Kris Kowal kris.ko...@cixar.com wrote: ... Most of this is good clarification, particularly that load interacts with the exports of the foreign script's implied, anonymous module scope. The grammar is clear. It would be good for this to be expressed in one of the examples, and for it to be clarified in the description of semantics that every script is also an anonymous module from which the exports are only accessible through the lexical scope shadowing (I assume) and by being bound to a module through a load expression. Right. module M = load foo.js; creates a new module M with foo.js as its contents. This is a point that Ihab clarified for me yesterday evening that merits bold and emphasis: loaded modules are not singletons. You do this to avoid having to compare MRL's for equivalence, particularly to avoid having to define equivalence given the potential abundance of edge cases. http://example.com/module?a=10b=20 http://example.com/module?b=20a=10 It's worth noting, and please dismiss the implication that the approach is necessarily proper and correct, that this is not a problem for CommonJS modules because the specification limits module identifiers to a very small subset of expressible URLs and defers the issue of URLs to the packaging layer, wherein the semantics are similar to those put forth here. * for a script to have importable bindings, these must exist in a module block of the loaded script. I don't know what this means. Ihab clarified that this is not true. This is a re-statement of my mis-perception that there is no implicit, anonymous, top-level module in a script and that therefore there cannot be exports outside explicit module blocks. I stand contentedly corrected on this point. It's possible to use the module loader API to do this, slightly more verbosely. But why? If you say: module A = load aQuery.js; then A.$ is already available for use in expression contexts. I can make the same argument about import *. If I import A, I can access its contents as A.$. To permit destructing on all import expressions would be consistent philosophically. link.js module aQuery_ = load(scripts/aQuery.js); const $ = aQuery_.aQuery.$; Your example might point to a need to augment the module loader api with information on 'load' calls specifying what module the 'load' occurs in. Exactly. The Narwhal loader receives an id and a baseId on from require(id) calls. Each module gets a fresh require effectively bound on the baseId. I think that the loader handler needs to receive the base MRL as an argument or part of the request object. Another thing that Ihab clarified which merits a full section on the wiki is the dynamic scoping of lexical module names. Ihab pointed out that, when a script is loaded, it inherits the module scope chain of the declarer, permitting a certain degree of aspect oriented dependency provision, or external linkage. This depends on an understanding that each load always instantiates a module and cannot ever rebind an existing module (a singleton). loaded.js export function poof(el) { $.poof(el); } aQuery.js export function poof(el) { // one implementation } bQuery.js export function poof(el) { // an alternate implementation } a.js module $ = load(aQuery.js) module X = load(loaded.js); b.js module $ = load(bQuery.js) module X = load(loaded.js); linkage.js module A = load(a.js); module B = load(b.js); Noting that in this example, having loaded linkage, there are two instances of loaded.js, each of which sees $ as aQuery and bQuery respectively. They also see X, A and B following the dynamic scope chain. This is something I have not considered. It would be good to do a write-up on what use-cases you have in mind for this feature. Also note that, because I was not aware of this feature, I've been using the terms external linkage and internal linkage differently, in the context of my first email on this thread. I used the terms internal and external to refer to modules from a given working set of modules from one coordinated design (a package), and to modules outside the package, in other packages. Sorry for the confusion. At this point I have been convinced that it is possible with this proposal to integrate uncoordinated working sets of modules by using the load syntax and script-scoped exports. I've also been convinced that there is a way to inject free variables into an isolated context, as mediated by the loader. I've been made aware that there exists a way to implicitly inject modules when loading scripts, which implies that there is a contract between the loader and loadee that certain free variables in the loadee will be bound through the module scope chain. This provides a finer grain means of weaving dependencies
Re: Composition of Uncoordinated Working Sets of Modules
On Mon, Jun 7, 2010 at 12:10 PM, Erik Arvidsson erik.arvids...@gmail.com wrote: On Mon, Jun 7, 2010 at 10:35, Kris Kowal kris.ko...@cixar.com wrote: Another thing that Ihab clarified which merits a full section on the wiki is the dynamic scoping of lexical module names. This is a common misconception. Simple modules is using static lexical scoping, not dynamic scoping. The thing that might be confusing is that the loaded module is defined in the lexical scope of the module that loaded it. Reviewing the idea, it's certainly not dynamic scoping. If you're very free with the analogy to a function call as established by the syntax, I recklessly intuited that there's a case for it sharing the analyzability problem that dynamic scoping causes, but I have not found such a case. However, you cannot statically observe a reference error on a single script in isolation; you need to know the lexical scope in which it has been loaded. I don't think that's necessarily a problem. It's certainly the same case with any situation where successive script tags have access to the modules declared by previous scripts. Kris Kowal (For anyone observing the political mess I've made, I do plan to do a write-up redacting my claim that Simple Modules can't be used to compose independently designed scripts. I think this is the big issue and I'm glad this design has a solution. I'll continue to ponder the implications for CommonJS and see if I can come up with a migration story that makes sense.) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Composition of Uncoordinated Working Sets of Modules
Supposing that aQuery and bQuery are implemented by independent uncoordinated authors. aQuery.js module $ { } bQuery.js module $ { } If my interpretation is correct, these cannot be combined in a single Application. script type=harmony src=aQuery.js/script script type=harmony src=bQuery.js/script One solution to this problem is to convince A and B to coordinate, which I've hitherto inferred was the only solution supported by Simple Modules, in which case they share a fault with Java. Is this a solution? script type=harmony module A_ = load(aQuery.js); module A = A_.$; module B_ = load(bQuery.js); module B = B_.$; /script With this example, I am inferring that * That the web-browser's loader knows the location of the current page, so it can resolve the MRL based on that location. * load can only be used in the context of an importing module assignment. * conceptually, if not at run-time, load returns a module instance that contains the top-level modules of the given script. * that the top-level modules of the remote script are not registered as top-level modules of the local application, unlike co-DOM scripts. * for a script to have importable bindings, these must exist in a module block of the loaded script. * there is no notation for destructuring a module from a loaded sub-module * a script is not a module, so exports cannot be used at the top level. If that's the case, I would like to refine this approach, such that loaded modules can have exports at the top level. This would permit the function export. aQuery.js export var $ = function () { }; bQuery.js export var $ = function () { }; link.js module A = load(aQuery.js); module B = load(bQuery.js); It would also be good for there to be a way to bind $ without binding a module. const A = load(aQuery.js).$; const B = load(bQuery.js).$; This obviously breaks a load call outside an import clause, which I infer is not possible with the present proposal. Is it possible to decouple name spaces from loaded modules? Another point of interest is transitive loads. I do not think that there is a provision in the specification that would permit load directives to be resolved relative to the location or MRL of the module from which load call is declared. scripts/sazzle.js module Sazzle { } scripts/aQuery.js module Sazzle_ = load(sazzle.js); // relative to // scripts/aQuery.js module Sazzle = Sazzle_.Sazzle; module aQuery { export $ = function () { }; } link.js module aQuery_ = load(scripts/aQuery.js); const $ = aQuery_.aQuery.$; Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Composition of Uncoordinated Working Sets of Modules
On Sat, Jun 5, 2010 at 3:40 AM, Sam Tobin-Hochstadt sa...@ccs.neu.edu wrote: On Fri, Jun 4, 2010 at 9:48 PM, Kris Kowal kris.ko...@cixar.com wrote: On Fri, Jun 4, 2010 at 5:17 PM, David Herman dher...@mozilla.com wrote: By keeping modules second class, we get a number of benefits, not just handling cyclic dependencies. (In fact, cyclic dependencies can be handled nicely in a first-class module system as well.) One of the benefits of second-class modules is the ability to manage static bindings; for example, import m.*; is statically manageable. Allen has made some good points about how second-class modules are a good fit for the programmer's mental model of statically delineated portions of code. At any rate, cyclic dependencies are not the central point. As far as I can tell, Simple Modules only changes the composition hazard introduced by imoprt m.* from a run-time hazard to a link-time hazard. In your example, certainly the earlier error is a benefit of our proposal. I strongly disagree. Either Alice is at fault for using import m.*, Charlie is at fault for altering her API, or neither Alice and Charlie are at fault because they were merely and earnestly using the features of the underlying system, in which case the system is at fault. Alice should be able to trust the features of her module system. Charlie should be able to *augment* her API without breaking her dependents. But the really key benefit is this: module M { export x = 7; } module N { M.y + 3; // an error - just like an unbound variable in ES5 strict } This feature does not preclude the omission of the import * syntax variant. This can be an early error because we statically know a lot about modules. This is good for programmers, because it supports early errors, and also good for compiler writers, since it supports optimization. I agree. I do not think that any of my objections preclude statically linking name spaces. Because Simple Modules is based on lexical scope, collecting modules is as simple as collecting objects into a larger object: module Container { module Sub1 = load http://example.com/foo.js;; module Sub2 = Other.InnerModule; module Sub3 { module SubSub4 = load http://example.org/bar.js;; } } And I presume that usage of submodules is: module Container = load(the script above); module X = Container.Sub1.SubSub4; If that's the case, please consider making the nested module export explicit: module Container { export module Contained { } } I am not attached to the name spaces feature of the Simple Modules proposal, but it's not worth fighting. This is also not true; the ability to attach modules to module loaders (as well as the dynamic evaluation methods) makes it possible for separate module loaders to communicate. However, loaders aren't about linking multiple working sets, but rather providing isolated subspaces. (One use case I sometimes use is an IDE implemented in ES, that wants to run other ES programs without them stepping on its toes.) Code examples would be insightful. Currently, in web-based IDEs such as Bespin, code being developed has the ability to muck with the internal state of the IDE and the overall page, which is usually undesirable. With module loaders, simply by not sharing access to the DOM or other internal state with the code being developed, this would be prevented. I understand and wholeheartedly agree with the why. I do not understand how. Code examples would be insightful. Perhaps I am misunderstanding the scope of a module name. Is it not true that a module is available by its self declared name in all modules that share a loader? Is it actually possible to bind a single module name that provides access to all of the modules in another loader? module X = load(http://example.com/api;); module Y = X.Y; // is this possible? Yes, if that URL has a module Y in the code that it provides. For example, if that URL produces the code: module Y { ... } module Z { ... } Then it's certainly possible. Developers should not need to concatenate subsystems to construct packages. It should be possible for one to connect loaders to other loaders. Is it possible for MRL's to be CommonJS top-level and relative module identifiers? We've avoided committing to particular syntax for MRLs so far, although the discussion at the last meeting tended toward the following syntax: MRL = URL | RelativeURL | @Identifier This notation seems adequate. The question remains whether relative URL's are supported by the proposed loader API. It's my impression that it is not presently possible for a loader handler to observe the MRL of the module that requested the module. If that's the case, it would be the responsibility of the loader itself to resolve MRL's. It would be better if that responsibility were deferred to the loader handler. If that's the case, is it possible
Re: Composition of Uncoordinated Working Sets of Modules
On Sat, Jun 5, 2010 at 2:41 PM, Brendan Eich bren...@mozilla.com wrote: I strongly disagree. Whoa -- I don't see how anyone can disagree that early error is better than a runtime error, if there is an error case at all. It seems to me you're instead arguing that no such error should be possible because import m.* should not be supported -- that you're arguing against any import-everything-that's-exported feature. Right? Yes, we're in agreement that an early link-error is better than run-time error. You are also correct that my argument is that import * should not be supported. It also true that this is not my primary objection and it does not poison the design; it is a side-show. It is also true that this is a value-judgement between the convenience of the feature when used responsibly by wise and scholarly programmers within a system of modules designed in coordination, and the value of protecting programers from the hazard at the cost of that convenience. CommonJS put this to vote. There was support on both sides, but on CommonJS, the feature was sacrificed to get unianimous support. Only Tom Robinson called for the include function (import *) in the final show of hands, but cast his +1 without the feature. http://groups.google.com/group/commonjs/browse_thread/thread/d2dc85a2725992be/4a7fb3943fdd?lnk=gstq=modules+include#4a7fb3943fdd It is likely that it not possible to get a large enough group of people either in support of the feature or against the feature to reach unanimity, and that nobody cares enough either way to block ratification. This is far more likely than that there is consensus either way. The only reason import m.* is in the proposal is that when one is using modules in one's *own* (definitely including the single-author case, but also the single-curator and same-origin-hosted case) larger program, where the hazard of new names can be controlled by testing and auditing, then lack of import m.* is a royal pain. This is especially true during rapid prototyping. Yeah, I've been on both sides of the debate. I got bitten in the ass when I was using from django.models import *, which is naturally a case of using a module in foreign control (which you note is not proper usage) but also very compelling because of the royal pain you mention. I think it would be good to put this issue to vote. I think we're in agreement about the nature of the trade-off and we wouldn't want to make Buridan donkeys of ourselves. I also think we should get a show of hands on whether we should try to decouple name spaces (named module clauses per the simple modules proposal) and modules (as linked with a loader), and whether we need both layers. Meanwhile, I would still like to see examples of how to compose working sets of modules with other working sets of modules that were not designed in coordination. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Composition of Uncoordinated Working Sets of Modules
. Then, using reflective Loader or Linker API, it would be possible to create and use optimized bundles. Furthermore, package mappings could be accomplished if browsers provided a URL Linker/Loader that would automatically fetch and link modules on a particular URL tree. In summary, the problems worth solving include: a.) balancing linkage brevity and uniqueness, with the goal of offloading the global name space problem to DNS, providing reliable sovereignty over name spaces controlled by: * the developer of a single file * the developer of a tree of files * domain owners * IANA b.) elimination of accidental global variables c.) the manual explication of transitive dependencies d.) the manual linearization of execution and linkage e.) mutual dependency f.) the elimination of the need for build steps during development and debugging. g.) decoupling the utterance of dependencies from the order and timing in which dependencies are transported in production. h.) isolation of scopes i.) isolation of internally consistent modules j.) reliable linkage to independently develop, internally consistent working sets of modules Simple Modules will assist individual designers of coherent groups of name spaces for the purpose of producing single internally consistent applications and APIs. Simple Modules, at present, will not sufficiently assist people constructing applications and APIs by composing non-coherent groups of name spaces produced by non-cooperating groups of developers. In any case, that's my two bucks, Kris Kowal [1] http://wiki.commonjs.org/wiki/Packages/Mappings/B [2] http://limi.net/articles/resource-packages/ [3] http://www.chromium.org/spdy/spdy-whitepaper ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Composition of Uncoordinated Working Sets of Modules
is the identifier of the module from which this // module was requested? I need that to resolve the // identifier of the request module. when(fetch(id), request.provideSource, request.reject ); } else { var external = externalLoaders[parts[0]]; request.provideLoader(external, parts.slice(1).join(/)); } }) I think it might be best to organize the syntax around MRL's rather than local short-names. MRL's can be reasonably short if they're permitted to be relative paths, which requires the module loader handler to receive the MRL of the requesting module. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Modules: Name capture
On Wed, Jun 2, 2010 at 12:14 PM, David Herman dher...@mozilla.com wrote: but if you have a module graph of N modules, and each needs to be explicitly linked with N - 1 other modules, then you impose a quadratic code-size requirement on programmers. Unless, as I said, you beef up your linking-specification language. I agree that requiring explicit linking is a non-starter. I do however favor the option of explicit linking at some level of granularity. At reasonable expense, Narwhal provides several layers at which someone can buy-into explicit linking: * by manually instantiating a module using the module constructor proferred by the loader. var module = require.loader.load(id); module(freeVariables); * by manually instantiating a module using a facility of the sandbox that provides the import and export facilities but a.) does not memoize the module and b.) permits additional free variables to be injected. This is useful for creating module-enhanged DSL's that permit scripts designed for QUnit or Bogart to be migrated without alteration, subverting their use of global variables with explicitly injected free variables. require.once(id, freeVariables); * by manually instantiating a system of modules with a preopopulated memo of module instances. var SANDBOX = require(narwhal/sandbox); var subRequire = SANDBOX.Sandbox({ modules: { even: EVEN } }); var EVEN = subRequire(odd); I would invoke the axiom, Simple should be easy, powerful should be possible. It's reasonable to pay for what you get. At the risk of misrepresenting their views, Ihab and Mark have argued that people should always use explicit linking for a variety of reasons, but I for one agree that implicit linking should be the norm, and explicit linking can at least be deferred to the layer of packages, or coherently designed sets of modules linking to other coherently designed sets of modules. I presume that it is possible to isolate and explicitly link groups of modules. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Tech talk on proxies and traits
On Fri, Apr 30, 2010 at 3:42 PM, Tom Van Cutsem to...@google.com wrote: Hi, I recently gave a Google tech talk on my joint work with Mark S. Miller on Harmony proxies and the traits.js library. Below is an abstract and a link to the video. May I recommend that the enumerate method return a forEach-able object, such that: for (x in proxy) … be reified as: handler.enumerate().forEach(…) albeit optimized for proper Arrays? This would permit at least some degree of laziness. I've also been working on a handler API for promises in CommonJS, which has a reasonable degree of symmetry. One thing that's occurring to me is that it is probably desirable for a generic, potentially frozen prototype handler to be exposed so that they can be explicitly prototypically inherited and extended. I'm not sure whether you've specified that handlers must be records, owning all usable trap properties, but that would preclude meta-object hierarchies. I suspect that these will be desirable and that exposing the base handler prototype would be useful. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Tech talk on proxies and traits
On Sat, May 1, 2010 at 6:25 PM, Brendan Eich bren...@mozilla.com wrote: W.r.t enumerate, a proxy could return a proxy for an array. Would be satisfactory if the reification re-checked the length on each iteration. Additionally, enumerate should be modified as soon as there is a solid proposal for generators/iterators. Yeah, I caught that in the preso. Sounds good to me. Dave Herman and I have a generators/iterators proposal coming along -- should be up some time next week on the wiki. Excellent. Not to worry, traps are accessed as handler properties, not own, just in (so possibly in a prototype). See http://wiki.ecmascript.org/doku.php?id=harmony:proxies_semantics. Example: Excellent. Mozilla's implementation (see https://bugzilla.mozilla.org/show_bug.cgi?id=546590) already includes a no-op handler. We envision others that can be reused and delegated to via prototypes. I see, in the unit test, makeNoopHandler. My suggestion was that this should be exposed as part of the API as a base type, but on further reflection, the behaviors of the noopHandler are implied by the non-existence of properties on the handler. This is all excellent and I'm really glad it's getting such deeply detailed attention. Thanks. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
forEach on next
[moving this thread onto es-discuss] On Tue, Mar 23, 2010 at 2:45 PM, Brendan Eich bren...@mozilla.org wrote: On Mar 23, 2010, at 2:17 PM, Kris Kowal wrote: Aside: I hope we can resolve MarkM's suspicions of composability problems with generators; they are one of my very favorite features of Python: like UNIX pipes, composability is their middle-name. The PEP he referenced some time ago just provides more terse syntax for chained generators; I find that this is a nicety but not a demonstration that the simple yield is flawed. Yes, just because something doesn't sing and dance doesn't mean it is not a good actor ;-). I also hope that ECMAScript opts to follow the Python iterator protocol more closely than JavaScript 1.6—for chained lazy iterations, next needs to be the most discrete layer of the protocol, with forEach implemented in terms thereof. JS1.6 was forEach and other Array extras. JS1.7 introduced generators and iterators, and yes, we didn't incompatibly change the Array extras to treat iterators as arrays. We also didn't introduce new libraries, e.g. Python itertools workalikes. It's easy enough to do this in user-land, and hard for the TC39 committee to get library design right. Thanks for the clarification. At this point how would you make forEach and other Array extras work on iterators? I'm getting all sorts of alarms going off in my head to the tune of this is all obvious; I probably missed something important. Like, this is how it works already. I've heard complaints about for each loops stalling to collect though, so here are my thoughts about iterators anyway: I was just looking at some transcoding stream stuff, which follows the general form of Python's iterator protocol. The notion is that next is the most atomic unit of the iterator protocol; if you have an object that implements iterator, that returns an object that implements next, you get forEach and friends for free. This is important because next is pausable (or progress on explicit request, really), and forEach is not. This means that you can create incrementally iterable generics like mapIterator and thereby create chains of decorated iterators that can operate on iterations of indefinite length, and forEach doesn't have to collect the values of the iterable before entering its loop. /*** * @this {Object} */ SomethingAutoIterable.prototype.iterator = function () { return this; }; /*** * @this {{iterator}} any iterable object. `iterator` must * return an object with a `next` method that returns the * next element of the iteration or throws `StopIteration`. */ SomethingAutoIterable.prototype.forEach = function (block, that) { var line; var iterator = this.iterator(); while (true) { try { line = iterator.next(); } catch (exception) { if (exception === StopIteration) break; throw exception; } block.call(that, line); } }; If you're crazy, can optimize the crap out of the try/catches (presumably by removing them for a small set of common types), and want to take things one step further than Python, you can implement both continue and break semantics by adding SkipIteration. …forEach = function (relation, that) { var iterator = this.iterator(); try { while (true) { try { relation.call(that, iterator.next()); } catch (exception) { if (exception !== SkipIteration) { throw exception; } } } } catch (exception) { if (exception !== StopIteration) { throw exception; } } }; And, if you're *really* crazy, you can implement breaking and continuing outer loops by associating individual StopIteration and SkipIteration instances with each iterator. By really crazy, I mean that my PEP got shot down, so I wouldn't be surprised by a repeat success. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: simple modules
On Thu, Feb 4, 2010 at 2:04 PM, Sam Tobin-Hochstadt sa...@ccs.neu.edu wrote: Module Name Manager/Context/Module Loader: An entity that specifies how to find modules, given their names or identifiers. By creating these, programmers can manage what modules can be seen by what code. I think this (or the next item) is what Kris called a Context in his presentation at the face to face meeting. The module primordials proposal includes a Context constructor that creates what is presently an ES execution context and contains its intrinsic primordials. The concept of a Context in that proposal is completely orthogonal from the entity that manages the process of grabbing module code (Load/Loader) or linking and instantiating them (Require, which I've called a Sandbox in the past). It's my impression that the module statement in your proposal is a Registrar, or a module transport declaration [1] that enables modules to be transported in Programs. I do not understand the Linking and Instantiation semantics of the Simple Modules proposal, but it's possible that the concerns of registration, linkage and instantiation have been combined and additionally coupled to what I called the context, in which case it would be appropriate to call the entire entity a Context. However, I think that for the purpose of this discussion, it is desirable to separate the layers and concerns so that we can see the breadth of options. Kris Kowal [1] http://wiki.commonjs.org/wiki/Modules/Transport ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: simple modules
On Wed, Feb 3, 2010 at 12:39 PM, Brendan Eich bren...@mozilla.com wrote: On Feb 2, 2010, at 6:23 PM, Kris Kowal wrote: This verbiage implies black-listing. It would be good to be clear that the object formerly known as a module context should be explicitly populated with a white-list of module instances for SES. Agreed, and good point. Oprah moment: something about the way you wrote makes me want to plead for goodwill assumptions in our informal exchanges. No one on the committee is trying to open up capability leaks or introduce ambient authority. I doubt anyone is unfamiliar with the problems of blacklisting. It seemed clear to me that Dave was not specifying rigorously, just giving two examples. (Ok, group hug :-P.) My tone was definitely severe and the content lacked balancing concessions. My apologies to David. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: simple modules
Would someone mind posting a summary of the current positions of the active participants of this discussion, perhaps contrasting the proposals? Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: simple modules
Presuming that in the proverbial glossary a Context is what ES presently calls an execution context that has some intrinsic Primordials, and a Sandbox is a mapping from unique module identifiers to modules (albeit instances or makers depending on what proposal you're talking about), does this proposal suggest that there is exactly one Context for every Sandbox and that any module block statement evaluated in a context populates the corresponding sandbox with a mapping from the given module identifier to the first class exports object of that module? Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: typed array strawman proposal
On Tue, Jan 26, 2010 at 10:43 AM, Vladimir Vukicevic vladi...@mozilla.com wrote: Howdy, At Brendan's request, I've just added a new strawman proposal for ES typed arrays to the wiki. This proposal comes from the WebGL group, which needed a way of efficient access to and manipulation of native machine-type arrays; once we came up with a reasonable baseline API, it looked like something that would be generally useful as more interop and performance demands are placed on ES. Typed arrays is probably not the best name; but that's probably an easy bikeshed. I've made three similar proposals over in CommonJS. http://wiki.commonjs.org/wiki/Binary/B http://wiki.commonjs.org/wiki/Binary/D http://wiki.commonjs.org/wiki/Binary/E ArrayBuffer is a strict subset of what I'm calling ByteArray (which incidentally fits the TypeArray pattern you establish in your proposal). I think we could converge these proposals. Yours is most similar to Binary/B. Binary/D adds some bit types and improved the details a bit. Bineary/E abandoned the notion that binary types could become natives in CommonJS, removed the bit types, and reduced the API significantly again. To get closer to your proposal, it would probably be easier to start from yours and add rather than start from one of mine and subtract. I recommend ByteArray for the name. It matches the pattern you establish for Integer Arrays. Secondly, I think slice needs to return an immutable fixed length type, or ought not be included. Daniel Friesen proposed a Range type and a range method in Binary/C which I incorporated in D and E. range is like slice but returns a view of the underlying buffer region and supports the relevant subset of the ByteArray API. With range, there is no expectation of indefinite consistency. I think the various aligned typed arrays are a good idea, but I think CommonJS would be satisfied if we were to agree on the byte array buffer type initially. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: quasi-literal strawman
I am also in favor of the quasi-literal type name not being mangled. I would, in fact, consider making the quasi-literal type any expression returning a function, even if this necessitates a parenthetical expression. You might consider refining the escaping rules to resemble rraw strings as in Python. That would afford a greater degree of flexibility in escaping rules within the quasi-literal. The only difference is that in a raw string, only backslash before the same quote character as the enclosing quotes and a backslash are treated as escape characters and all others are preserved. Then, the quasi-literal function would be entirely in control of the meaning of other escaped characters. There's also a trade-off between using back-ticks and plain double-quotes. Using back-ticks affords us an opportunity to have a default quasi-literal. On the other hand, I don't miss having to distinguish front and back ticks in Perl. Also, it might be undesirable to have to claim a variable name for the default case, unless your intention is that the default quasi-literal have a consistent behavior in any scope. In one of my former language projects, I considered something similar for numbers, in suffix. For example: 3ce for thrice or 1mm for one millimeter, where ce and mm were constructors in scope. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Binary Data - possible topic for joint session
On Fri, Nov 6, 2009 at 11:24 AM, Brendan Eich bren...@mozilla.com wrote: Kris did a good job with Binary/B (although I do not see the point of the .get method additions) -- I didn't look at the other proposals yet. Thanks. The .get method is certainly not relevant for an ECMAScript spec, where you have the luxury of specifying [[Get]] and [[Put]]. The .get method in the CommonJS proposal is intended to serve as a stop-gap for implementations that cannot provide properties. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Typo in Annex E
The last paragraph of Annex E notes that getPropertyName is among the divergences from ES3. I presume this is intended to be getPropertyNames with plural infection. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Hermetic Evaluation, Modules Strawman
I've begun my work on a second draft [1] of the module proposal that Ihab and I put forth at the January meeting. Just to get started, I wanted to emphasize that all we need is hermetic evaluation, and re-propose the interface for hermetic eval in light of experience with the CommonJS [2] and Narwhal [3] implementations of the SecurableModules [4] proposal Ihab and I made to that group a week later. We've made a lot of great progress in the last 9 months in vetting the module system idea. This new draft proposes that the primitive hermetic evaluator be more like the Function constructor and permits early exceptions for non-primordial, non-injected free variables. The new proposal is safer since it emphasizes that the module text must be a program construct, makes explicit what names are being injected into the program's scope, and explicates that, unlike with blocks, specific names are injected into a function block scope instead of placing a stock Object in the scope chain. It's my intention to copy and edit sections of the original proposal into the wiki, making minor revisions to match up with CommonJS SecurableModules, the Module meta-object amendment [5], explicate synchronous and asynchronous variations of importing modules, and to specify the API's of module loaders and module sandboxes. Ihab is spearheading an effort on CommonJS to formalize packages of modules, their layout, their metadata, how to verify their signatures, and how to import modules from packages, which I hope to integrate in a future draft. We remain in discord about whether to conflate the name spaces of injected capabilities and modules, but we had a good discussion recently that might help us arrive at a compromise. This all being said, between Object.freeze and hermetic evaluation, we can do a lot in libraries without native language support so it's worth kicking off a discussion around that feature early. Kris Kowal [1] http://wiki.ecmascript.org/doku.php?id=strawman:modules [2] http://wiki.commonjs.org/wiki/CommonJS [3] http://narwhaljs.org/ [4] http://wiki.commonjs.org/wiki/Modules/SecurableModules [5] http://wiki.commonjs.org/wiki/Modules/Meta ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Spawn proposal strawman
kevin curtis wrote: Is a 'canonical' AST part of the plans for ecmascript 6/harmony. On May 9, 2009, at 9:19 AM, David-Sarah Hopwood wrote: I hope so; that would be extremely useful. I would like to see an ECMAScript source - AST parser (as well as an AST evaluator) in the Harmony standard library. On Sat, May 9, 2009 at 11:57 AM, Brendan Eich bren...@mozilla.com wrote: We've wanted this since early in ES4 days. It would help many projects and experimental extensions (type checkers, template systems, macro processors, etc.) to have a standard AST, which could be serialized to JSON. Other neat uses for the AST would potentially include comment scraping for automated documentation tools and minification, which have their own requirements beyond those for execution, optimization, and static analysis. Upon further reflection, I'm not sure that parse(program:String):AST would serve the purpose of fast sandboxing. The intent of splitting parse and execute is to reduce the cost of execution, so that modules can be reused in many small sandboxes. Having parse produce a (mutable) AST, and then leaving execute to translate the AST for the interpreter might constrain our options for producing the desired performance. It might be better to have a compile() routine that returns an opaque, engine-specific Program object that can in turn be executed multiple times. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Spawn proposal strawman
On Mon, May 11, 2009 at 4:21 PM, Brendan Eich bren...@mozilla.com wrote: On May 11, 2009, at 4:10 PM, Kris Kowal wrote: Perhaps I'm behind on the times, but I'm under the impression that presently the behavior of this function foo declaration has no standard behavior: (function () { function foo() { } })(); No, that's fully specified by ES3. Once again, I've been chasing a JS phantom. That cuts the complexity of the options tree roughly in half. Let's consider: let asts = {}; let memos = {}; // loading if (Object.prototype.hasOwnProperty.call(asts, id)) return id; let ast = parse(moduleText); asts[id] = ast; // executing if (Object.prototype.hasOwnProperty.call(memo, id)) return id; let ast = asts[id]; let exports = memo[id] = {}; let require = Require(id); execute(ast, {require, exports}); Furthermore, let's assume that execute enforces use lexical scope and use strict. These are the ramifications if I understand correctly: * free assignment becomes an error at run time. * free variable access, apart from primordials, require, and exports throw reference errors. * the object bearing the primordials has no name. * global object has no name. * the bottom scope has no name. * default this for functions and the bottom-scope is undefined. * function statements are local to the module and only accessible lexically. * var and let declarations in the bottom scope. * require and exports get injected into the bottom scope. What scope contains primordials? Should primordials be injected into the bottom scope before require and exports or should their be two scopes (global, local) in a module? I see several potential definitions of execute: execute(program:AST|String, scope); // wherein we create a new global scope and add require and exports for each program execute(program:AST|String, local); // wherein a shared frozen global scope is implied and a local scope is pushed above it execute(program:AST|String, global, local); // wherein we reuse the global scope frame and put require and exports in a scope right above it In both of these cases, Mark's comments about copying members to a scope frame instead of using the object itself might apply. I presume that this is to avoid following the prototype chain when resolving a variable. If globals are shallowly copied into the local/bottom scope of the module, some things get simpler. For one, we can freeze the global object without freezing the bottom of the scope chain, which would impair module local declarations. We also wouldn't need two scopes initially. However, it would be nominally slower. I think that execute should take two arguments either way, since it would be inconvenient and slower than necessary to do this for every module execution: var scope = copy(global); scope.require = Require(id); scope.exports = memo[exports] = {}; execute(ast, scope); // scope chain is [Frame(scope)] …since execute effectively hides an implicit copy to the scope frame, making the explicit copy superfluous, as opposed to: var local = { require: Require(id), exports: memo[exports] = {} }; execute(ast, global, local); // scope chain is [Frame(global), Frame(local)] Is this on the right line of reasoning? Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Spawn proposal strawman
On Mon, May 11, 2009 at 9:26 AM, Brendan Eich bren...@mozilla.com wrote: On May 8, 2009, at 8:49 PM, Kris Kowal wrote: (function (require, exports) { + text + /**/\n} Nit-picking a bit on names: require : provide :: import : export -- so mixing require and export mixes metaphors. Never stopped me ;-). I agree about mixing metaphors. The befuddlement of start : stop :: begin : end is one that bothers me a lot. The notion is to desugar import and export to these two facets, importing and exporting. imports : exports would be proper, but doesn't read well in code. The reason for using the term exports is to ease migration, since: exports.a = function a() {}; Is easy to transform textually to: export a = function a() {}; So, I'm inclined to stick with exports instead of provide. The metaphor would be complete if we used imports(id) or import(id). Since import is a keyword, it would not be available for the desugarred syntax. That leaves imports. const {a} = imports(module); What makes functions eval'ed hermetically by the module function occur in a statement context? They should be nested function declarations, not (sub-)statements. Or I'm missing something. Perhaps I'm behind on the times, but I'm under the impression that presently the behavior of this function foo declaration has no standard behavior: (function () { function foo() { } })(); If foo gets bound in function block scope, there's no problem (which is the case in most browsers, I believe), but if it gets bound as a member of global, that would be a problem, and if it gets bound like a free assignment, it would only be a problem if free assignment isn't localized to the module somehow. This is a language change. ES1-5 put free variables created by assignment in the object at the bottom of the scope chain. I'm of course in favor of changing as little as possible. If the bottom-most scope is unique to the present module instead of the global object, there's no need for change here. Mark is citing a proposal that *removes* the global object from the scope chain; that proposal does not fiddle with where declared and free vars go. Alright, I'm following now. I'll explain why I think that this would be sufficient to fix some problems, although perhaps not necessary. Implementations would need to decouple the top of the scope chain and the global object. Implementations can do this easily, but the issue is language-level: is the global object at the bottom of the scope chain? So far, it is. I've operated on the assumption that the global object was on the bottom of the scope chain. There are some concerns about module texts for parsing and interpreting modules, some of which might be sufficiently addressed by moving global off the scope chain for module evaluation, but perhaps not necessarily. * free assignment. I'm less concerned about the behavior of free assignment. I'd prefer assignment to global to be explicit, but this ship may have sailed long ago. It might be more appropriate for free assignment to create module locals or module exports, which could be accomplished by changing the bottom-of-the-scope-chain, or by changing the behavior of free assignment in the context of a hermetic eval. In any case, this is not something I'm deeply concerned with. * function statements. These really must be module local. I'm not in-the-know about whether this is a problem or not. In the case where hermetic eval runs a program, we'd have to wrap the program in a function declaration. In that case, if function statements create function block scope locals, there's no problem. If they operate like free assignment, then there's a problem if the bottom-scope is global, but not if it's a module local object. If hermetic eval returns a module factory function that runs a program with a given require and exports object, function statements would occur in the bottom-scope. In that case, it would be a problem if the bottom-scope were global, whether or not function statements behave like free assignment or function block scope declarations. * return statement. This should be a parse error in the top most scope of a module. If hermetic eval wraps a module's text in a function declaration, the return statement would not be a parse error, which would be a problem. If heremetic eval returns a function that executes the module with a given require and exports object, then return would be a parse error in the bottom-scope. * injection attack strings. These are a weakness of using a hermetic eval that immediately evaluates a module factory function expression with the module text inside. In present implementations, it's possible to have globals available as free variables by replacing the bottom-scope-chain object with one begotten from globals. I'd concede that this is a hack. Here's a pseudo-code representation of our options and their ramifications: running a module looks like: let require
Re: Spawn proposal strawman
hope we can provide a switch on the sandbox machinery so the application programmer can chose whether they want light-weight sandboxes or heavy ones. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Universal Feature Detection
On Wed, Apr 29, 2009 at 5:30 AM, David-Sarah Hopwood david-sa...@jacaranda.org wrote: David Foley wrote: Please forgive me if I'm polluting the list, and re-direct me if I am, but considering that there has been so much focus on browser implementation, that JavaScript is also employable in various 'environments' (IDE's, Servers etc.) and that all of these environments avail different features to developers, that a universal / standard feature detection API, perhaps through a standardised global Environment object, would be prudent. Are there any plans to do such? There will probably be some kind of module system in ES-Harmony (which will be prototyped before then). It would make sense for that to support querying whether a given module is available, its version, and other metainformation about it. Ihab Awad and I made an initial proposal for a module system for Harmony in January, and presented it to TC39. Proposal: http://docs.google.com/Doc?id=dfgxb7gk_34gpk37z9vhl=en Presentation: http://docs.google.com/Presentation?docid=dcd8d5dk_0cs639jg8hl=en Since then, we've been working closely with a group called ServerJS that is creating a standard library for server-side JavaScript, with participants working on prototypes for {Spider,Trace}monkey (Flusspferd, GPSEE), V8 (v8cgi, k7), and Rhino (Helma NG, Persevere, Narwhal). They've converged on a module system specification that is very close in form to the initial phase of our proposal (that is, without syntactic sugar). The proposal and links to the relevant discussions, which have been extensive, are on the Moz wiki: https://wiki.mozilla.org/ServerJS/Modules/SecurableModules https://wiki.mozilla.org/ServerJS/Modules https://wiki.mozilla.org/ServerJS The proposal does not require augmentation to the global name space, but it might be desirable. In the proposal, there's a require free variable in the module, and various prototypes inject the free variable into the module's scope, some as an argument to the module factory function, some as a member of a fresh context object begotten of global. So, within modules, there's no need for a global variable. There are a couple known options for loading the main, or initial module. One of them is to add a require method to the global object. Another is to introduce a variant of the script tag that loads a module instead of a global script. Chiron, my client-side prototype, uses a script tag to bootstrap a module loader and loads the module in the script src query string. Regarding feature testing, the module system might be useful since the platform, albeit browser, could provide features as modules, in which case calling require on that module's identifier would throw an error. Some prototypes have a require.isLoaded(id) method that could be used to test whether modules provided by the platform have already been loaded, without having to catch a require error. However, these ideas probably don't obviate the need for a feature testing system for layout, rendering, event, and other features and quirks that might not be neatly distinguished based on the availability of a module. Kris Kowal ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Remarks about module import
much like /usr/lib/libc.so usually symlinks to /usr/lib/libc.so.5 on Unices. So, I recommend that modules be identified by URL's, although not necessarily Strings since that might compromise static analysis again. I also think that, borrowing a meme from python3k, if a URL begins with a dot, it be module relative. Consider (where import stands in for some yet to be determined keyword): // in http://my.com/site.html where the moduleRoot is the same as the page URL by implication: import window; // moduleScope.window = require(window); import http://jquery.com/jquery-2.6.js;; // moduleScope.jQuery = require(...); import ./widget.js as widget; // moduleScope.widget = require(http://my.com/widget.js;); from ./widget.js import Widget; // moduleScope.widget = require('http://my.com/widget.js').Widget; On the topic of PATH, it occurs to me that a page could potentially subscribe to a module root either hosted by the browser in chrome:// or potentially on a CDN like Google's AJAX modules. That might answer my performance concern from walking the PATH and hitting a 404, extending page load times by a Round-trip-time for each missed module. This leaves the issue of bundling. Web page authors will still need to concatenate scripts and CSS to improve a page load's performance. To that end, I recommend that module's have a provide or register function, wherein they can, in a single module, provide a bundle of module objects that they construct themselves, or declare in the same way that they would in another file. provide(./widget.js, widgetModule.freeze()); provide ./widget.js { } I'll leave it to the Ihab or Mike to comment on the security implications of bundling; I suspect they are dire. Perhaps only modules in subordinate URLs can be provided by one module. That's another tension we should consider. There was mention on the original wiki page of requiring module dependencies to form a directed acyclic graph (ok, a tree). I don't believe this is any more necessary than in Python, where it's desirable by not enforced. Since module objects are singleton and registered before a module is evaluated, modules have the option of providing their partially completed module objects to cyclic dependencies. Not having a solid module system is my biggest pain-point in modern JavaScript. Without it, JavaScripters are relegated to using best practices and design patterns to make their scripts more but not quite portable, and more but not quite secure. I've managed to make most of these features possible in user-space JavaScript using a collection of naughty practices like gratuitous use of eval and with and I consider the sacrifice worthwhile, but something similar needs to just be natively available for security and ubiquity. I have great hope for the fruit of this discussion. Kris Kowal ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Remarks about module import
Peter, Can you provide concrete examples (something a few lines longer than a hello world module) which shows both the module and importer code? sink.js /** this module provides a `sink` function which allows the user to cause a DOM element to forward its events to one and only one, detachable Widget object that implements `./event.js#Signaler`. */ /* these are modules by the same author, in the same directory */ from ./urllib.js import urlJoin; from ./base.js import Set; /* this is a cross-browser compatibility layer */ from ./browser.js import normalizeEventName, browserEventName; /* presumably browser is a module provided by the browser in some * cross-browser compatible way. */ from chrome://js/browser.js import observe; /* using let or var makes a variable private to the module */ let widgetNs = urlJoin(__FILE__, '#widget'); // or let widgetNs = urlJoin(moduleUrl, '#widget'); let sinksAttribute = urlJoin(__file__, '#sinks'); /* the name __FILE__, moduleUrl, __file__, or __DIR__ * isn't as important as the behavior. It would not * be onerous to provide both module file and dir variables, * but dir can be inferred from file and is best * dealt with via urlJoin which handles both cases unless * the provider of __DIR__ is unscrupulous about the * final forward-slash. */ /* assigning to this makes it an export */ this.sink = function (element, widget, eventName) { if (element[widgetNs] element[widgetNs] != widget) { element[widgetNs].final(); } element[widgetNs] = widget; let sinks = element.getAttribute(sinksAttribute); element[sinksNs] = sinks; let normalizedEventName = normalizeEventName(eventName); let browserEventName = browserEventName(eventName); if (!sinks.has(normalizedEventName)) { observe(element, browserEventName, function () { let widget = this.target[widgetNs]; widget.signal(normalizedEventName, this); }); sinks.insert(normalizedEventName); } /* break reference cycles */ widget = undefined; element = undefined; }; index.js from ./sink.js import sink; // or let sink = require(./sink.js).sink; from http://jquery.com/dist/jQuery.10.1.js; import jQuery as $ from ./my-widget.js import MyWidget sink($('#widget'), MyWidget()); Kris Kowal ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss