`if (pseudoRandom() < 0.57) houseWins()` gives the same payout as `if (trueRandom() < 0.57) houseWins()` for all intents and purposes; the only difference is the former is more predictable to people trying to game the machine.
792 karma · joined February 4, 2012
`if (pseudoRandom() < 0.57) houseWins()` gives the same payout as `if (trueRandom() < 0.57) houseWins()` for all intents and purposes; the only difference is the former is more predictable to people trying to game the machine.
Where they might have caused a bug, 90% of the time Flow will catch them, and insist that I do a null check and handle that case.
And when they do crop up, it's usually more of a serious failure that I'm happy to trigger an exception early, rather than having it propagate further down the stack by using something like nothing.js. Especially given the list of gotchas. The fact that `Nothing` is not falsy is really problematic.
I'm pretty convinced at this point that `a && a.b && a.b.c && a.b.c.d` is an anti-pattern in javascript anyway; if I'm that unsure about the structure of my data, I have more serious problems than just trying to avoid null pointers.
Most of the hacks were just to get IE up-to-par with the other browsers. For example, to send a postMessage between a popup and the parent page, the only way is to place a hidden iframe on the parent page, with the same domain as the popup. post-robot abstracts most of that away.
The line we had to walk in terms of security was, on top of not introducing any new vulnerabilities ourselves, making sure we didn't make it too easy for people to accidentally introduce any security loopholes using what we've built.
For example -- the idea of passing a function over to a different window is a fairly novel concept. The idea is, if you want to give the other window control over something, say to log out a user, you can just pass a `user.logout` function directly in a message to the target window. But then there's a risk people will absentmindedly pass functions in messages that they didn't expect to.
But then, on top of that, there's a lot we can do automatically to protect users, that doesn't happen automatically with regular browser apis. For example, if you render an xcomponent with a certain url, xcomponent will (by default) ensure that only messages from that domain are allowed up from the iframe. Which is something you'd need to remember to do manually if you were just listening for post-messages.
- Switching everything to .ts and .tsx files
- Switching a lot of tooling (TypeScript's built-in ES6 transpiler instead of Babel, tslint instead of eslint, etc.)
- At the time, TypeScript's types were nullable, Flow's were non-nullable, which makes a huge difference to me
- Given that TypeScript is a transpiler along with a static type-checker, it's not always easy to tell which features are going to have build-time vs run-time effects (e.g. private properties, property decorators)
That said, some of the errors from Flow can be incredibly confusing, and even with the latest versions I feel like there's improvement which needs to be made here. This (in my view) is the number one thing it needs to drive adoption.
Being able to just start writing code without spending forever setting up the perfect environment is hugely liberating. I'd encourage everyone to find good boilerplates for what they want to do (or put together their own if nothing else fits)
This is fine, unless you're:
1. Modifying the DOM and hoping to avoid jankiness 2. Trying to work with popup windows, in a browser which deprioritizes setTimeout in all but the focused window.
I ended up implementing https://github.com/krakenjs/zalgo-promise to get around this. It intentionally "releases Zalgo" by allowing promises to be resolved/then'd synchronously, but my belief is this doesn't have to cause bugs if it's used consistently.
What's with the secrecy? Not saying this is a non-issue, but the best way to present your issue as a non-issue is to be this vague about what you're complaining about.
For example, for one of my libraries I wanted a really simple way to allow people to include custom templates. I started with string-based templates, but quickly realized that this was inflexible for any kind of event binding or later dom mutations. Achieving that was super easy with jsx -- I just implemented a custom jsx function which directly outputs DOM elements.
Step 1: implement a jsxDom function [^1] which takes (name, props, children) (e.g. https://github.com/krakenjs/xcomponent/blob/master/.babelrc#...)
Step 2: point babel to my jsxDom function (e.g. https://github.com/krakenjs/xcomponent/blob/master/src/lib/d...)
This even allowed some cool hacks like including iframes directly in the jsx, to sandbox sections of the page (since the library is geared towards creating components to be embedded on 3rd party sites):
containerTemplate({ jsxDom }) {
return (
<iframe>
<style>
p {
margin-top: 40px;
}
</style>
<p>I can be sure the styles in this iframe won't affect the parent page</p>
</iframe>
)
}Even sped things up a little versus phantom.
Best way I can think to describe `this`:
-----
1. Either you decide in advance exactly what you want `this` to be:
- Use `.bind()` on your function and fix the value of `this`
- Create an arrow function and get `this` from the lexical scope
- Alias `let self = this` in your desired scope, and only ever reference `self`
- Create a wrapper function which fixes the value of `this` (essentially, implement `.bind()`)
-----
2. Or `this` will be decided by your caller:
- Your caller will `.bind()` your function with an unknown value of `this`
- Your caller will call `.call()` or `.apply()` with an unknown value of `this`
- Your caller will attach your function to an unknown object, then call `unknownObject.yourFunction()`, setting `this` to `unknownObject`
- Your caller will call your function as a standalone function: `let newFunc = someObj.someFunc` - then call it, setting `this` to `global` or `window`
- Your caller will pass your function as a param to something like `setTimeout` and achieve the same effect, setting `this` to `global` or `window`
-----
Obviously, most of the time if you're going to use `this`, #1 is to be preferred, #2 is to be avoided, so it's imperative to decide in advance what you want `this` to be rather than allowing it to be decided by your caller.
(Unless that's absolutely what you want, and you have a good reason why -- like if you're writing a wrapper function which is agnostic to the value of `this` that's passed)
- Making sure all promises are fulfilled or rejected, so window objects don't get caught indefinitely in closure scope for any .then() or .catch() handler functions.
- Using WeakMaps as much as possible, when we have things that are tied to a particular window, like message listeners or response handlers in post-robot
- Manually clearing up any global references to windows when we destroy an xcomponent instance
Finding the references was the tricky bit. A lot of the effort was finding a leaky test-case, running in 100 times in succession, and deleting code until the memory graph was flat -- then figuring out what I'd just deleted that caused the leak.
The problem started manifesting as I added more and more tests -- so now I'm actually checking my tests' memory usage on the fly and failing if they cross a threshold. Hopefully that should avoid getting into this kind of sticky situation ever again.
https://github.com/paypal/paypal-checkout/blob/master/test/t...
Chrome deals pretty well with garbage collection, so long as I'm careful to de-reference closed windows properly¹, and only uses a maximum of 150mbs. PhantomJS eats up almost 6GB of memory before it's done, which makes it almost unusable on machines with less memory or CI boxes. Travis is a no-go.
I'm hoping running Chrome in headless mode should give a nice speedup for our tests.
-----
¹ Turns out even a closed popup window or iframe keeps a huge amount of memory hanging around. Who knew.
The point I'm trying to make it, there's already a huge amount of churn around the vast amount build tooling needed to write any javascript these days. Part of making a framework with a low barrier to entry is having the build tooling stay out of your way until you're ready to deploy.
I get that's not necessarily Glimmer/Ember's philosophy, I just think it's a shame that using the framework from day 1 requires buying into all of the technology choices around ember-cli.
https://medium.com/@bluepnume/introducing-support-for-cross-...
I'd love it if it were a little more flexible to get started with though. Rather than fire up ember-cli, I'd love to just be able to:
1. Load glimmer.js from a CDN
2. Extend glimmer.Component
3. Render my component into an element
I know ember-cli solves this problem for a lot of users, but I'd love for the number of steps to get a "hello world" working to be as simple as the above. I think that's one of the reasons React has been so successful: it's stupid-simple to get started with, and it draws you in from there.
That said, it's way too hard to figure out how to buy into this thing without adopting the whole ember-cli ecosystem.
Ember-cli is a fantastic achievement, but for god's sake, give me a CDN link with a global `glimmer` object so I can at least play around with the thing in one of my projects, without buying into the entire ecosystem first!
I know that Ember is the "we'll take care of your whole app" framework, but with Glimmer maybe there's a chance here to cater to folks who love libraries like React, because they can get started with about 5 lines of code bunged into an html file and grow from there.
Let me start small, and make it easy for me to grow big.
https://github.com/krakenjs/grumbler
Pretty opinionated on the tooling it uses, but good if you just want to say "Fuck it, I want to fork some boilerplate, write some code, and build/distribute it", then worry about the finer details later, and swap in specific tooling that you need later.
But hey, thanks for the largely irrelevant, but hilarious xkcd!
https://github.com/krakenjs/grumbler
Pretty opinionated on the tooling it uses, but good if you just want to say "Fuck it, I want to clone some boilerplate, write some code, and build/distribute it", then worry about the finer details later.
git reset abc # unstage file `abc`
git reset xyz # switch to commit `xyz`
or: git checkout mybranch # switch to branch `mybranch`
git checkout myfile # remove any local changes to `myfile` since the last commit
---Maybe this would work great in a typed language where I might have `reset(File x)` and `reset(Commit x)` with different signatures... but for a CLI where everything is stringly-typed? Not so fun.
Also, god knows what happens here if there's a branch name with the same name as a file...