IE11 "Unable to get property 'bind' of undefined or null reference - main.js (5,9402)" when using Promise ponyfill
See original GitHub issueSetup:
- Webpack + Babel.
- I can’t touch the global scope, so I can’t polyfill.
- I’m using Webpack Provide Plugin + native-promise-only-ponyfill for Promise support.
My code:
import { h, render, Component } from 'preact';
When I clicked the error, I found this in the Preact build:
e.prototype.then.bind(e.resolve())
It appears as though “e” is the minified name for “Promise”, and that the error is coming from around there in the code.
Is Preact intentionally touching the prototype of Promise? Would there be a reason for this? Or is this an artifact of a build tool?
Issue Analytics
- State:
- Created 4 years ago
- Comments:13 (7 by maintainers)
Top Results From Across the Web
Angular2 IE11 Unable to get property 'apply' of undefined or ...
Angular has dependency on core-js. Thereby you can use Object.assign polyfills from it:
Read more >How To Get Property 'Bind' Of Undefined. Babel 7 + Core-Js + Ie11
Ask questionsIE11 Unable to get property 'bind' of undefined or null reference main.js 59402 when using Promise ponyfill. Setup: Webpack + Babel.
Read more >IE11 Unable to get property 'apply' of undefined or null reference
We had exactly the same error and today everything started to work fine again. I'm looking for some information about updates or error...
Read more >IE11 Dialog Promise Undefined - The Aurelia Discourse
I'm in the process of updating an existing app using (Aurelia Framework 1.1.4) to the latest version of Aurelia.
Read more >Fix Cannot Set Property of Null Error in JavaScript - YouTube
Check us out at https://www.skillforge.com The "cannot set property of null " error is a very common JavaScript issue that you may come ......
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@jacobbogers @just-boris That’s a great suggestion and it is indeed a few bytes shorter than what we have now 👍 But we have to think about the big picture here. This piece of code is somewhat in the “hot path” as it’s called very frequently during the life of a Preact application. It’s not as hot as
createElement/h
, but still it will be called quite a lot. Because of that any changes will affect benchmarks here.An additional allocation here will affect benchmarks negatively like this one: https://github.com/krausest/js-framework-benchmark . One can of course rightfully argue about how meaningful those numbers are, but many developers still make decisions based on those numbers. The
.bind
approach seems to armortize that cost for us and the few benchmarks we have in our repo seem to back that up. There thebind()
approach is slightly faster on my machine. So we trade a few bytes for runtime performance here.Optimizations change frequently in browsers, so this may not be this way for forever. Just to be sure I posted the same question on Twitter to some v8 engineers.
In Preact we use that trick to process our global queue in “ticks”. The queue holds components that need to be rendered or otherwise updated. There are 3 ways components are pushed into the queue:
component.setState()
component.forceUpdate()
render(<App/>, container)
Note that even our
hooks
implementation makes use of classes internally and will call the samesetState
orforceUpdate
function on the backing class of a component.Once the queue has some items in it, we need to start processing it. But we don’t want to do that immediately as the current diff should finish first, so that all dirty components of the same “commit” are processed at the same time. So we need to somehow schedule the invocation of when we should start processing it.
An easy way to do that in all browsers is via
setTimeout
. It fullfills our requirement to defer processing the queue until the current synchronous diff is completed.Now on more modern browser we do have more options on how we can schedule work. One of those is via so called microtasks. It’s quicker and in our benchmarking tests more performant compared to
setTimeout
on modern browsers. To do that we have to leverage thePromise
object. In a similar fashion tosetTimeout
we need to have a function that works the same way, but usesPromises
under the hood.Calling just
Promise.prototype.then()
directly will throw as a Promise expects to act on a receiving Promise that is passed via thethis
argument. To check that one can fire up node and paste the following lines:As you can see above, calling
Promise.prototype.then
directly throws an error. Therefore we need to bind some Promise object to thethis
value of the.then
method. We can do that via the.bind()
operator, which brings us to the code that we use in Preact today:So in conclusion the main reason we use
Promises
instead ofsetTimeout
to process our queue is performance. Hope that answers your questions 👍