When running Sencha Cmd v6.5.3.6, i get the following error message:
[ERR] C2001: Closure Compiler Error (This code cannot be converted from ES6. extending native class: Array) -- compression-input:111263
The error is caused by this code:
class Chains extends Array {
}
The error still occurs with methods inside class declaration.
Is there a way to make this code compiled by Sencha Cmd ?
UPDATED :
To solve the problem, I change the code to:
function Chains() { };
Chains.prototype = new Array;
Chains.prototype.anyMethod = function () { }
You are using a feature of ES6 that cannot be transpiled into pre-ES6 code.
Sencha Cmd by default transpiles your code into pre-ES6 code because IE11 support has not yet been dropped.
You can disable code transpilation starting with Sencha Cmd 6.5.0 as described in the official docs:
There are cases where you won't need all that transpiling. Maybe you’re targeting Electron or you only support modern browsers that have all these features. You can disable the transpiler and still use the Sencha Cmd code compressor against your native ES6 code. Just a tweak to the app.json file and say goodbye to the transpiler and its polyfills:
"output": {
"js": {
"version": "ES6"
}
}
I don't think ExtJS supports that syntax as of now. For the time being, you might have to go with their syntax:
Ext.define('Chains', {
extend: 'Array'
});
Then in your code you can call it like this:
var chns = Ext.create('Chains');
chns.push('a');
console.log(chns);
Related
I am writing in Javascript using classes. Example:
'use strict';
class MyClassName
{
myGame;
constructor(game)
{
this.myGame = game;
}
startGame()
{
this.startActions();
}
startActions()
{
//
}
}
When i try to compress it in PhpStorm by using Assets Compressor, i get error:
[ERROR] 3:6:identifier is a reserved word
How i can make correct compressing my code in PhpStorm? Are there any ways to compress JS code that uses classes?
Assets Compressor plugin only supports ECMAScript 2015, it will throw errors on new syntax.
Please try following the instructions from https://www.jetbrains.com/help/idea/minifying-javascript.html: install either UglifyJS or the Closure Compiler and set it up as a file watcher to run from the IDE
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.
I observe that In angular 2 there is no finally block for promise API
angular 1 :
loadUsers() {
fetch('/api/users').then((response) => {
return response.json();
}).then((data) => {
this.users = data;
}).catch((ex) => {
console.error('Error fetching users', ex);
}).finally(() => {
this.userLoaded = true;
};
Assuming I have to do same thing in angular 2
How to add finally block in angular 2 promise , as of now there are only then & catch blocks available in angular 2. If not finally then is there any way to add cleanup code after execution of each method , where do i write code to do finally block activities ?
The easiest way to do this is to use the promise.finally shim.
Add it with npm install --save promise.prototype.finally
Add the typings: npm install --save-dev #types/promise.prototype.finally
In your main class, before bootstrapping the application, add the following code:
import { shim } from 'promise.prototype.finally';
shim();
You should now be able to use finally on your promises.
This is usually done using Promise.always. This takes one function, and adds a new .then on the promise that gives the same function for both success and fail states. If the function is not available in the given promise-based environment, it's pretty easy to polyfill in.
Promise.always = function(p, fn) {
return p.then(fn, fn);
}
usage:
var prom = fetch('/api/users').then...
Promise.always(prom, () => {
this.userLoaded = true;
});
return prom;
Modern solution in 2019-2020
First of all, you should avoid manually adding polyfills without a good reason for it, don't do it blindly because you've read it somewhere.
The problem you encounter has two sides: typing declarations and the implementation.
In order to use Promise.finally in your code without typing errors you should add es2018.promise to the lib option in your tsconfig.json file.
For modern projects you should use the following configuration (which is default in Angular 8):
{
"compilerOptions": {
…
"lib": [
"es2018",
"dom"
]
}
}
This will fix the typing errors you have in the editor.
Also, according to the docs and my observations the correct polyfill for Promise.finally will be added by the Angular compiler automatically, you don't have to install or add anything.
But, in general, you could add a polyfill (only if it is proven to be required) in ./src/polyfills.ts file using core-js library. Always try to use core-js instead of other libraries, cause it's an industry standard and it's used by Angular internally.
For example, Promise.finally polyfill could be added like this:
import 'core-js/features/promise/finally';
See more at core-js documentation.
Also, make sure to read browser-support and differential-loading articles of Angular documentation.
I'm having trouble getting an npm module to work since it was changed to ES2015.
I have an ES2015 app that is bundled by browserify and transformed with babelify. I am trying to upgrade an npm module named credit-card for credit card validation, which was changed from ES5 to ES6 in the current version. The problem starts with IE11/Edge. The code works fine on Chrome. Here's how the module is imported in the transformed app (babel'd code):
var _this = this;
var _creditCard = require('credit-card');
var _creditCard2 = _interopRequireDefault(_creditCard);
Here's a piece of code calling it:
this.validateCreditCard = function () {
var ccNumber = _this.account_number_credit_card.value.replace(/\D/, '');
_this.creditCardValidation = {
accountHolder: _this.account_holder_credit_card.value.replace(/\W/g, '').length >= 2,
cvc: _this.account_cvc_credit_card.value.replace(/\D/g, '').length > 2,
accountNumber: _creditCard2.default.isValidCardNumber(ccNumber, _creditCard2.default.determineCardType(ccNumber, { allowPartial: true }))
};
return _underscore2.default.all(_underscore2.default.values(_this.creditCardValida tion));
};
Now on Chrome this works without a problem. On IE however, the exported functions of the credit card module are missing.
Here's a printscreen of a console log of the module in IE
And here's Chrome
It looks like defaults is completely missing in IE. Is this a known issue? Do any of you have encountered this problem before and can give me some hints? Any pointers on how I could investigate this issue to understand what is going wrong and how I could fix it?
Stepping through the require() in IE11 Debugger i found out that there was a problem with Object.assign being undefined in IE11. After some searching I found this thread. The answer in this thread worked out in the end. I needed to add polyfill to my browserify bundle and enable the "transform-es2015-classes" plugin with the opt loose: true (See this thread for code).
I am studying typescript and I'm trying to create a simple let and it won't work because it says I need to use ECMA6 or higher. This is is the error message I'm getting in the typescript compiler:
Error:(11, 5) TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
And this is the code:
class website{
url:string;
facebookLikes:number;
}
let google = new website();
google.url = "google.com";
google.facebookLikes = 23124;
I searched online and I found an answer that says to go to settings and langauges and frameworks and go to javascript and change it to EcmaScript6. I done this but I still get the same error.
If anyone can shed some light on this I would really appreciate it. Thanks.
You need to use the ES6 target just as the error suggests.
I don't know how you compile your typescript files, if it's using the builtin compiler or a file watcher, but in any case the compiler options have the target property which should be ES6 if you want to use let (and other es6 features).
If for example you are using tsconfig.json then it should look like this:
{
"compilerOptions": {
"target": "ES6",
...
}
}