Bug
[email protected] doesn't work in IE11 with polyfills. Please note that version 3.x.x works with IE11. The root cause seems to be some interaction with polyfills and: Symbol, Symbol.iterator, Arrays, Object.defineProperty, and prototypes.
The error surfaces in machine.initialState property not containing the array of actions from the state configs onEntry (and presumably onExit) action arrays, and instead containing an empty array.
I created a static HTML file that demonstrates the issue. A strange thing to note is that when the same file is reloaded and executed several times, the error varies.
The error message varies. I have seen a variety of error messages with a complex hierarchichal state machine (rather than the simplified case in my repro below). Here are some that I have seen where the same page is reloaded and executed, but reports different errors:
Invalid descriptor for property __kind__Unable to get property @@CLOSE of undefined or null reference (where CLOSE is an event name).Unable to get @@actions of undefined or null referenceArrays are created correctly in IE11.
Arrays are not created correctly in IE11.
Since polyfilled features are not guaranteed to work the same way as native code, I think that the change in version 4 to use many more ES6 features makes IE11 break, even when those features are polyfilled.
Instructions:
Since codepen doesn't work in IE11, you can go to the pen in a different browser and save the HTML content as a static file and load that into your IE11 browser.
machine.initialState.I would gladly accept a PR for this - I don't have the environment to test this in IE11 but if you can figure out exactly what doesn't work in IE11, that'd be very helpful.
This bug was really hard to diagnose. Unfortunately, I have not yet figured out the particular bad interaction causing this bug, even after quite a few hours of debugging. If I do manage to figure it out, I will be sure to update this issue.
Just took a brief look at this in an IE11 Dev Image in VirtualBox VM.
I suspect the first error may be related to the spread on this Set:
https://github.com/davidkpiano/xstate/blob/master/src/StateTree.ts#L174
and an incompatibility between the resulting compiled code:
Object.defineProperty(t.prototype,"nextEvents",{get:function(){var t=this,e=this.stateNode.ownEvents,n=b(f(this.nodes).map(function(e){return t.nodes[e].nextEvents}));return s(new Set(n.concat(e)))},enumerable:!0,configurable:!0})
and the custom Object.defineProperty() polyfill added (as part of the Symbol polyfill) via that polyfill.io service.
(Other uses of the Object.defineProperty() and Set polyfills throughout seem to be working fine.)
I'll dig into this further when I have little more time.
Amazing. If I have a breakpoint in just the right spot it works perfectly.
Capturing some notes for when I have time to take a look at this again:
After simplifying the scripts portion of the example down to the following:
<script src="https://polyfill.io/v3/polyfill.js?features=es5,Array.from,Object.assign,Object.create,Object.getOwnPropertyDescriptor"></script>
<script src="https://unpkg.com/xstate@4/dist/xstate.js"></script>
<script src="https://unpkg.com/xstate@4/dist/xstate.interpreter.js"></script>
<script>
window.machine = XState.Machine({
key: 'testmachine',
initial: 'initializing',
states: {
ended: {},
initializing: {
on: {
start: 'started'
},
onEntry: ['create']
},
started: {
on: {
end: 'ended'
}
}
}
});
</script>
(and executing machine.initialState in the Console as above).
The first error I encounter is:
Invalid descriptor for property `_values`.
Set is instantiated in the StateNode::ownEvents or StateTree::nextEvents getters (even if I neuter the implementations of both to simply create an empty Set and return an unrelated empty Array).Symbol polyfill instead of this branch.new Set(), it enters the correct branch and successfully returns the machine's initialState.This appears to be a bug in the interaction between the Set and Symbol polyfills under IE11, rather than an XState bug, per se.
It also could well be influenced by the other bundled polyfills - worth checking if polyfill.io returns them in a consistent order. If not, that could explain the odd and varying behavior described in the initial report.
The Invalid descriptor for property `_values`. error Heisenbug I encountered above appears to be related to the IE11 developer tools, rather than the web app itself. When you type machine.initialState, the error occurs while the IE developer tools REPL traverses the resulting object in an attempt to render an interactive inspectable result row in the IE11 Console.
If I execute JSON.stringify(machine.initialState) (rather than machine.initialState) in the IE11 Console instead, that error disappears.
Just tried the following, and it appears to address the original complaint for the supplied example - the "actions" array is populated.
<script src="https://polyfill.io/v3/polyfill.js?features=es5,Array.from,Array.isArray,Array.prototype.@@iterator,Array.prototype.find,Array.prototype.includes,matchMedia,Intl,Object.assign,Object.create,Object.values,Object.entries,Number.isNaN,Map,Set,Symbol,Symbol.iterator"></script>
<script src="https://unpkg.com/xstate@4/dist/xstate.js"></script>
<script src="https://unpkg.com/xstate@4/dist/xstate.interpreter.js"></script>
<script>
window.machine = XState.Machine({
key: 'testmachine',
initial: 'initializing',
states: {
ended: {},
initializing: {
on: {
start: 'started'
},
onEntry: ['create']
},
started: {
on: {
end: 'ended'
}
}
}
});
var element = document.createElement('pre');
element.textContent = JSON.stringify(machine.initialState, null, 2);
document.body.appendChild(element);
</script>
Before (using the polyfills from the supplied CodePen):
{
"actions": [],
"activities": {},
"meta": {},
"events": [],
"value": "initializing",
"event": {
"type": "xstate.init"
}
}
After (with the updated polyfills referenced above):
{
"actions": [
{
"type": "create"
}
],
"activities": {},
"meta": {},
"events": [],
"value": "initializing",
"event": {
"type": "xstate.init"
}
}
I tried to derive the polyfill selection from the selection listed in the comments from the original CodePen, but:
html5shiv does not appear to be a valid option currently; and Object.create appeared to be important.Hope that helps!
Great analysis! I'll see if I can avoid using Set, but other than that, not much I can do with regard to IE11 behavior.
I've dug into this a little bit too and it really seems like a problem with polyfill.io service (at least with the version posted by @Zenwolf ), because I've run the example machine right now with their recent polyfills and it works OK (at least when it comes to reading the .initialState.
In the version posted here originally there was a broken "setDescriptor" implementation:
setDescriptor = function (o, key, descriptor) {
var protoDescriptor = gOPD(ObjectProto, key);
delete ObjectProto[key];
defineProperty(o, key, descriptor);
if (o !== ObjectProto) {
defineProperty(ObjectProto, key, protoDescriptor);
}
};
It has crashed because protoDescriptor was undefined for one of the cases and that couldn't be set on ObjectProto, when I've fixed the condition to if (o !== ObjectProto && protoDescriptor) the issue went away.
To sum it up - this really shouldn't be reported here and I believe the issue can be closed as XState can be successfully ran in IE11, it just needs proper polyfills.
Most helpful comment
I've dug into this a little bit too and it really seems like a problem with polyfill.io service (at least with the version posted by @Zenwolf ), because I've run the example machine right now with their recent polyfills and it works OK (at least when it comes to reading the
.initialState.In the version posted here originally there was a broken "setDescriptor" implementation:
It has crashed because
protoDescriptorwas undefined for one of the cases and that couldn't be set on ObjectProto, when I've fixed the condition toif (o !== ObjectProto && protoDescriptor)the issue went away.To sum it up - this really shouldn't be reported here and I believe the issue can be closed as XState can be successfully ran in IE11, it just needs proper polyfills.