At work we have (sigh!) to support IE 11 for the current project I'm working on. The project uses RxJS 6.
To support most of the features we've included, we used Webpack with Babel and core-js (as suggested by Babel itself) as polyfiller.
If we try to import RxJS, our application loading get stuck on a specific line:
Observable.prototype[_symbol_observable__WEBPACK_IMPORTED_MODULE_2__["observable"]] = function () {
return this;
};
with the error SCRIPT5005: String Expected
.
We are using the es5 transpiled version of RxJS. So the code original typescript code should be this one.
I know symbols are not supported in IE 11, as per Kangax's Ecmascript compatibility table and that core-js
includes a polyfill for Symbols, and we are importing all the polyfills.
In fact, if I try to run this with the polyfill after the error through the console, it works perfectly.
var obj = {};
Object.defineProperty(obj, Symbol.for("test"), {
value: 5
});
What's weird is that if I try to set a breakpoint on the line that give us the error, I can access singularly to these components without problems.
Observable.prototype
_symbol_observable__WEBPACK_IMPORTED_MODULE_2__
_symbol_observable__WEBPACK_IMPORTED_MODULE_2__["observable"]
The second and the third lines returns me an object.
If I do manually Observable.prototype[_symbol_observable__WEBPACK_IMPORTED_MODULE_2__["observable"]]
it still returns me the error.
Accessing to Object.prototype
through an Object is not allowed (as using an object as index makes the container object automatically call .toString()
on the key). Therefore IE returns me that error. Or, at least, I think that might be the reason.
What's more weird is that Symbol.for("test")
returns an object that is the same as _symbol_observable__WEBPACK_IMPORTED_MODULE_2__["observable"]
(with description: test
instead of observable
). And if I do obj[Symbol.for("test")]
it works perfectly.
Also, it seems like I'm unable to create variables or such while I'm stopped on a breakpoint in IE 11 console, so I cannot even export that symbol to test that later (it allows me to do var x = {};
or var x = 5
, but if I call 'x', it throws me 'x' is undefined
).
Any clues about this problem and how we might solve this? Might this be a problem of the polyfill?
I'm attaching here below my webpack config and my .babelrc
module.exports = {
module: {
rules: [
{
test: /\.jsx?$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-flow'],
},
},
exclude: /node_modules\/(core-js|(react.+)|(rxjs.+))/,
},
...
]
}
}
{
"presets": [
"@babel/preset-react",
"@babel/preset-flow",
["@babel/preset-env", {
"targets": {
"browsers": [
"last 2 versions",
"safari >= 7",
"Explorer 11"
]
},
"useBuiltIns": true
}]
],
"plugins": [
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-transform-runtime"
],
"env": {
"test": {
"presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-flow"]
}
}
}
Thank you.
TL;DR
Since we have a monorepo with multiple projects (a "sample app" that loads another project on its inside), I was including the core-js polyfill both on the sample app and in that project. They were somehow conflicting, I'm still not sure why and how. This wasn't concerning rxjs but affecting it.
Also, I wrote a wrong regex on the webpack.config.js
on babel-loader, but I'm not sure this was really affecting all.
It was: /node_modules\/(core-js|(react.+)|(rxjs.+))/
It should have been: /node_modules\/(core-js|rxjs|react[^\s+]*)/
Since I had to target the packages, not the files as I was thinking. I added a more complex regex on react to match also react-dom or other react-things (if any).
I was able to create a sample application that could work without problems. I discovered RxJS has somehow its own polyfill for symbols.
In fact, running that sample with React, webpack, babel, rxjs but not core-js, wasn't giving any problem. (Note: the sample has core-js installed).
Setting a breaking point on
Observable.prototype[_symbol_observable__WEBPACK_IMPORTED_MODULE_2__["observable"]]
, reveals this:
While using core-js, it reveals this:
Although this difference, both with and without the sample, it works perfectly on that sample. So I thought how it was possible and thought that I read somewhere that the polyfill should have been loaded only once in the most global object.
Since we are developing a project in a mono-repo that has React-based Website and another complex React component that gets imported on runtime, and that website seemed to need also polyfills, I added core-js
import on both the projects.
By removing the one on the website, the error changed (it got stuck on another point not concerning this one).
Moreover, as said in the TL;DR, I think there was a problem with the regex applied on babel-loader
.