17:47 | <Ben Lesh> | Has there ever been discussion of adding very common functions to the standard. In particular noop and identity ? Is a palatable to propose adding something like Function.noop and Function.identity to the standard, so people stop creating () => {} and x => x over and over in their libraries and codebases? |
17:49 | <ljharb> | yes |
17:49 | <ljharb> | i tried doing that early in my tc39 time, and before i even got to proposal stage nobody found it valuable. engines seem pretty good at optimizing () => {} |
17:51 | <Ben Lesh> | Interesting. I mean the next thing I'd ask for would be a Function.pipe but given the discussion over |> I suspect that wouldn't go over. :) |
17:52 | <ljharb> | unrelated to pipe, that was rejected on its own merits, let me find the link |
17:52 | <ljharb> | https://github.com/tc39/proposal-function-pipe-flow |
17:52 | <ljharb> | ah, i guess not entirely unrelated to pipe |
17:58 | <Ben Lesh> | Yeah, that's pretty much exactly what I'm proposing. Haha. Disappointing but not at all surprising. 😅 |
18:00 | <Ben Lesh> | Have there been any updates to the :: bind proposal? That's been dead-ish since about 2015, I think. |
18:01 | <Ben Lesh> | https://github.com/tc39/proposal-bind-operator .. seems still dead. |
18:04 | <Ashley Claymore> | Has there ever been discussion of adding very common functions to the standard. In particular |
18:06 | <bakkot> | I think if the syntax proposal dies there's at least some chance the stdlib function might come back, though tbh I kind of prefer reading chained arrows or chained calls over reading a call to pipe |
18:06 | <Ben Lesh> | Haha. Yeah, I used to do that trick, but i got tired of explaining it to people. Also passing it around is like noop.lol = 'wee' and everyone has fn.lol from then on. Or delete noop.call |
18:12 | <Ben Lesh> | Well, the current |> proposal makes me sad. I really don't like it at all... which historically means it will do well in the TC39. In fact, if you all want me to be a fortune teller, you could just point me at a proposal, and if I don't like it, it's probably going to Stage 2 minimum. If I do like it, it'll be stuck in Stage 1 forever. 😅 |
18:19 | <Ashley Claymore> | I have a proposal idea. If your fortune telling rates are reasonable I'll DM you 😎 |
18:20 | <ljharb> | Have there been any updates to the |
18:22 | <Ben Lesh> | yes! https://github.com/tc39/proposal-call-this |
18:23 | <ljharb> | lol |
18:23 | <ljharb> | there's a variant of it that tab has suggested as well |
18:23 | <ljharb> | fwiw i made it pretty clear at pipeline advancing to stage 2 that a requirement for going to stage 3 was something like call-this or :: being on a likely path to advancement, if that helps |
18:29 | <Ben Lesh> | fwiw i made it pretty clear at pipeline advancing to stage 2 that a requirement for going to stage 3 was something like call-this or |> at this point, I guess I don't care because I have very little use for that in anything I'm working on at the moment. ~> or the like, on the other hand ARE interesting to me, and it's plausible that RxJS and other libraries could pivot that way. |
18:38 | <bakkot> | I want neither of these things :( |
18:38 | <bakkot> | I would've been OK with pipe if there was a version which made everyone happy, but there isn't |
18:39 | <bakkot> | the call-this operator I am still confused why people think it's a good idea despite me being like a 98%ile user of .call |
18:41 | <Ben Lesh> | I'd only want call-this because pipeline is wrong, TBH. I'm looking to see if there are ways to prep libraries that compose like RxJS does for either the current pipeline proposal or call-this. Current pipeline proposal isn't something people can engineer towards right now in an ergonomic way... We might be able to with call-this though. Still experimenting for my use cases. |
18:44 | <ljharb> | it's a good idea because of the order being wrong with .call, and also syntax is undeniable and robust, which is pretty important for invoking functions |
18:45 | <bakkot> | "syntax is undeniable and robust" is important to rounds-to-0% of programs |
18:47 | <Kris Kowal> | For those programs (like Node.js core), the performance cost of uncurryThis is good to avoid. |
18:47 | <bakkot> | if you're trying to be defensive against people mutating builtins you have to run first cache all of the other standard library stuff anyway, at which point a.) your ergonomics are already shot and b.) caching call in addition is a very small burden |
18:48 | <bakkot> | For those programs (like Node.js core), the performance cost of uncurryThis is good to avoid. |
18:48 | <ljharb> | it's important to a MUCH larger percentage than that, because they transitively run code they didn't author |
18:49 | <ljharb> | the reason node wants to remove primordials isn't because robustness doesn't matter, it's because the current approach sucks for ergonomics and perf |
18:49 | <ljharb> | call-this, specifically, would be a huge benefit for node, which would help quite a lot of programs. |
18:49 | <bakkot> | just because a program has a dependency which makes use of a particular feature doesn't mean that the feature is important to the program |
18:50 | <bakkot> | it may be - as it is in this case - that the dependency is using something so that it can provide a guarantee (e.g. "robust against other code on the page messing with built-ins) which the actual program doesn't care about |
18:52 | <Kris Kowal> | it would be odd for javascript to accept defeat as a safe sandbox language in the face of supply chain attacks when it’s the closest language to winning and the most important field to win. |
18:52 | <ljharb> | true. but the program also may only be able to not care about it because that guarantee is already provided without them knowing |
18:52 | <ljharb> | it's a really strange argument to me that because people don't yet care about robustness, the language shouldn't make it maximally easy and performant to be robust. |
18:52 | <bakkot> | it would be odd for javascript to accept defeat as a safe sandbox language in the face of supply chain attacks when it’s the closest language to winning and the most important field to win. .call " is not "accepting defeat as a safe sandbox language" |
18:53 | <bakkot> | it's a really strange argument to me that because people don't yet care about robustness, the language shouldn't make it maximally easy and performant to be robust. array.push , nor should it |
18:53 | <Kris Kowal> | you can’t use .call. You have to use uncurryThis, which frustrates optimization. |
18:54 | <bakkot> | "engines haven't optimized userland uncurryThis" is also not "accepting defeat as a safe sandbox language" |
18:55 | <Kris Kowal> | no feature that we ever add to the language is going to cause people to write anything other than |
18:55 | <Kris Kowal> | engines optimizing uncurryThis would also be an acceptable outcome. |
18:55 | <bakkot> | true. but the program also may only be able to not care about it because that guarantee is already provided without them knowing array.push() working in their own program, so the fact that the dependency wants to be robust against people mutating Array.prototype is completely irrelevant to their program |
18:56 | <bakkot> | so, no. they are able to not care because it does not in fact matter in practice in almost any program. |
18:56 | <bakkot> | engines optimizing uncurryThis would also be an acceptable outcome. uncurryThis and similar would be fine by me |
18:56 | <bakkot> | just not syntax |
18:56 | <bakkot> | (wasn't there one, actually?) |
18:58 | <bakkot> | ah https://github.com/js-choi/proposal-function-demethodize |
18:59 | <ljharb> | not all programs mutate arrays. |
19:00 | <bakkot> | very nearly all programs are written in a style which assumes builtins are intact. |
19:01 | <bakkot> | as well they should. |
19:01 | <bakkot> | no feature we ever add to the language is going to cause people to write in a way which does not assume that, nor should it. |
19:03 | <Kris Kowal> | i see no argument that suggests anyone here holds the contrary position |
19:03 | <bakkot> | the specific claim I am defending is
|
19:04 | <Kris Kowal> | but i for one propose that under some conditions it is both valuable and possible to not only assume they’re in tact, but to make it possible to rely on their being in tact. |
19:06 | <Kris Kowal> | i agree that very few existing programs rely on the immutability of shared primordials, but that’s circular. they are rare because of the economics of security, which we are in a position to adjust. |
19:07 | <bakkot> | I am ok with exploring adjustments which don't require people to completely change the style in which they write their programs, for sure |
19:07 | <bakkot> | however, that does not include the call-this proposal |
19:08 | <Kris Kowal> | and on that, i think you and i at least agree that a non-syntactic solution is acceptable |
19:10 | <Kris Kowal> | i merely disagree that the winning argument is based on the unimportance of defending language integrity in mutitenant (read: effectively all) programs |
19:11 | <Kris Kowal> | the winning argument is that it’s possible to achieve that goal without syntax that a minority of programs will need to use before making intrinsics immutable |
19:13 | <Kris Kowal> | and in some flavors, systems like airgap would prefer to accept the ergonomic cost of using a call-bind pattern pervasively instead of making intrinsics immutable. |
19:13 | <bakkot> | if that's the path forward you'd also need to ensure making intrinsics immutable doesn't break everything, which is... demonstrably tricky |
19:14 | <Kris Kowal> | for sure |
19:15 | <Kris Kowal> | not as bad as you’d think for specific applications, but override mistake is certainly a recurring theme in herding the ecosystem into the safe subset. |
19:15 | <bakkot> | at the very least it entails replacing everything with accessors, doesn't it? |
19:15 | <bakkot> | which is... oof |
20:05 | <shu> | i agree that very few existing programs rely on the immutability of shared primordials, but that’s circular. they are rare because of the economics of security, which we are in a position to adjust. |
20:27 | <Kris Kowal> | Notably, nothing based on classes suffers from the override mistake. So, replacing a lot of intrinsic value properties with accessors does make a lot of the problem go away. It’s far from ideal. |
20:27 | <bakkot> | well, doesn't suffer from the override mistake as long as you declare all your fields, anyway |
20:27 | <Kris Kowal> | aye. |
20:37 | <Kris Kowal> | I hacked a computer once. I locked my dad out of a 486 by putting an infinite loop in AUTOEXEC.BAT. And echoing out some ANSI that remapped Y and N to *. And also making the foreground color black. |
21:42 | <Mathieu Hofman> | at the very least it entails replacing everything with accessors, doesn't it? |
21:51 | <bakkot> | right, yes, fixing the override mistake is also an option |
22:30 | <voidhedron> | What exactly is "the override mistake"? Trying to search it on google even adding "javascript" as keyword only yields irrelevant results |
22:32 | <ljharb> | voidhedron: 'use strict'; var o = ({ __proto__: Object.freeze({ foo: false }) }); o.foo = true; it throws, instead of defining an own property on o |
22:32 | <Kris Kowal> | There’s a mention here https://exploringjs.com/deep-js/ch_property-assignment-vs-definition.html |
22:41 | <bakkot> | https://github.com/tc39/how-we-work/blob/c96099d8ab460b933bd80d65b8b4c6a05ee0c791/terminology.md#override-mistake |
22:53 | <voidhedron> | voidhedron: |
22:56 | <voidhedron> | that's an understatement actually, looking back on my code now |
22:58 | <voidhedron> | I actually enjoy using nodejs with their --frozen-intrinsics flag for personal projects, so a lot of my code is written to handle that but I've just never recognized it as a well known pattern (mainly because it's caused by an experimental flag which I assume very few use) |
22:58 | <ljharb> | it also breaks a surprising number of packages, due to the override mistake (often transitive deps, not because lots of code breaks from it) |
23:01 | <voidhedron> | Yeah I'm aware, it may or not be related to the fact that I am also very packagephobic, at least at runtime, devDependencies all good, I pull in tsc and stuff whatever, but runtime deps I avoid as much as possible and always thoroughly review any I pull in, and when I do I only use zero or low dependency ones so I can avoid issues related to that and other things :P |
23:02 | <voidhedron> | I also often just copy the specific parts of a package I actually want directly into my code so I can adapt it into my hardened-JS-style I prefer |
23:03 | <voidhedron> | I actually have a helper function I created that I guess solves the "override mistake" although I didn't realize it was known as that when I did it |
23:09 | <voidhedron> | it's not that complex:
it works for anything as long as |
23:10 | <voidhedron> | has TC39 ever considered just adding a function like this to solve the "mistake"? |
23:10 | <voidhedron> | like Reflect.setOwnKey |
23:11 | <shu> | opt-in fixes won't fix the mistake; the mistake is that it proliferates in shipped code that's not updated |
23:11 | <shu> | you can already opt-in to use define instead of set semantics to work around |
23:12 | <voidhedron> | ah I see, fair enough |
23:13 | <bakkot> | and then you don't have to change the prototype of your thing |
23:13 | <bakkot> | which you generally want to avoid for optimization reasons |