Some days ago I've asked a question related to the error when I've tried to use babel.js in my application https://community.apigee.com/questions/10387/usag...
I got an answer and understood differences between 'a127' and 'trireme' environments. According to the Apigee documentation modules dependent on ES6 code are not supported.
But I still hope to find possibility to use the most useful features of ES6 (at least some of them) to make my developers life easier :)
Apigee references to the NodeJS 0.10.32 version. I've used NodeJS 0.12.4 before and was able to add 'babel.js' which have made all 'dirty' job for me. Arrow functions, classes, string interpolation... everything which all developers like. Didn't face any issues.
But the same approach doesn't work on Apigee at least because of this bug in Rhino sources https://github.com/mozilla/rhino/pull/236#issueco... I'm not sure that it is only one blocker.
So I have some questions related to the possibility to use ES6 features (emulate them). Will be gratefull for any advices.
Answer by dmitry_zhivushko1 · Sep 28, 2015 at 01:48 PM
I have forced application startup with babel using ugly hack in 'toString'. It was interesting to check if it is a single blocker or not.
after it I found that I can use an arrow functions. But creation of the class failed (strange exception with stacktrace from mozilla.rhino...). Also because of changes made by babel, it is difficult to find errors. The line numbers in stacktrace are not the same as in original source. as there are no possibility to debug code line by line (line in dev tools in browser apps) it became an additional problem.
So, it looks like unrealizable dream to use ES6 in Apigee right now. Will hope that trireme will support it in future
Sorry that it didn't work out in the short run. We have a lot of work in order to make ES6 work in Rhino but stuff is happening.
If you want to try out more with Babel, and get more advice on Rhino, then also feel free to check out Rhino on GitHub and post to the Rhino mailing list -- there are a bunch of active people there.
Answer by Greg Brail · Sep 25, 2015 at 05:11 PM
Thanks for following up on this.
We will certainly be upgrading Trireme and the Rhino engine regularly in the Apigee cloud. However, it's likely to stay the same until after the new year because we're starting to lock things down for the holiday shopping rush.
I have not personally tried any transpiler technology with Edge or Trireme. However there's no reason why that would not do the trick. If you have specifics we can certainly try to help here on on the Trireme GitHub site and mailing list.
Finally, if the "toString" thing is really the main blocker, then you can always monkey-patch it yourself by inserting some code like this:
var oldToString = String.prototype.toString;
String.prototype.toString = function() {
if (this === null) return '[Object null]';
return oldToString.call(this);
};
Hello Greg,
Thank you for detailed explanation.
What about overriding of the String.prototype.toString I have already tried something similar. But my attempt was not successful. I don't have 'proof link' right now but problem was described in one of JS specifications. It was something like " if 'this' is null in such places then it will be automatically replaced with global object ". It was a cause why I was not able to get 'this === null' eq. TRUE in such cases.
After weekends I will come back to it again and will try the code example you provided 'as is' (can't do it right now).
Answer by dmitry_zhivushko1 · Sep 28, 2015 at 09:34 AM
I've tried proposed solution. Doesn't work.
And it is clear why it doesn't work. According to the documentation (https://developer.mozilla.org/en-US/docs/Web/JavaS...) "if the method is a function in non-strict mode code, null
and undefined
will be replaced with the global object"
And following test can confirm it
Object.logger.info('null before override:',Object.prototype.toString.call(null)); //Override to string var oldToString = Object.prototype.toString; Object.prototype.toString = function () { if (this === null){ return '[Object Null]'; } return oldToString.call(this); }; Object.logger.info('null after override:',Object.prototype.toString.call(null));
If I run this code on NodeJS (a127 project start) then it works according to the documentation. In 'strict mode' I can override 'toString' method because function accepts 'null'. If I don't use 'strict mode' then 'null' became a global object and this code became not correct
But if I run this code using 'trireme' then in both cases (strict mode or not) null replaced with global object. So I can't catch the situation when 'this === null' because it doesn't happen for the 'null' argument.
So it is a cause why 'babel.js' fails on startup. It depends on regexpu\node_modules\recast\node_modules\ast-types\lib\types.js and this library uses Object.prototype.toString for some specific cases and expects that 'call' with 'null' argument will work according to the documentation.
Unfortunately I don't have any other ideas about possible workarounds but still hope to get any advises from guys who knows 'trireme' and its specifics.
One solution that we found was disabling browser polyfills in Babel. We can still use arrow functions, imports and probably other functionalities. We are using Webpack as well.
We set useBuiltIns to false in babel: https://babeljs.io/docs/en/babel-preset-env#usebuiltins-false
Example of .babelrc file:
{ "presets": [ [ "@babel/preset-env", { "modules": false, "useBuiltIns": false, "corejs": 3 } ] ], "plugins": [ "@babel/plugin-syntax-dynamic-import", "babel-plugin-transform-async-to-promises" ] }