Re: Since JSDoc seems cerebrally dead...
Hi, > They don't want to add TS to their stack. Then what else would they want to add to their stack? Notice one doesn't necessarily need the TypeScript Compiler to add TypeScript- or Flow-like type annotations and remove them in a build step - Babel for example could do that just fine as well. Or are you asking for a jsdoc-like thing that lives in comments, where the code can be run without a compilation step? kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: [PROPOSAL] Provide a way to enforce integrity check on module imports
Hi, > The problem with inlining the integrity into every import site is that this > is naturally incompatible with import maps. I don't see a problem with that. When using import maps, you should be able to specifiy the integrity check in the import map, not needing it in the module itself. When not using import maps, specifying the integrity in the importing module itself seems to give the best developer experience, following the rationale of https://github.com/tc39/proposal-import-assertions#why-not-out-of-band. When using it in *both* places, then of course both integrity checks would need to match, and an import map would be prevented from swapping out the module under your hands. kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A Function.tag proposal?
Hi Andrea, my 5ct: Putting the static function on the `Function` object doesn't make any sense to me. Using `String.tag` seems like much more sensible choice. Or, how about `String.plain`, in contrast to `String.raw`? I can see the use case, altough I'd really prefer tooling to become more intelligent in that regard. best, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A way to construct Functions with custom scopes?
Hi! It's a bit unclear to me what problem you are trying to solve, but you can already construct closures with custom scopes using the `Function` constructor: ```js function makeFunction(name, args, body, scope, values) { if (typeof args == "string") values = scope, scope = body, body = args, args = []; if (!Array.isArray(scope) || !Array.isArray(values)) { if (typeof scope == "object") { values = Object.values(scope); scope = Obect.keys(scope); } else { values = []; scope = []; } } return Function(scope, ` function ${name}(${args.join(", ")}) { ${body} } return ${name}; `)(...values); }; const foo = makeFunction("foo", [], "console.log(x)", {x: 10}) foo(); // logs 10 ``` kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Conditional assign operator
Hi! > What I've long wanted is an assignment operator which evaluates to the > pre-assignment value of the LHS. > You know, sort of like `a++` evaluates to the pre-incremented value of `a`. Given the amount of confusion that the difference between `++a`, `a++` (and `a += 1`) already has caused, I doubt that would be a good idea. In most, if not all, cases the desired behaviour can be easier and cleaner expressed with two statements, and a temporary variable if absolutely necessary. > ``` > let a = 1; > console.log(a =^= 2); // logs 1 and then sets a to 2 > ``` would be just ``` let a = 1; console.log(a) a = 2; ``` kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Yet another attempt at typed JS data
Hello! > Unfortunately, `Array.from({ length: 4 }, () => whatever)` produces a holey > array Does it? But really, if the performance difference betweeen HOLEY and PACKED arrays were large enough to be relevant[1], the engine programmers would certainly already have optimised all those trivial cases where an array is filled gradually to produce the more efficient representation. kind regards, Bergi [1]: it probably isn't: https://stackoverflow.com/questions/54481918/#comment95848513_54485509 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Async iterator destructuring?
Hi, > It might be useful on some occasions to [collect] async iterators [into an > array]. No need for destructuring or spreading here. The iterator helpers proposal <https://github.com/tc39/proposal-iterator-helpers> already covers these: ```js return Buffer.concat(await someStream.setEncoding('buffer').toArray()) ``` ```js // It's different for each database const [item] = await db.scan({ filter: {key: value}, limit: 1, }).toArray() ``` kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: `await.all {...}` for parallelism
Hello! > This [current] structure is also just fundamentally different from working > serially in async/await and it forces you to reason about the problem > in a specific way. This doesn't appear to be a conscious decision to > force good code practices Actually I'd argue that it is. Doing stuff concurrently *is* fundamentally different from doing it serially, and should be reasoned about every time you use it. kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Optional Curly Braces in JavaScript
Hi! > If it's possible in JavaScript to have `:`, and enable significant spacing, > that would be great. > > Why you don't *want* to? Your argument for significant whitespace seems to be that the simplicity of Python is great. However, adding an alternative block syntax to JavaScript would fail to achieve this goal, in contrast, it would only make the language more complex. So no, my educated guess is that it's not possible for you to persuade the wider community and especially the technical committee to accept your proposal. They are very reluctant to add features that don't show a clear benefit. Since you asked for my personal feedback: JS syntax was influenced by C and Java, and it will consistently keep its curly braces. A different block style would only be a viable choice for a new language or dialect, which should not allow curly braces at all, and would not provide backwards compatibility. kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Optional Curly Braces in JavaScript
Hi! > Note that significant whitespace greatly minimizes the yields of minification Why would it? Nothing would prevent a minifier from changing significant whitespace into braced blocks - just like today, they omit semicolons where possible and remove braces around single-statement blocks. kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Optional Curly Braces in JavaScript
Hi Ed! > Update to the proposal: > > Since we can't make spaces in JavaScript, the best we can do is use '_' > instead. You misunderstood. We *could* make use of significant whitespace in JavaScript (enabled by the `:` instead of a brace after a statement) - we just don't *want* to. That said, `_` is not a workable solution - apart from _ (and any repetitions of it) being a valid identifier already, *chaining* it like you described doesn't work with nested blocks: ``` for (const x of [1,2,3]) _ if (x % 2) _ console.log('odd') _ console.log(x) ``` would be indistinguishable from ``` for (const x of [1,2,3]) _ if (x % 2) _ console.log('odd') _ console.log(x) ``` (and no, please don't suggest repetion of whatever token you come up with for signifying nesting level) kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Optional Curly Braces in JavaScript
Hello Ed! > That would make JavaScript an easy to write on board language, where a > language like python dominates because of it's simplicity in writing. This > would make JavaScript spread into more areas in science, education and > engineering. You seem to not only want to make block syntax optional, but rather make whitespace indentation significant. You might want to have a look at CoffeeScript <http://coffeescript.org/#language> which is a compile-to-JS language that uses this concept. Its function syntax is a bit different from what you imagined though, most importantly it doesn't offer any declarations. kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: ECMAScript feature suggestion: Streaming Array items through filter/map/reduce functions
Hi! However, when I want to write performance sensitive code, chaining these functions is not a good approach. const b = a.filter().map() will require 2 traversals over the whole array, up to 2*N iterations (if the filter passes all items). Actually, the number of passes hardly matters. It's still linear complexity. What makes this slow is the allocation of the unnecessary temporary array. I suggest adding a capability to streamline items to these functions. We don't need streams, JavaScript already has iterators. What we do need are proper helper functions for those - see the existing proposal at <https://github.com/tc39/proposal-iterator-helpers>. You then can write const b = Array.from(a.values().filter(…).map(…)) or for (const x of a.values().filter(…).map(…)) console.log(x); kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal for Promise.prototype.flatten
Hello, I oppose this proposal. In my opinion, mixing normal exceptions (promise rejections) with result-error-tuples is rather inconsistent than a more consistent interface. The only thing it might interface better with are node.js-style callbacks, but we already deprecated those in favour of promises. `if (err) throw err;` is reminiscent of this old style, it's no longer necessary to explicitly re-throw with modern syntax. It's not even simpler, or better to read. The example you gave could easier be written as ```js async function test(promise1, promise2, promise3) { const val1 = await promise1.catch(err => void err); // ignore exceptions const [val2, val3] = await Promise.all([promise2, promise3]); // throw to caller return val1 + val2 + val3; } ``` (Notice also that no default value for the destructuring is necessary, which is a rather error-prone part of your snippet). Using `catch` forces the programmer into explicitly providing a default value (even if `undefined`), which could go unnoticed otherwise. Can you please add an example where using `.flatten()` actually introduces an advantage? If one needs a more powerful error handling approach, you should use `then` with two callbacks. (Getting a try-catch-else syntax <https://stackoverflow.com/questions/4872170/javascript-try-catch-else-finally-like-python-java-ruby-etc> for that would be nice, though). As already mentioned, the name `flatten` is ill-suited for this method. If you absolutely need this functionality, use `.then(r=>[,r],e=>[e])` in your code, or put it inside a helper function. (Or use one from a library like <https://github.com/scopsy/await-to-js/>). We do not need this as a method in the EcmaScript standard. best regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: Static Typing
Hi, I am having hard time understanding the counter argument "you need a transpiler anyway". Sorry, I agree it's a bad argument, I should have just omitted it. It was meant to support "If you are only looking for development-time benefits, you have to install a static toolchain anyway - which might as well transpile away the annotations". the real value of strict types, in my view, is at development time, not at run time. This is not correct. Check what AssemblyScript managed to do via types, targeting WASM instead of non-typed JS I would be curious to know if anybody has a usage for them at run time Developers might not have such usage, but V8 / Chakra / JSC / SpiderMonkey might spin up optimizations ahead of time, enabling right away hot code. ...or at least allow throwing exceptions instead of having to de-optimise a JITted code, which allows simpler & better optimisation algorithms. These are the kinds of arguments I want to hear, reasons for sending type annotations to the client/runtime. And such a goal puts a very different focus on what the type system should look like: WASM interoperability and optimiser efficiency instead of developer productivity. kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: Static Typing
Hello, to play the devils advocate: why does JavaScript need static typing? Your proposal doesn't really answer that. Sure, it mentions tooling and IDEs that can provide you with type hints and complain on mistakes, but things like Flow and Typescript do this today already. What's your goal, to have JS engines run Typescript(-like) code natively without transpiling? For backwards-compatibility you'd have to do that anyway, especially if new type system features are introduced incrementally. What's the point of building this feature into engines? It just provides additional complexity. Not to mention the difficulty of finding a suitable type system that is both sophisticated enough to describe all useful code (not taking away too much flexibility) and simple enough to understand without a CS degree. And which interfaces well with un-typed completely dynamic code. What does "static typing" even mean to you in a dynamic scripting language? JavaScript is not compiled by the developer, it is run by the user. Where (when) do you expect types to be checked? Should the engine throw early errors (during parsing)? During parsing of which parts of the code, even when "normal" (untyped) code is calling into typed code? Or do you expect dynamic runtime errors, like when assigning an invalid value to a "typed variable" or calling a "typed function" with wrong arguments? Are type definitions completely constant or could they be mutated/extended/etc dynamically (and what happens when you introduce new types with `eval` or by loading another script)? A proposal would need to provide an objective that answers all these questions, before even considering any particular type system or syntax. One way to go forward that I can see would be a proposal that reserves a relatively unrestricted syntax for type annotations (which are already considered during every grammar amendment anyway, for compatibility with Flow/Typescript), but not assign any semantics to them and require engines to simply ignore them. External tooling could then use these annotations according to its own rules. kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal For A New Alternative Keyword To “this” For Classes
Hi John! I think the js run-time already has that information at hand, so as long as we don't implement this as pure syntactical sugar, there would not be a need to keep an extra reference to anything, because it would be already there. The run-time will know which instance the invoked method belongs to. Well no, you're wrong here: the runtime does not have this information at hand. In your example (simplified) ``` var reqManager = new RequestManager(); function addEventListener(f) { console.log(f); f(event); } addEventListener(reqManager.responseHandler); ``` the `addEventListener` function will not know that the function `f` you passed was a method of the `reqManager` instance. It cannot distinguish that call from ``` addEventListener(RequestManager.prototype.responseHandler); ``` or ``` var g = otherReqManager.responseHandler; addEventListener(g); ``` It is exactly the same function that is passed in all three cases. There is no instance bound to `f`, and `f(event)` will not invoke it as a method (with a receiver/`this` value). Best regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal For A New Alternative Keyword To “this” For Classes
Hi John, I believe that it would be a trivial task for current static code analyzers to restrict usage of "this" for anyone opting in to use this new keyword exclusively. Static tooling, like the TypeScript compiler, can detect problematic method usage already today. Sure, having a dedicated syntax for this will make static analysis simpler, but I don't deem that a worthy addition to the language. As you mentioned, arrow functions might have their own problems. Wouldn't such an alternative keyword be a good addition to our toolkit anyway? What I was trying to say is that your proposed alternative has exactly the same problems as instance-member arrow functions have today. Best regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal For A New Alternative Keyword To “this” For Classes
Hi John, I don't think we do need another keyword for this. People would forget to use that new keyword instead of using this, just like they currently forget to use arrow functions. That said, your desired "behind-the-scenes implementation" can already be achieved easily with the class fields proposal and an arrow function. However, [there are many problems with that approach](https://medium.com/@charpeni/arrow-functions-in-class-properties-might-not-be-as-great-as-we-think-3b3551c440b1) anyway. kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Reflect.toStringSpec proposal
Sergey R schrieb: I want to propose a new language feature — Reflect.toStringSpec. `Reflect.toString` or `Reflect.toStringSpec`? Here is a repo https://github.com/chicoxyzzy/proposal-reflect-tostringspec | Rationale | | There is no exact way to call spec's `ToString` in JS. | However it may be necessary for polyfills. It's not that hard to emulate, is it? There are other internal operations would be more important. Regardless, the `Reflect` namespace is supposed to only contain object tools that would be the default for proxy traps. No `ToString` in there. | Current solution is to do something like: | | function toStringSpec(target) { |return target == null ? target : String(Object(target)); | } That looks horribly wrong. It doesn't do the least what `ToString` does in ES6. The spec says it should do ``` function ToString(x) { if (typeof x != "symbol) return String(x); else throw new TypeError("…"); } ``` This would be a pretty standard approach, also being used e.g. in https://github.com/ljharb/es-abstract/blob/035153777213981e0e24f6cf007ffbd279384130/es6.js#L129-L135 And if you don't care about Symbols, you can easily just use `String`. Kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Conditional object properties
Luke Mitchell schrieb: Hi all, I often come across a situation where I wish to extend an object (usually an argument for an API request) if a particular condition is satisfied, such as the presence of a function parameter. Currently the only way to do this is by assigning the object to a variable, checking the condition using an `if` statement and then extending the object. I am proposing the inclusion of an operator that allows a property to be included, subject to a particular condition, inside the object definition. You can already do ```js let obj = Object.assign({ … }, cond ? { prop: value } : null); ``` Or depending on your condition, also just `cond && { prop: value }`. The object spread proposal will achieve the same, without the need for any extra operator. - Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Cancel Promise pattern (no cancellable promises)
Jan-Ivar Bruaroey wrote: On 10/27/16 4:25 PM, Bergi wrote: I'd however love to be able to cancel specific chaining operations, i.e. `then` callbacks. If you try the fiddle - http://jsfiddle.net/jib1/jz33qs32/ - you'll see cancelling terminates the chain. If you intersperse non-cancellable operations, there'd be a delay if cancel is detected during those. Yes, that's what I mean. Sure, I could use `Promise.race` to get the cancellation even if the non-cancellable operation resumes, but that's quite ugly: Promise.race([ promise() …chain…, cancelToken ]).then(callback); especially when you'll need to nest that pattern. Instead, I'd just like to write promise() …chain… .then(callback, cancelToken) with the same behaviour. A crucial problem that promises don't solve is synchronous inspection. If my operation was cancelled, I'd like to know immediately (before starting further work) about it, instead of waiting another tick to be notified. I think it'd be odd to observe cancellation and not success nor failure, so this seems orthogonal. I meant the producer would want to observer the cancellation so that he doesn't attempt to resolve the promise. But yeah, observing cancellation vs success/failure is another problem that would benefit from inspection. Let's say I have a cancel token and a promise chain. Now I want to do exactly one of three different things, depending on what happens first: the operation is cancelled, the promise is rejected, or the promise fulfills. How do I do that? But the fundamental problem with promises as cancellation tokens is memory leaks. In your example, if the cancel button isn't clicked for 10 seconds, the `token` promise will reference 3 `() => clearTimeout(id)` callbacks which close over their respective `id`s. Three functions and three integer ids doesn't sound like much, but in real applications with long-running un-cancelled operations a token could accumulate quite an amount of resources which cannot be collected. A clever programmer might make the callbacks become cheap no-ops, but still at least the functions themselves will consume memory. For the simple programmer, we need an automatic (not error-prone) unsubscription mechanism once the respective cancellable operation ended. Thanks for the links. I think I'm in the camp of not being concerned about this. Recall I'm not proposing new functionality, just using promises, so this stands to benefit from optimizations browsers ought to make already, without needing special attention. Once browsers optimize: function poll() { return isDone() || wait(1000).then(poll); } I'll worry about this. ;) Yeah, I just think that we *need* new functionality (like the ability to remove callbacks from a promise) to solve cancellation properly. It's true that ES6 has a bug that prevents implementors from optimising recursive assimilation, but it's a different kettle of fish to fix that in the spec. I'm trying to avoid that we make the same mistake again for cancellation tokens, so I think you *should* be concerned. kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Cancel Promise pattern (no cancellable promises)
Jan-Ivar Bruaroey wrote: I'm posting this here in hopes to bring the discussion back to practical use cases and minimal needs. Sorry, did we leave that somewhere? :-) But you've got some good and important points. Things to note: - Cancellation is targeted to specific operations (no "cancel chain" ambition). I'd however love to be able to cancel specific chaining operations, i.e. `then` callbacks. - Token can be reused down the chain. - Cancellation is propagated using a regular (new) CancellationError (no third rail). - It is up to the caller whether to treat cancellations as non-exceptional. Very important. I'd even go so far to let the caller only treat cancellations that he caused himself as non-exceptional. - Basic Promise.race pattern works even to wrap APIs that aren't cancellable (stop waiting) - Pattern allows substituting any error (though I hope we standardize CancelledError). - Pattern allows chain resumption by resolving token with any desired value instead. I'm not sure what you mean by "resumption". And what would that value be used for? I'm open to hearing what use-cases are not be covered by this. Looking forward to your feedback about using a regular promise as a cancellation token. A crucial problem that promises don't solve is synchronous inspection. If my operation was cancelled, I'd like to know immediately (before starting further work) about it, instead of waiting another tick to be notified. But the fundamental problem with promises as cancellation tokens is memory leaks. In your example, if the cancel button isn't clicked for 10 seconds, the `token` promise will reference 3 `() => clearTimeout(id)` callbacks which close over their respective `id`s. Three functions and three integer ids doesn't sound like much, but in real applications with long-running un-cancelled operations a token could accumulate quite an amount of resources which cannot be collected. A clever programmer might make the callbacks become cheap no-ops, but still at least the functions themselves will consume memory. For the simple programmer, we need an automatic (not error-prone) unsubscription mechanism once the respective cancellable operation ended. Kind regards, Bergi -- Of course, my own proposal <https://github.com/bergus/promise-cancellation> is the holy grail. Feedback welcome :-) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: Array.prototype.accumulate and Array.prototype.accumulateRight
Mark M. Young wrote: I am proposing a replacement for Array.prototype.reduce and Array.prototype.reduceRight. Nice. Allowing to pass an argument for the `this` value was missing when folding an array, and your suggestion `accumulate` is a fitting method name. However, I fear the use cases are too unimportant to need a fix. The `this` keyword is becoming less and less used for anything but class methods. And for those, arrow functions solve the problem needing to invoke functions on the expected receiver. For passing in data to a reusable reducer function, closures are much simpler than setting the `this` value for the callback. https://github.com/MarkMYoung/ArrayAccumulate <https://github.com/MarkMYoung/ArrayAccumulate> says `reduce` is not reusable code because there is no way to know what the second parameter was once beyond the first iteration. That makes no sense. The whole point of the initial value parameter is that it only goes into the first call (if any), or is the return value in case the array is empty. the second parameter is always available as `this`. It really should not be. If you want to pass a value for `this`, it needs a third parameter. kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Alternative way to achieve cancelable promise
Kagami Rosylight wrote: I want to find a way to replace cancellation token in the current [stage 1 cancelable promise proposal](https://github.com/tc39/proposal-cancelable-promises) with an alternative way which does not require passing an additional parameter. You're not the only one who is unsatisfied with the current proposal :-) Also have a look at * https://github.com/stefanpenner/random/tree/master/cancellation * https://github.com/rtm/cancelable-promise * https://github.com/bergus/promise-cancellation (mine) Here is a short representation of [my current thought](https://github.com/SaschaNaz/cancelable): ```ts // A cancelable object supports new `Symbol.cancel`. // `object[Symbol.cancel]()` will cancel any tasks related to the object. interface Cancelable { [@@cancel](): void; } interface Promise extends Cancelable {} ``` That's not going to happen. Promises are result values that can be passed to multiple consumers, and not every consumer should be allowed to cancel the computation. So by default, promises must not be cancellable. There could be such promises that can be cancelled by whomever gets a hold on them - they are known as `Task`s iirc - but that needs to be an opt-in. // Here, a new `chain` object from promise constructor callback will // help chaining cancelable tasks and provide cancellation related // helper functions. I don't see the major difference between these "chain" objects and "tokens" from the other proposals. Can you expand on that, please? function foo() { return new Promise(async (resolve, reject, chain) => { await nonCancelableSubWork1(); chain.throwIfCanceled(); // This line will throw `Cancel` object if the promise got a cancellation request await nonCancelableSubWork2(); resolve(); }); } That's not going to work. You should never pass an `async function` to the `new Promise` constructor, have a look [here](http://stackoverflow.com/a/39409757/1048572). Fortunately, the code in your actual proposal seems more reasonable here. And with some syntax sugar for readability: ```js cancelable function foo() { // `chain` is a keyword inside cancelable function blocks await nonCancelableSubWork1(); chain.throwIfCanceled(); // similar form like `new.target` await nonCancelableSubWork2(); } cancelable function bar() { chain foo(); chain baz(); } const promise = bar(); promise.cancel(); ``` If I understood correctly, your `chain` keyword could be used like `await`? What is the difference between them? But I really like the idea of `cancelable function` sugar that does the housekeeping implicitly and returns cancellable promises automatically. This very much reminds me of my own ideas https://github.com/bergus/promise-cancellation/blob/master/enhancements.md :-) kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Making Object Literals a sub-class of Object
I wrote: Brian Ninni wrote: On more than one occasion I've had to determine whether something was a plain old Object, or some other class. This involves checking that the given object was NOT an instanceof any other acceptable class. `Object.prototype.isPrototypeOf(o)` should do that (if you don't care about other realms). Ooops, `Object.getPrototypeOf(o) === Object.prototype` is what I meant. - Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Try/Catch always needed for await?
Jordan Rome schrieb: My apologies if this has already been discussed but what is the "preferred" pattern for using await ? Since await, which runs on promises, will now throw if the promise is rejected (preventing execution of code after the await and killing the process in Node), is it neccesary to always be wrapping await in try/catch? No. Just like in synchronous code, you only wrap a part of your code in try-catch if you actually want to *handle* an exception. If you don't handle it, it will bubble as usual and reject the promise returned by the `async function`. Let the caller deal with the exceptions you can't handle - just like always. Of course, in the top-level invocation it might be a good idea to use a `catch` (or the `.catch()` method) to catch any exceptions and log them to whereever you want if you don't want to get an unhandled rejection, but those are usually exceptions you *don't expect* so you might not need to deal with them at all. - Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Making Object Literals a sub-class of Object
Brian Ninni wrote: On more than one occasion I've had to determine whether something was a plain old Object, or some other class. This involves checking that the given object was NOT an instanceof any other acceptable class. `Object.prototype.isPrototypeOf(o)` should do that (if you don't care about other realms). Array, RegExp, Function, and Class Literals all already create an Object sub-class, so why not Object Literals? Because Object-objects are just Objects and not anything special that would need a subclass with specific methods. Are there any other major reasons why this is a bad idea? As you already said, it would break a great lot of code. - Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Power operator, why does -2**3 throws?
Cyril Auburtin schrieb: I would expect `-2**3` to return -8, or `-2**2 == -4`, since it should be like `-(2**3)` You would, others would not. -2 ** 2 clearly should return 4, shouldn't it? Is there a reason for this restriction? Python does it `-2**3` fine Because of the ambiguity it has been decided to make it a syntax error if the two operators are used together. If you want `-(2**3)`, you have to write it like that, and if you want `(-2)**3` you have to write it explicitly as well. See https://esdiscuss.org/topic/exponentiation-operator-precedence for the full discussion. - Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Why no tail calls from generators?
Joe Gibbs Politz wrote: What is the rationale for explicitly disallowing PTC in generators? (Or, in the case of proposals like STC, why not allow users to opt in to TCO in generator bodies?) I'd guess that generator functions are already complicated enough, and the `next()` call that at least has to wrap the result in `{value: …, done:true}` would always have to stay on the stack. However, it would be possible to do tail-recursive calls in generator functions via return yield* f(…) Kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Syntax Proposal: Add getter/setter directly on current scope ??
Li Xiaolong schrieb: Sometimes, we want to get a representation of another variable, or get an abstract representation of some other variables. In this case, we often use getter/setter. But defining a getter/setter in current scope is complex. Can we make adding a getter or setter to current scope easier like the following example? ```js var a = 2; get b() {return a+1;} b; //returns 3 You already can do that: ```js var a = 2; with({get b() { return a+1; }) { b // 3 } ``` However, magic bindings (that do something else than variable assignment and access) are a source of confusion and usually a bad idea. Why not simply use a function `b()` that you can call? It's clear what happens with that. We hardly need a special syntax for getter/setter variables in lexical scopes. - Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: use "One More Point" to handle async functions
What you call "one more point" already exists as the `await` keyword and is much more powerful than a limited `.return` operator: <https://github.com/tc39/ecmascript-asyncawait> Please make sure to be familiar with the topic before making further proposals. - Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Clarification regarding Completion Records
Felix Kling wrote: - `ResolveBinding` is an *"abstract operation"* so it returns a completion record, whose value is a *"Reference"*, even though completion records are only supposed to have language values as value (6.2.2) (this still confuses me) Uh, that's weird indeed. Looks like you found a mistake. - As per your quote, `Return ?ResolveBinding(...)` simply returns that completion record. - In `Let exprRef be the result of evaluating Expression`, `exprRef` is a Reference, the completion record obtained by *"evaluating Expression"* was implicitly unwrapped, according to 6.2.2.2: *"Any reference to a Completion Record value that is in a context that does not explicitly require a complete Completion Record value is equivalent to an explicit reference to the `[[Value]] field of the Completion Record value unless the Completion Record is an abrupt completion."` Am I right so far? I believe so, yes. Then, does the sentence The algorithms of this specification often implicitly return Completion Records whose `[[Type]]` is `normal`. mean that 1. Algorithms may or may not return a completion record (i.e. some do and some don't). 2. Algorithms *always* return a completion record, but it's not always *explicitly* stated in the algorithm. I'd say the second. But then again, there might be some algorithms that get the [[Value]] from a completion record, and those hardly will return a completion record, would they? Take `ReturnIfAbrupt` as an example. It's weird. - Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Clarification regarding Completion Records
Felix Kling wrote: I need some clarification around completion records. You'll want to have a look at the algorithmic conventions (http://www.ecma-international.org/ecma-262/7.0/#sec-algorithm-conventions) and the implicit coercion of completion values (http://www.ecma-international.org/ecma-262/7.0/#sec-implicit-completion-values): | Calls to abstract operations return Completion Records. | The algorithms of this specification often implicitly return | Completion Records whose [[Type]] is normal. Unless it is otherwise | obvious from the context, an algorithm statement that returns a value | that is not a Completion Record, such as: | > Return "Infinity". | means the same thing as: | > Return NormalCompletion("Infinity"). | | However, if the value expression of a “return” statement is a | Completion Record construction literal, the resulting Completion | Record is returned. If the value expression is a call to an abstract | operation, the “return” statement simply returns the Completion | Record produced by the abstract operation. Yes, it's a bit sloppy, but makes the spec much more readable. It's already technical enough, so this does formally apply some common sense :-) kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Extended dot notation (pick notation) proposal
Bob Myers wrote: This is a creative idea. I'd rather see it in the language than not. But still half a loaf. Yeah, it's not the whole thing, but I believe it's something the TC could agree on before moving further. Minor nit: I don't see how this is a "simplification in object destructuring". It has nothing to do with destructuring, right? For consistency and ease of understanding I would apply the same pattern for destructuring cases, i.e. ``` ({o1.x, o1[y]} = o2); ``` desugars to ``` ({x: o1.x, [y]: o1[y]} = o2); // but `y` being evaluated only once ``` This would help a great deal where the object on which the properties should be assigned already exists, e.g. in a constructor: ``` constructor(options) { ({this.propA, this.propB, this.optOne} = options); } ``` to provide some kind of "selective `Object.assign`". It's a bit sad that I don't see how to get to renaming and defaults with this syntax. Renaming has always been part of the language: ``` o2 = {y: o1.x} // o2.y = o1.x ({y: o2.z} = o1); // o2.z = o1.y ``` and with destructuring we'd also get defaults. - Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Extended dot notation (pick notation) proposal
Jonathan Bond-Caron wrote: On Tue Sep 20 03:38 PM, Bob Myers wrote: People in the real world continue to wonder why they can't pick/destructure from objects into objects, instead of just variables. Yeah, StackOverflow is hit pretty often with people asking how to do that. Seems like allowing to "dot" into another identifier could work: https://tc39.github.io/ecma262/#prod-CoverInitializedName CoverInitializedName[Yield]: IdentifierReference[?Yield] Initializer[+In, ?Yield] IdentifierReference[?Yield] . IdentifierName I don't think that's the right grammar rule, but yes, I'd love to see this: const IDENTIFIER = 1; const sandwichesIWantToEat = { SANDWICHES.CHEESE_STEAK, SANDWICHES.SLOPPY_JOE, IDENTIFIER }; Use the RHS identifier as the member/property name and resolve the "dot" expression to get the value. const sandwichesIWantToEatResult = { CHEESE_STEAK: SANDWICHES.CHEESE_STEAK, SLOPPY_JOE: SANDWICHES.SLOPPY_JOE, IDENTIFIER: IDENTIFIER }; This simplification in object destructuring and shorthand property intialisers should be easy to add to the language and rather simple to understand. There are no grammar ambiguities, and no completely new productions, but I believe it would help a great deal. Yes, one would still have to repeat the name of the object to/from which the properties to assign/take, but that's usually rather short so it's not a large burden. I could create a proposal repo, who would like to help? kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: anaphoric if and while syntax
Danielle McLean wrote: variables declared using `let` or `const` would be scoped to the individual `if` or `while` statement, rather than the containing block. In other words, the above syntax would be equivalent to the following currently-valid form I ended up writing: { const oldValue = _.get(object, 'some.long.path'); if (oldValue) object.some.long.path = transform(oldValue); } What about `else` blocks, would the variables be available in them as well? - Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Function composition syntax
Hi, interesting proposal! Here's what I propose: a new infix operator `>=>` (operator and direction can change) for composing two functions. Sweet, reminds me of Kleisli composition in Haskell http://hackage.haskell.org/package/base-4.9.0.0/docs/Control-Monad.html#v:-62--61--62- (which does something different to functions though). 2. It allows engines to statically optimize functions in the middle (avoid an extra function allocation), like with `f >=> x => console.log("x:" + x)`. I don't understand that one. Wouldn't `x => console.log("x:" + f(x))` be optimised better (and also be easier to read)? 3. It can simplify the internal model some to deal with a binary pair instead of an array, especially when pipelining gets involved. 4. Composition isn't usually combined as a function in JS. Can you clarify what you mean with this? My questions would be * What precedence would the operator have? Clearly something between member access and assignment, but what exactly? Particularly interesting cases: f >=> g (x) f >=> p ? g : h f >=> x => x >=> g * Do we also need a partial application operator to make this syntax useful? I guess the discussions from https://github.com/tc39/proposal-bind-operator/issues/35 and https://github.com/tc39/proposal-bind-operator/issues/26 are relevant here. Kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Static `super` may cause a unwanted "memory leak".
/#!/JoePea schrieb: ```js export default function SomeFactory(name) { let tmp = { [name]() { /* this doesn't use `super` */ } } return tmp[name] } ``` Then that will store each new `tmp` object in memory although the user of the factory only cares about the functions created. Why would `tmp` be stored as the [[HomeObject]] when the function doesn't use `super`? In that case a [[HomeObject]] is not needed at all. kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Looking for champion (Was: Alternative Promise cancellation proposal)
I am searching for a champion to present this proposal as a strawman to TC39. I would like to get an official feedback from the committee, as Domenic seems unwilling to incorporate my fundamentally different ideas into his proposal. Looking forward to see you step up, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Alternative Promise cancellation proposal
ng ES6 and ES7) * A+ assimilation would translate cancellation into forever-pending promises: `ThirdStatePromise.resolve(AplusPromise.resolve(cancelledThirdStatePromise))` * it's confusing if it does not behave the least like the other states So after all, I believe that my approach requires no changes to completion semantics, has better backward compatibility, offers nicer, simpler and more composable syntax to developers, and gives more predicability with cancellation semantics that are easier to reason about. If you want a particular behaviour from Domenics proposal, you still can model it fairly easy with explicit rejections; In contrast, you can't get the behaviour I desire with Domenics approach. Feedback here on the mailing list and at the repo is warmly welcome. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: The `super` keyword doesn't work as it should?
Raul-Sebastian Mihăilă wrote: An alternative would be to consider the object where the method key was found as the home object of the method. That's just as error-prone, method borrowing would only work when the two objects had the same superclass. Also, what about methods that are not "found" anywhere when called, for example when used with `call`/`apply`/`bind`? Or static class methods that don't use `this` at all and are called like a plain function? Are you suggesting that every property access that yields a function implicitly creates a closure over the "home"/"found" object? That's a no-no for obvious reasons. Kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: The `super` keyword doesn't work as it should?
/#!/JoePea wrote: Why can't `super` simply be a shortcut for "look up the prototype of the object that the method is called on, then find the `.constructor` property and call it on `this`"? That seems to be simple. Simple, yes, and broken in the case of multi-level inheritance: ``` const x = Object.assign(Object.create({ method() { console.log("parent"); } }), { method() { console.log("child"); Object.getPrototypeOf(this).method(); // super.method() } }); x.method(); // works as expected const y = Object.create(x); y.method(); // infinite loop/stack overflow ``` A `super` query must not depend on `this` (only), it must statically resolve the object on which the called method is defined. In constructors, using the prototype of the currenctly called constructor for `super()` works well, but you'd need to use `Object.setPrototype` as there is currently no declarative way other than `class`es to define functions with custom prototypes. In methods, there would need to be a way to populate the [[HomeObject]] other than declaring the method as part of a class/object literal. Kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Class expressions in object initializers.
/#!/JoePea schrieb: A use case could be to dynamically name a class at runtime without `eval`. `let o = { [name]() {} }` produces a named function inside of `o` (at least in Chrome) without needing eval, and then we can extract it from the object. If you just want to name a class, there are much easier ways to do that: let x = class { get name() { return dynamicName; } … }; or class x { … } Object.defineProperty(x, "name", { value: dynamicName }); Kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Class expressions in object initializers.
/#!/JoePea wrote: Might be nice to be able to do it with classes too: ```js let dynamicName = "foo" let o = { class [dynamicName] { /* ... */ } } console.log(o.foo) // logs the class ``` You can already do let dynamicNAme = "foo"; let o = { [dynamicName]: class { … } }; but I can see absolutely no reason why you'd want to put a class inside an object literal. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Can strict parameters shadow strict function names?
Mark S. Miller wrote: var foo = function bar(bar) {'use strict'}; On all version of Safari/JSC I just tested, this code gives a SyntaxError: Invalid parameters or function name in strict mode. On all versions of Chrome/v8 and FF/SpiderMonkey I just tested, this code is accepted without error. Which behavior is incorrect? This appears to be a bug in Safari/JSC. Is this an ES5 vs ES2015 issue? No, both ES5 <http://es5.github.io/#x13.1> and ES6 <http://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions-static-semantics-early-errors> only have a syntax error if there are duplicate *parameter* names, regardless of the name of the function. We are running into this when loading the output of a minifier as strict code. Guess you should file a bug there - it a) doesn't make sense to name a function expression (does it ever in minified code) and use the same name for a parameter b) it should not fail in real-world engines even if the spec says something else. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Oddly accepted RegExps
Jeremy Darling wrote: /[]]/ This one throws me, that should require the first ] to be escaped (\]) to be useful. I can see it parse and accept but have no clue why or what it would do. It should throw an error. I can't see it accept anything. Afaics, it's equivalent to /[]\]/ - which contains an empty class that never matches anything, which is followed by a literal "]". Kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Reflect.create()
… was bad typed by me there. Indeed it was. I tried to explain why I mean that this isn't a real object by saying that it doesn't contain prototype or constructor and thereby people got the analogy. Often when I say things are not things, as by object is not objects, I assume people manage to reason without having to pin facts straight into their faces. Sorry, but this approach isn't going to work on this mailing list here or when you are going to write a technical document like a spec proposal. Don't talk in (bad) metaphors, state facts and use precise language. We still don't understand how your `Reflect.create` is supposed to work or be implemented, how it is different from the old approach, and what exactly its advantage(s) will be. Kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Reflect.create()
Hi Even! Wierd. Was having this discussion / pep-talk with Brendan Eich and think he understood that fairly.( https://twitter.com/ev1stensberg/status/722180638971936768) Thanks for that link, but while Brendan Eich seemed to agree with the idea that *something* had to be done about defaulting declarations, he also showed some confusion about your ideas. Btw, that gist you linked (https://gist.github.com/ev1stensberg/883fd67da9809c84c08b84982e74148a) seems to be broken now. About lack of answer in the reason, you should read the Medium article again, and reconsider what I said about ambiguously written code. I think it provides a clear intent, of which we want to avoid re-writing an assignment in order to use the logical OR. Yes, I did reread the article. I know that there are many wrongs about | var value = value || "another value"; but I failed to understand which ones you mean. By "avoid re-writing an assignment" you refer to the duplication/repetition of the variable name? And what is ambiguous about this code? It's purpose is well-known, it's behaviour is well-defined, and after all it's a common JS idiom. In the medium post you seemed to propose a new "declare" keyword that could replace the repeated variable name, and that keyword would magically resolve the the contextual variable if I understand correctly. OK, regardless of what I think about this idea (too verbose, too implicit), what does this have to do with your `Reflect.create` proposal? I advice you to read this on MDN <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect> which explains what I mean about "not an object" . ( It's a built-in object) Uh, `Reflect` is still an object if that's what you refer to here. Maybe what you actually wanted is to introduce a new Specification Type that works similar to a Reference? Where you need to assign it through a object assignment. And yea, the name was intentional. What makes this somewhat similar to `Object.create` is that we create an logical instance, but not an actual object like `Object.create` does. Sorry, you lost me here again. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Reflect.create()
even stensberg wrote: I wrote up a draft about how I'd like this to look at: https://github.com/ev1stensberg/proposal-reflect-or I'm sorry for the harsh tone, but that's not a draft. I tried to read [your medium post](https://medium.com/@ev1stensberg/iteration-in-javascript-needs-a-tectonic-shift-a74b6554bbd7) but failed to understand anything (and didn't get any point you were going to make). As such, the "Reason" for this proposal is completely missing to me. While I fail to understand what your proposal is all about, it seems to have something to do with defaulting values. And great, you've even asked the question "How is this different to Default Param in ES6 / the OR operator?" yourself in that text - but there is no answer?! The next thing that completely escaped me is your API description | `Reflect.create(target, value, [DefaultValue])` | | Creates a Reflect, which is not an object. Uh, what? What is "a Reflect"? And the first thing that came to my mind after I read what you're talking about is that you should rename the proposal. `Reflect.create` will remind everyone of `Object.create` (given that some of the methods are duplicated between `Object` and `Reflect`) and one would expect that they do the same or at least have a similar purpose. You seem to be proposing something completly different that has nothing to do with creation. Kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: stable sort proposal
Isiah Meadows wrote: A polyfill could check if `A.p.sort` is stable, replacing if necessary, and alias the old one to `A.p.fastSort` if it doesn't exist. How does one check/test for the stability of a black-box sort? You can't, afaik. In my opinion, you'll never be able to rely on the stability of `Array.prototype.sort` because of backward-compatibility with older implementations where it is unstable. As ugly as it might be, I'd recommend a separate `Array.protytype.stableSort` (with an unambiguous name) therefore that can be tested for existence and polyfilled in absence. Or at least we'd need to tag the available implementations explicitly: ```js Array.prototype.fastSort[Symbol.isStable] = false; Array.prototype.stableSort[Symbol.isStable] = true; Array.prototype.sort[Symbol.isStable] = /* to be chosen by implementer */; ``` which has the benefit that a test `if (…sort[Symbol.isStable])` will yield a falsy default value (`undefined`) in legacy implementations. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Object.prototype.forIn
Langdon wrote: Something that simply wraps this all-to-common code: var key; for (key in obj) { if (obj.hasOwnProperty(key) === true) { ... } } Imo the problem is not that there is no wrapper method for this pattern, but that this code is all too common. It should rarely be needed, and is mostly wrong anyway. The cases to consider are * You use `obj` as a dictionary. If you want to safeguard against inherited properties, you use `obj = Object.create(null)`. Those objects don't even have a `.hasOwnProperty` method. And with ES6, a `Map` is a better solution anyway. * You are enumerating array keys. To safeguard against inherited properties from `Array.prototype`, you should not use `hasOwnProperty` but rather use the proper loop type that iterates indices instead. * You are processing JSON. `JSON.parse`'d objects inherit only from `Object.prototype` which does not have enumerable properties anyway. * You are processing (JSON/dictionary) objects and fear that someone added enumerable properties to `Object.prototype`. Well, that's their fault, not your loop's one. If the environment is broken, your code is as well; there's nothing you can - and need - to do against. * You are processing arbitrary objects with unknown prototype chains. To skip inherited properties in a `for in` loop, the only safe approach is to use `if (Object.prototype.hasOwnProperty.call(obj, key))` or avoid the drama altogether via `Object.keys`/`Object.getOwnProperty…`. The last case is the only one where you'd really need `hasOwnProperty`. The proliferation of `if (obj.hasOwnProperty(key))` needs to be stopped, it's cargo cult programming at best. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: non-self referencial cyclical promises?
Bradley Meck wrote: 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",...)` I fear that's what the standard says, yes. The ES6 spec does too many (and in some cases, unreasonably many) `then` calls on promises anyway to be followed by an efficient promise implementation. [Promises/A+](https://promisesaplus.com/) in contrast says | Implementations are encouraged, but not required, to detect such | recursion and reject promise with an informative TypeError as the | reason. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Destructuring an object into a new object (like Underscore pick but ESier)
Viktor Kronvall schrieb: What would this do? ``` let newObj = {obj.a.b} ``` `{a: {b: obj.a.b}}` or `{a: obj.a.b}`? Or should nested property access be disallowed? Neither - `obj.a.b` is `(obj.a).b`, so it's equivalent to `let newObj = {b: obj.a.b}`. The spec would basically be something like | Let propKey be GetReferencedName(exprValue) and otherwise [the same](http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer-runtime-semantics-propertydefinitionevaluation). ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Destructuring an object into a new object (like Underscore pick but ESier)
Zacqary Adam Xeper wrote: But if I want to initialize a new object that pulls in just the foo and bar properties, I have to type this whole structure out: let newObj = {foo: obj.foo, bar: obj.bar, quux: 4} Or, if I want to use shorthand property names, I can use a destructuring statement, but then I have to type all the property names twice: let {foo, bar} = obj; let newObj = {foo, bar, quux: 4}; I would suggest that we also allow property references, not only variable identifiers in shorthand property notation: let newObj = {obj.foo, obj.bar, quux: 4}; What do you think? Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Any reason why __proto__ is not a well known symbol?
Andrea Giammarchi wrote: As much as Id love to see dunder-`__proto__` burn away from any future specification, Before doing that, we should burn it away from everyones code :-) there are at least two use cases I do like in terms of simplification: 1. to shortcut literals with enumerable, configurable, and writable own properties that extend known objects (or null) such `{__proto__:null, key: 'value'}` . This cannot be compared with the tedious `Object.create(null, {key: {enumerable: true, writable: true, configurable: true, value: 'value'}})` The much simpler solution to that would be `Object.setPrototypeOf({key: 'value'}, null)` (which also returns the object). Admittedly, putting the prototype in the end is a bit awkward, and `__proto__` in a literal probably simplifies creation optimisations. The way to overcome this would be to promote the [prototype `<|` operator](http://wiki.ecmascript.org/doku.php?id=harmony:proto_operator), which I would love to see in ES8. Anyone up for making an up-to-date proposal? 2. to explain inheritance through the console or to people in general, using it only as virtual-read-only reference to the inheritance chain I wholeheartedly recommend to use the term *[[prototype]]* (in italics or color) for this, and call it out as what it is: an **internal** property. Don't teach people that `__proto__` is a magical property - it is not (causing confusion); and they only will start or continue using it in new code. Even in code examples, or simple demonstrations, use `console.log(x, Object.getPrototypeOf(x))` over `console.log(x, x.__proto__)`. Regards, Bergi PS: Ceterum censeo __proto__ esse delendum :-) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Optional Chaining (aka Existential Operator, Null Propagation)
Claude Pache wrote: .? (?) [?] Yes, that syntax is possible. Whether it is preferable is a question of taste. Personally, I don’t like it: * I slightly prefer `?.` over `.?` for the following reason: The `?.` token may be conceptually separated in two, first the question mark which checks whether the expression at its left evaluates to null/undefined (and orders to stop processing if it is the case); then the dot which proceeds with property lookup. Totally agreed. * I find that the question mark inside the brackets is out of place, as it isn’t part of the arguments (for function call) or of the expression defining the key (for property access). I agree here as well, it does feel out of place, and `?[…]`/`?(…)` would feel a lot more natural. Given that those are not feasible for parsing however, I would still prefer them obj[?expr] func(? …args) new C(? …args) over the proposed alternative obj?.[expr] func?.(…args) new C?.(…args) where the placement of the dot is just horrifying my eyes. Maybe we could at least use some other character instead of the dot? obj?:[expr] func?:(…args) new C?:(…args) might bear too much resemblance to the ternary, but imo the colon fits better than the dot here. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Using 'this' in default parameters
Jason Orendorff wrote: On Fri, Jan 29, 2016 at 8:14 AM, ` Mystery . <mystery...@gmail.com> wrote: IMHO I don't think the default parameters should be evaluated within the context of the function being called, at least not while it's outside of function body's region.. Is there a specific reason to do that, or it's just a design preference? Sure, there is a reason: it's about how defaults are used. Most defaults are probably constants or empty objects. Those don't need to refer to any variables at all, so we can set them aside. Well, primitive-valued constants are fine. But if you have an empty object constant, which is statically attached to the function instance instead of being re-evaluated at every call, that would surely cause enough havoc already :-) Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Using 'this' in default parameters
` Mystery . wrote: During the development of an ES6 web application, I came across a situation where I wanted to bind 'this' of the outer function to a parameter of an inner function Use an arrow function for that: ``` function outer() { const inner = (_this = this) => { console.log(_this.a); // 1 } inner.call({}); } outer.call({a: 1}); In the latest Firefox, the above script prints 'undefined'. This seems pretty counter-intuitive, and it also fails when I try to pass 'this.a' as default value for the parameter of the inner function. I wonder if this is an intended behavior? Thanks in advance. Yes, it is intended, and pretty intuitive - default initialisers are evaluated in the scope of the called function, at the call - they're not values that are computed at the time of the definition of the function. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: JavaScript Language feature Idea
Bob Myers schrieb: The syntactical construct `array()` is unused as far as I know, since currently it would always generate a syntax error--an array is not a function. It's a runtime `TypeError` rather. Thus we can use this as in ``` [1,2,3](-1) ``` Shouldn't break anything. This would break much more than a `last` getter/method or `nth`/`at` method. Arrays becoming callable would mean that their `typeof` changes from `"object"` to `"function"`, which is a very bad idea. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Legitimate uses of IIFEs?
Fabrício Matté schrieb: Btw, the term "IIAFE" should probably be avoided, as the "A" can ambiguously mean "Arrow" or "Async". I've never heard of an "Arrow function expression" - it's just "arrow function" :-) I think it would always be clear from the context anyway. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Legitimate uses of IIFEs?
Andrea Giammarchi schrieb: Reading this thread felt like one problem is gone and another is coming ... and to be honest, a `module.exports = new Promise(myModule);` should most likely become a new standard for asynchronously defined modules in the node.js world, and I've no idea how that could be represented through the current ES2015 specs which seem to assume every module loading could be asynchronous, but the exported behavior would be definitively sync. I think a top-level (read: module-level) `await` could solve this quite elegantly. ... or maybe I am missing something, like the fact if a module export a Promise it's automatically usable no matter if the requester was within a sync execution or async? That would be up to the loader. But I don't think a module loader should mess with these things, for various reasons. Error (=rejection) handling would be obscure. Sometimes I *want* to export promises without anyone awaiting them. And of course, exports do resolve to variable bindings, not to values, so this would be hard to align with the current spec. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Fwd: Indirect references to variables
John Gardner schrieb: ECMAScript currently offers no clean way to "dereference" a variable in the current scope. There is one. It's called `eval`. A hacky workaround is to create an anonymous function that simply returns a reference to the named variable: function dereference(name){ return new Function([], "return " + name)(); } dereference("Paintbrush") === Paintbrush; // true Actually that does only work with global variables as well, quite like the property access on the global object. Another approach might be to leverage `eval`, which opens up the obvious issues of performance and security. And so does your proposed backslash operator. The only difference I can see would be that you are wishing to `eval`uate only identifier references not arbitrary expressions, but *that* can be trivially dealt with by testing the expression to match the Identifer production. A regex could do that. Neither performance nor security would be any better though. The preferred way of what you are trying to do is to whitelist the classes you want to make available, and by naming/aliasing them explicitly. Basically var classReference = {Paintbrush, …}[className]; var instance = new classReference(); For additional security, you might want to use an object that doesn't inherit from `Object.prototype`, or just a `Map` right away. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Could String internalize an ArrayBuffer?
Coroutines schrieb: What I want is to be able to view a String through a typed array without duplicating the memory/contents of that string. The largest problem I see with this is that strings are immutable while typed arrays / buffers do allow indexed write access. So before using strings instead of buffers (or efficiently creating buffers from strings), we'd need to introduce something like ConstTypedArrays. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Reflection to know if executed within a generator/async ?
Andrea Giammarchi schrieb: simply adding async and await and the only change to do in a well known/used *synchronous* API would be to check if the returned value is held and behave accordingly? No, making a consumer of an API asynchronous should not be simple. Unless you are only writing pure functions, everything that involves states will very likely break. Concurrency is not trivial, it needs a lot of consideration. as soon as you go for async/await or a generator that function will return a Promise for you. Please never do that. Functions that sometimes return promises and sometimes not are already known to be an antipattern. Making this obscurely dependent on some fragile syntactic conditions could only make this worse. If you want to migrate your library to asynchrony, just make it a breaking change. Your consumers will thank you for it. Kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: String.prototype.padLeft / String.prototype.padRight
Coroutines schrieb: I disagree with what has been decided. :p I was in favor of {trim,pad}{Right,Left}(). The reason: Iterators. As JS moves forward toward people creating iterators to traverse an object, referring to the start and end of something *can* be ambiguous. There is no confusion with *Left() or *Right(). I could not disagree more with that. Iterators don't have a "left" or "right" side, they have a start and an end? The former would be much more confusing. So when you `padStart` or `trimStart` an iterator you can be sure it will always put something in front of it or cut something at the beginning, regardless whether your iterator does iterate your array or structure backwards (right-to-left?), from left to right, top-down, bottom-up, or whatever direction you've drawn/imagined it in. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: String.prototype.padLeft / String.prototype.padRight
Jeremy Darling schrieb: Just as an aside, I think padLeft/padRight should still be added in addition to padStart/padEnd. There are times (token generation, identity padding, etc) where you would want to specify the handedness of the pad operation and ignore the locale. This goes for the trim* methods as well. I don't get that argument. Doesn't `start`/`end` exactly do that: ignore the locale? It always trims/pads at the start/end of the string, regardless whether that will be rendered to the left or right of the screen? Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Concise Method Binding
Andrea Giammarchi schrieb: Just my thoughts, I wouldn't put any self-bound thing in the class and rather improve that `::` proposal so that whenever you `obj::method` it creates a uniquely bound callback so that `obj::method === obj::method` This was considered: https://github.com/zenparsing/es-function-bind/issues/17 - it's quite unexpected that an operator would return the same result every time, and there are security considerations as well. Also it would be quite complicated to spec - how and where did you store the memoisation. Feel free to join the discussion! Using the `::` operator in the class declaration itself makes sense to me. It conveys "this method will always be bound" very effectively, and you wouldn't even need special syntax to access it. ```js class Xample { ::myListener(…) {…} } ``` should desugar to ```js class Xample { // a getter on the prototype get myListener() { // with per-instance memoisation return this.myListener = (…) => { // that returns a bound method … }; } } ``` It might be equivalently done via a custom decorator of course: ```js class Xample { @autobind myListener(…) {…} } ``` Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Concise Method Binding
Gilbert B Garza schrieb: Forgive me if I'm missing the point, but isn't the entire purpose of using classes to make all instances share the same function in memory via `this` ? If you want methods to always be bound, why not use closures instead? ```js function Person (name) { var person = this person.greet = function () { return person.name + " says hi!"; }; } Yes, the point of prototypes is sharing. But maybe we don't want (cannot use) that. The point of the `class` syntax is just to enable a more declarative definition of class methods - which should include some way to create instance methods as well, simply because they're needed often enough. And being able to declare methods that will get bound outside of the constructor (even if that's a bit confusing) avoids much boilerplate again. Just compare ```js class Person extends … { constructor(name) { super(name); this.greet = () => { return this.name + " says hi!"; }; } } ``` vs ```js class Person extends … { // with default constructor ::greet() { return this.name + " says hi!"; } } ``` Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Generator getter method
Mohsen Azimi schrieb: I'm proposing to allow `get corners* () { ...` (a generator getter method) so the for..of loop can be written like this: ``` for (let corner of rectangle.corners) { console.log(corner); } ``` I would avoid that. `rectangle.corners !== rectangle.corners` could be quite confusing. Creating the generator explicitly is a better idea. And as kevin said, you still can return generators from your getters manually if you really want that. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Concise Method Binding
Jordan Harband schrieb: > JD Isaacks <j...@jisaacks.com> wrote: > >> class Foo { >>bar = () => { >> // bound >>} >>buz() { >> // unbound >>} >> } In your first example, the arrow function's "this" would be the "this" of the context the "class" is defined in - it wouldn't be bound at all. No, the methods defined with "=" are automatically moved into the constructor, so that they are created once for each new instance. `this` in the arrow function would in fact be bound to the instance. It's indeed super-confusing to "declare" such methods right inside the `class` though, that's why I'm really opposing that proposal (https://github.com/jeffmo/es-class-static-properties-and-fields). Greetings, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Arrow function declaration
Федор Неживой schrieb: I'm looking for a champion for https://github.com/gyzerok/ecmascript-arrow-function-declaration Your proposal doesn't seem to solve the problem that you gave in your rationale. Let me paraphrase: You've got curried functions, and you want to partially apply them declaratively without caring for order. ```js // does not work const sumOfSquares = compose(sum, squares); const sum = reduce((x, y) => x + y, 0); const squares = map(x => x * x); ``` ```js // would work because of hoisting: function sumOfSquares(xs) { return compose(sum, squares)(xs); } function sum(xs) { return reduce((x, y) => x + y, 0)(xs); } function squares(xs) { return map(x => x * x); } ``` Now you are proposing some kind of "arrow declaration" that desugars to a function declaration. This makes no sense. The non-working code doesn't benefit of that in any way - there are no arrows function, only function calls. What you are *actually* looking for seems to be a lazy initialisation of variables - the variable declaration is hoisted just as usual, but the initialiser would run when the variable is used the first time. The following would be what I'd envision to solve your problem: ```js // does work lazy sumOfSquares = compose(sum, squares); lazy sum = reduce((x, y) => x + y, 0); lazy squares = map(x => x * x); ``` where `lazy` would work pretty much like a `lazy val` in Scala. Regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Exponentiation operator precedence
Alexander Jones schrieb: Exponentiation is written in conventional mathematics as if it were a postfix unary operator, parameterised by a value written in superscript. IMO this puts it in a whole different class to binary operators where both operands are written equally. I don't see a ** b ** c as a good reflection of mathematical convention. I disagree. When in maths we write x sup y sup z /sup/sup, we mean x ^ (y ^ z). Which is exactly what `x ** y ** z` will do. And no, we never write x supy/sup supz/sup, if we wanted to express that we'd write x supy * z/sup (or often enough, with implicit multiplication, i.e. no * operator: x supy z/sup). If we'd want to express that in JS, it would by x ** (y * z). Number.prototype.pow, on the other hand, would be fine. You don't mean to use it like `x.pow(y).pow(z)`, do you? Sure, a function or method invocation is always explicit with parenthesis. But that's no improvement over the current `Math.pow`. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: please add x .= f()
Isiah Meadows schrieb: That's not really the point. The suggestion is this instead: ```js if (s[0] === '/') s = s.slice(1); if (s[0] === '/') s .= slice(1); ``` This already exists in CoffeeScript and most derivatives/dialects. ```coffee s .= slice 1 if s[0] is '/' ``` Don't know of any other languages that have an equivalent, though. Really? Which version of CS, or which dialect are you using? It doesn't work for me in the online tool http://coffeescript.org/#try:s%20%3D%20%22%2Fsomething%22%0As%20.%3D%20slice%201%20if%20s%5B0%5D%20is%20'%2F'. But if you're that much inclined to save single characters, I'd recommend to use ```js s = s.slice(s[0] == '/'); ``` Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: name anonymous functions on property assignments
Just saying that an exposed property name is a different (and potentially more broadly exploitable) capability than exposing a local variable name. TC39 reached consensus on automatically assigning the `name` property for expression forms like: Identifier = FunctionExpression and so it is part of ES2015. We did not have consensus on doing the same for: MemberExpression.IdentifierName = FunctionExpression or MemberExpression[Expression] = FunctionExpression so it is not part of ES2015. There were various objections that would have to be overcome before we could adopt that. Ah, that's what I wanted to know. Can you detail these objections, please? Or link to the TC39 notes where these were discussed? I see that method names are more capable than local variable names, but aren't we already naming methods by default everywhere else? Even those with computed keys? To me, there is not much difference between let o = { method: () = {…} }; and let o = {}; o.method = () = {…}; yet the first function gets a name while the second one doesn't. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: name anonymous functions on property assignments
I'm completely against magic-function-name assignment for various reason and leaking ain't one. What are these reasons? (I couldn't find previous discussions; if there are any, a link would be sufficient) I agree that explicit naming is better than implicit, and like to use function declarations over unnamed function expressions myself, but for named arrow functions this seems like a good idea. And browsers are doing it already anyway for a better debugging experience. Regardless, it's in ES6 now, I just wondered why it's not as consistent as I expected it to be. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: name anonymous functions on property assignments
a big concern for me is what to do about functions being passed around Nothing happens to them. This feature is only about assignments where the right hand side consists of a function expression. var a = {}; a.foo = function () {} // .name would be foo Yes. var b = {}; b.bar = a.foo; // .name would be bar No, the name would still be foo. It doesn't change when the function already has a `.name`, and `a.foo` is not an anonymous function definition but a memberexpression. doThing(()={}) // what is .name? Nothing. There is no identifier hanging around the function expression. It's anonymous, and will stay so. You see, no magic! :-) Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
name anonymous functions on property assignments
Hello! Currently, unnamed function (and class) definitions that are part of a variable assignment or property definition are automatically given the name of the target identifier (seehttp://www.ecma-international.org/ecma-262/6.0/#sec-assignment-operators-runtime-semantics-evaluation andhttp://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer-runtime-semantics-propertydefinitionevaluation). Same thing happens for (destructuring) default initialisers and variable initialisers. However, if a function (or class) definition is assigned to a property of an object, this doesnt happen: var o = {}; o.someProperty = function() { }; o.otherProperty = class { }; I dont see any reason for not doing this, it just seems to be advantageous and make the language more consistent. Im quite sure it wouldnt break any compatibility. This would only require a minor change tosection 12.3.1.4 http://www.ecma-international.org/ecma-262/6.0/#sec-static-semantics-static-semantics-isidentifierref, namely making IsIdentifierRef for MemberExpression : MemberExpression [ _expression_ ] MemberExpression . IdentifierName return true. (where it currently yields false). Everything else had already been abstracted out enough :-) What do you think, can we fix this? Do I need to make a more explicit proposal? Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Extensible destructuring proposal
Domenic Denicola schrieb: For maps you can just do ```js const [[k1, v1], [k2, v2], ...rest] = map.entries(); ``` The problem with this is that you would need to know the order of the keys in the map. Your code does only extract the first and second key-value pairs, allowing us to get the key values of them, but this syntax does not allow us to extract the value for a given key from somewhere in the map. Predictability is all fine, but I still consider maps to be inherently unordered. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Extensible destructuring proposal
Samuel Hapák schrieb: I find your idea really interesting. If get it, benefit of your approach is that user explicitly specifies how to extract data instead of relying on extraction method defined by object being extracted. This way, you can create multiple competing extractors That wasn't my primary goal (indeed most data structures would have only a single extractor). The main benefits I see are: * explicit is better than implicit * works anywhere in a destructuring pattern, not only the topmost level * can be chosen not to be used (e.g. for `let {size} = myMap;`) The only downside I see is the verbosity. That's an advantage imo :-) Could you show some examples? Thanks! I don't think there's much more than the ones I already gave. Notice that those `NoOptions` and `WithOptions()` was even an example for multiple extractors to be used for destructuring factory functions (by applying them), though I don't know whether that's the best solution for this `import` problem. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Extensible destructuring proposal
Ben Newman schrieb: That said, virtually every time I've written an unapply or unapplySeq method in Scala, it has been with multi-case pattern matching in mind, and we're only talking about destructuring assignment here, which I suppose is like a single-case pattern match. Right, we don't really have pattern matching in ES yet. I don't want to introduce that as well, it would be a pretty heavy change imo. If you have time/motivation to put together a proposal for Symbol.extractor, I would very much encourage you to think about the possibility of introducing multi-case pattern matching as well, as I think that would add significant value to the proposal, as well as highlighting some tricky issues. I've seen that Scala returns an Option for a pattern. My first thought was to make @@extractor return an empty iterator, but I'm not sure whether that's semantically sound. We then could consider an iterator to be not matching if any of the target elements are left `undefined`, i.e. when the iterator is exhausted before all elements have gotten a value, similar to default initialisers are handled today. Do you think that is viable? Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Extensible destructuring proposal
Domenic Denicola schrieb: Well, the spec says they are ordered, so I'm not sure where you're getting that from. Yes, the spec defines an order to make iteration predictable and consistent, but that doesn't mean anyone would use a `Map` for an ordered structure. I would consider new Map(Object.entries({a: 1, b: 2})) and new Map(Object.entries({b: 2, a: 1})) to be equivalent for all purposes of an algorithm that uses commutative operators. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Extensible destructuring proposal
Samuel Hapák schrieb: The main idea is, that if object defines `Symbol.get` method, it gets used to access properties of object instead of `[]` when destructuring. Aw, when I read extensible destructuring I had hoped to see an extension to the destructuring syntax, not to see how semantics of destructuring objects are changed. What do you think about extractor functions, like in Scala http://www.scala-lang.org/old/node/112? Instead of `unapply` or `unapplySeq` methods we'd probably use an `@@extractor` (`Symbol.extractor`) method or so, allowing us to do let Map({a, b, c}) = myMap; let List(a, b, c) = myList; const Map({author: Map({name: {first, last}, birthdate})}) = book; which would desugar to let [{a, b, c}] = Map[Symbol.extractor](myMap); let [a, b, c] = List[Symbol.extractor](myList); const [{author: __author}] = Map[Symbol.extractor](book); const [{name: {first, last}, birthdate}] = Map[Symbol.extractor](__author); where each extractor method would return an Iterable that is assigned to the arguments of the extractor. (A Proxy to lazily destructure object literals in there is a good idea, thanks @Claude). This would even allow us to call functions on destructuring, think about module imports: // a.js export default function factory(options) { … return moduleInstance; } // b.js const NoOptions = { [Symbol.extractor](factory) { return [factory()]; } }; const WithOptions = (...args) = ({ [Symbol.extractor](factory) { return [factory(...args)]; } }); import NoOptions(A) from a; import WithOptions(config)(A) from a; // A === moduleInstance What do you think about that? Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Instance bound class methods
Matthew Robb schrieb: What I'd really like to have in the language is the ability to store a property access into a single binding Notice that the https://github.com/zenparsing/es-function-bind proposal does exactly this, at least for methods (and I don't think I would want it for arbitrary assignments). Your example code would look like this: let someObj = { doStuff(){} }; let doStuff = ::someObj.doStuff; doStuff(); Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: function.sent beta equivalence?
Mark S. Miller schrieb: Something strange and bizarre that Jafar and I just discovered after the TC39 meeting: We all know that there are a set of conventional combinators, like flatMap, that work fine for iterators. Iterators are uni-directional. Generators are bi-directional. (As Jara observes: Generator implements Iterator, Observer) We thought that these combinators did not apply to generators in their full bidirectional glory. We were wrong. Flatmap of generators can approximately be modeled in terms of yield* wrap So you have a signature of `IterableGeneratori, o, r - Generatori, o, r` in mind, not a monadic `join`-like function that takes a generator? flatMap([g1, g2]) is equivalent to (function*() { yield* wrap(g1, function.sent); // result of g1 ignored! return yield* g2; }()) Maybe it should be (function*() { return [yield* wrap(g1, function.sent), yield* g2]; }()) with `IterableGeneratori, o, r - Generatori, o, Iterabler`? Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: insteadof operator
Bucaran schrieb: It would be nice if there was a special construct like `typeof` or `instanceof` that would take a name and evaluate to whatever variable / function of the same name existing in the parent scope (or undefined otherwise). Sorry, no. Please not. This would be a horrible feature, making name collisions (which are already confusing as hell at times) even more confusing. Scoping is already complicated, no need to introduce an edge case that all tooling (including human brains) would need to get learned. There already does exist a simple, familiar, and working solution (well, multiple ones actually), it's not worth the trouble of introducing a new operator. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Fwd: Re: insteadof operator
joe wrote: Would there be any security issues? Also, runtime or lexical scope? I've actually wanted this feature for a while now, but always assumed it had no chance of happening due to security issues. Of course, I know nothing about security so I could be wrong. Actually, now that you mention it, yes there might be. Iirc, some sandboxing techniques rely on executing unknown scripts in an own scope where globals (and other stuff that could be used to escape) are shadowed by local variables that contain the secured counterparts. By introducing an operator to undo shadowing, you could break out of that. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pick operator
Bob Myers schrieb: In the spirit of the discussion about language complexity and extensibility, consider the following brain-addled, pre-strawman proposal for a new pick operator. http://rtm.github.io/boberator.html Thanks, some quite interesting ideas! Some quick thoughts while reading: * `o typeof o === 'object'` should just test for `o != null`. Or at least not ignore function objects. * that array picker operator should be omitted. Nobody needs this, picking from an array is very rare. Just use the standard `#` picker operator, onto an array literal, with explicit property names if need be. * Don't introduce a new syntax for computed properties, we have brackets already. That `*` looks to much like generator functions. However, instead of introducing a new operator I'd rather like to extend destructuring and property shorthands to take more than single identifier. The basic examples from your motivation could easily handled by this, withoug looking much worse: let pickedObj = {o.p1, o.p2}; // uses p1 and p2 for property names {pickedObj.p3} = o; // takes p3 as property name, assigns to LHS `pickedObj.p3` Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: let function
Alexander Jones schrieb: On Thursday, May 14, 2015, Domenic Denicola d...@domenic.me wrote: They can, in fact, be scoped in a for loop. That's not what I see, in strict mode at least, which I assume most people consider de facto by now! From V8: SyntaxError: In strict mode code, functions can only be declared at top level or immediately within another function. That's ES5. In ES6, function declarations are allowed in blocks - with the new block scope semantics. This was only possible as ES5 strict mode held that spot open so now it doesn't break anything :-) Yes, it will need a while until people get accustomed to that. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Evaluate postfix after assignment
Emanuel Allen schrieb: Typo. I'm worrying about this: arr[i++]=obj[e] arr[i++]//this will evaluate first before the value return since the = have a lower precedence than ++. Notice that operator precedence has to do with parsing an (otherwise ambiguous) expression, not with evaulation order. So this is parsed to (((arr)[((i)++)])=((obj)[(e)])) and then basically evaluated left-to-right. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: is an iterator allowed to reuse the same state object?
No, it must return a new object every time. See https://esdiscuss.org/topic/performance-of-iterator-next-as-specified for the last discussion on this. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
stack-unlike behaviour of the execution context stack
Hello! In http://people.mozilla.org/~jorendorff/es6-draft.html#sec-execution-contexts, a paragraph reads: | Transition of the running execution context status among execution | contexts usually occurs in stack-like last-in/first-out manner. | However, some ECMAScript features require non-LIFO transitions of the | running execution context. I wonder what this means? My first guess was that this refers to generators, whose contexts enter and leave the stack multiple times at will (in contrast to a normal context that enters only once and is destroyed after being suspended), but I found that generator contexts are pushed to and popped from the stack as everything else. On closer inspection, I found that the spec sometimes uses the term remove and sometimes pop when suspending an execution context, but I can't imagine a case where this did not refer to the topmost context on the stack. Can you give me an example? Did I miss something? Thanks, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: super.prop assignment can silently overwrite non-writable properties
Jason Orendorff schrieb: […] `super.prop = 2` ends up with O=X.prototype. Uh, yes. And it should set `X.prototype.prop` to `2`, because that still is writable and not affected by the attributes of `x.prop`. So I would expect `x.prop` to still have the value `1`, shadowing the prototype property. (at least that's how I understood super references) Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Don't test promise results on their thenability multiple times
Hello, while working on the promise memory-leak problem https://github.com/promises-aplus/promises-spec/issues/179 I noticed the following in the current ES6 spec: ```js var count = 0, nonThenable = {get then() { count++; return undefined; }}; function GetResult(n) { if (n = 0) return nonThenable; return Promise.resolve().then(()= // just for a little delay GetResult(n-1); ); } GetResult(5).then((res) = { assert(res == nonThenable); assert(count == 1); // !!! }) ``` Since we only *resolved* a promise once with `nonThenable` (the promise that is returned from `GetResult(1)`), I expect that `.then` is only accessed once. The other 4 promises are *fulfilled* with it, and we know that [[PromiseResult]]s are never thenables. Or should not be, if it didn't change in the meantime. I suggest to change the spec so that a Promise Resolve Function (25.4.1.3.2) is not called multiple times, even if multiple promises (that adopt each other) are fulfilled with it. This would pave the road to allow fixing memory leaks from long recursive adoption chains, so that intermediate promises are no longer considered and can be garbage-collected before the eventual resolution. A possible change could be made by amending the sections 25.4.1.3 CreateResolvingFunctions and 25.4.5.3 Promise.prototype.then like so: * A promise resolve function is an anonymous built-in function that has [[Promise]], [[AlreadyResolved]] *and [[fulfillAdopter]]* internal slots. * CreateResolvingFunctions would set the [[fulfillAdopter]] slot of `resolve` to a function like function fulfiller(resul) { if (! F.[[AlreadyResolved]]) { F.[[AlreadyResolve]] = true Return FulfillPromise(F.[[Promise]], result) } } * Insert a step 5.5 in PerformPromiseThen, like If `onFulfilled` has a [[fulfillAdopter]] internal slot, set fulfillReaction.[[handler]] to onFulfilled.[[fulfillAdopter]] So when a promise is adopted, and its `.then()` method is called, a `fulfill` handler is installed not a `resolve` handler. Which works as long as the invariant holds that result values are not thenable. I haven't thought through the implications that this had on subclassing, but this is supposed to work even if `.then` was overwritten as long as it calls `super.then()` with the original resolve handler. (If it wrapped the resolve handler, we should resolve the value again indeed). regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nailing object property order
Scott Sauyet schrieb: Do you see good reasons *not* to do it, or are you just wondering if there actually were pros to this? Oh, I can see the use cases (you've given a good example, thanks). Everyone needs ordered dictionaries/maps once in a while. Maybe even sortable ones, including `insertAt` or `insertOrderedBy(comp)` methods? I would have loved to get another new data structure (`OrderedMap`? `SortableMap`?) for this purpose. What I am opposing is that objects - originally meant as unordered records - are now officially abused for this. I can see the argument for speccing backwards-compability, but now the people who were originally writing bad (implementation-dependent) code are supported by the spec and can claim that the end users had to update their browsers to ES6-compatibility, instead of needing to fix their bugs. I could even write an `isStrictlyEqual` that goes beyond property equality and checks key order. That's exactly what I am fearing. If such usage takes overhand, are we going to get `Object.prototype.reorderKeys` at some point? (Oh, wait, `Object.reorderKeys` of course). I think there should be a clear distinction between ordered and unordered dictionaries somewhere, with tooling supporting both versions. Instead of stuffing everything into objects. How does an algorithm know whether to use `==`, `===`, `Object.is`, `Object.isSameOrdered`, `Object.equals`…? Bergi (sorry if this came off as a rant. I know it cannot/will not be changed any more in ES6. I'm just missing a clear strategy statement) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Don't test promise results on their thenability multiple times
Another, maybe simpler way to put this: `Promise.resolve` needs to become idempotent, i.e. for all values `x` the expression Promise.resolve(x) must behave exactly as the expression Promise.resolve(Promise.resolve(x)); where it accesses `x.then` only exactly once. The current spec would test for it twice, which even gives way to fulfilling promises with thenables - if only the `then` method is attached to your object after you have resolved your promise with it. Which could cause some quite unexpected results. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Nailing object property order
Hello! Why does ES6 specify the order of keys in objects, maps and sets? Specifically section 9.1.12 [[OwnPropertyKeys]] says the result list must be integer indices in ascending numeric, then strings in property creation order, then symbols in property creation order. Similarly, 23.1.3.5 Map.prototype.forEach and 23.2.3.6 Set.prototype.forEach use the original insertion order of keys for their callbacks, and also their respective @@iterators use the ordered entries lists. What was the motivation to pin these down in ES6? In ES5, objects were intrinsically unordered. ES3 was explicit about that an object is an unordered collection of properties, the same thing is still in JSON for example, where objects are defined as unordered set of name/value pairs. ES5 did only specify that for-in and Object.keys should use the same order (if an implementation specifies one at all). ES6 didn't even tighten this, it only describes it with a new [[enumerate]]-mechanism. But would it be reasonable to expect that every implementation will use the same order in for-in loops and Object.keys as in Object.getOwnPropertyNames/Symbols property listings? I can't imagine how a different ordering would be helpful for an implementation. To me, a fixed order sounds like an arbitrary restriction. There would always be a little overhead in remembering the order, and it would prevent optimisations that could treat {x:1, y:2} and {y:2, x:1} as having the same structure. And while ordered maps/sets are a good thing, they are not really sortable by ones own criteria. If I wanted to insert a value at a certain position, I'd need to first clear the map/set and then re-append all entries in the desired order. There will surely be people who want to use maps/sets like that, and I wonder whether it was deliberately made that complicated/inperformant to support this use case. Does anyone share my concerns? The only thing I've found online was deterministic enumeration https://mail.mozilla.org/pipermail/es-discuss/2013-April/030204.html, pointers to other discussions are welcome. Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nailing object property order
Tab Atkins Jr. schrieb: On Wed, Apr 15, 2015 at 6:39 PM, a.d.be...@web.de wrote: What was the motivation to pin these down in ES6? Because, for objects at least, all implementations used approximately the same order (matching the current spec), and lots of code was inadvertently written that depended on that ordering, and would break if you enumerated it in a different order. Since browsers have to implement this particular ordering to be web-compatible, it was specced as a requirement. I see, that makes some sense at least. But why was the default object [[enumerate]] algorithm not specced to match the [[OwnPropertyKeys]] order then? Most, if not all, of the codes I've seen that unfortunately depend on this insertion-order ordering do use simple `for in` loops (sometimes accompanied by a `obj.hasOwnProperty` check, very rarely an `Object.prototype.hasOwnProperty.call` check). None iterated over the `Object.keys` or even `Object.getOwnPropertyNames` array. Shouldn't we add a guarantee to [[enumerate]] that the subset of enumerated *own* properties comes in insertion order as well? That would still leave open to engines how they deal with inherited properties. Similarly, we remove step 6 (*Order the elements of names so they are in the same relative order as would be produced by the Iterator that would be returned if the [[Enumerate]] internal method was invoked on O.*) from `EnumerableOwnNames` (`Object.keys`)? Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Default `this` value for static promise functions
Hi, I've just got bitten by return getError().then(Promise.reject); where `reject` threw an error that its `this` value was not a Promise constructor. Would it help to make the `C` constructor (in Promise.resolve, Promise.reject, Promise.all, Promise.race algorithms) default to `Promise` when no `this` value is supplied (throw only if it's there, but not an object and constructor function)? Or is this considered to be too error-prone with Promise subclassing, where `.then(MyCustomPromise.reject)` would not work as expected (fail silently)? regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: `of` operator ES7 proposal from Ian Bicking
Brendan Eich schrieb: From https://plus.google.com/+IanBicking/posts/PbXDtNF9Gg6: Huh, for (attr in obj) goes along with if (attr in obj), but for (item of array) doesn't have an equivalent if (item of array) It's obvious in hindsight. An `of` operator … I would like such an operator as well, but I can see a big problem with this proposal: of is not a reserved keyword. And it certainly has its usage as an identifier name already, most prominently: Array.of. The fantasyland applicatives https://github.com/fantasyland/fantasy-land#applicative do have such a method as well. I found a few uses of it in github code https://github.com/search?l=javascriptq=%22var+of+%3D+%22ref=searchresultstype=Code (most of those thousands are false positives or a particular test case, this example https://github.com/ELLIOTTCABLE/from/blob/fb19155abbf39e91a532537599d3d16f592e16b6/lib/from-new.js#L96 is not). Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss