New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Haxe 4 js.Bool.__interfLoop breaking change for Interface casting when using advanced JavaScript minification #9172
Comments
Is it possible to change this: // JavaScript riddle:
// Not minified:
var obj = {};
obj.key = "value";
if ( obj.hasOwnProperty( "key" ) ) {
var value = obj.key;
}
// Minified:
var o = {};
o.k = "value";
if ( o.hasOwnProperty( "key" ) ) { // <-- how to change that "key" to "k" based on the minified code?
var v = o.k;
} |
Does closure compiler have any options to not minify specific field names? |
Absolutely. Uglify JS as well. But with a very big code base that's not an option. :) |
I'm surprised they don't handle |
Closure compiler? We would need something like if ( o.hasOwnProperty( getPropertyNameFromJavaScriptCode( o.k ) ) ) {
} |
what if we do |
That wouldn't help since it would be undefined. |
We would need to do that for every access point everywhere. Actually that might apply to the "__ class __" and other keys as well? |
I guess that depends on whether we do the check by the string like in the |
How about we change the check to I wonder why the code is using |
See #7834 for the original issue. |
Ok, seems to be an ES6 thing. Yay. How about we leverage the type information we have? It would seem to produce the correct result: interface I1 {}
interface I2 {}
interface O1 {}
class Base1 implements I1 implements I2 {
public function new() {}
}
class Base2 extends Base1 {}
class Base3 extends Base2 {}
class Main {
static public function main() {
untyped {
js.Boot.__interfLoop = function __interfLoop(cc:Dynamic, cl:Dynamic) {
if (cc != null && cl != null)
trace(Type.getClassName(cc), Type.getClassName(cl));
if (cc == null)
return false;
if (cc == cl)
return true;
var intf:Dynamic = cc.__interfaces__;
if (intf #if (js_es == 6) && (cc.__super__ == null || cc.__super__.__interfaces__ != intf) #end) {
for (i in 0...intf.length) {
var i:Dynamic = intf[i];
if (i == cl || __interfLoop(i, cl))
return true;
}
}
return __interfLoop(cc.__super__, cl);
}
}
var base3 = new Base3();
trace(Std.is(base3, O1));
var cc:Dynamic = Base3;
haxe.Timer.measure(function () {
var x = false;
for (i in 0...10000000)
x = js.lib.Object.prototype.hasOwnProperty.call(cc, "__interfaces__");
if (Math.random() > 42) trace(x);
});// Main.hx:38: 0.12400007247924805s on node v10.15.3
haxe.Timer.measure(function () {
var x = false;
for (i in 0...10000000) {
var intf:Dynamic = cc.__interfaces__;
x = intf && (cc.__super__ == null || cc.__super__.__interfaces__ != intf);
}
if (Math.random() > 42) trace(x);
});// Main.hx:45: 0.015000104904174805s on node v10.15.3
}
} FWIW it also seems to be faster than native reflection. |
I'll have to look into this again, I don't see right now why it's an ES6 thing, but I like the idea of not using |
It's an ES6 thing, because without it, there's no prototype chain between class objects, as we have nothing in the output that would establish it. I'd say it's a design flaw in ES6 classes, but oh well. In any case, you can best observe the difference here: class A { static public var foo = 123; }
class B extends A {}
class Main {
static public function main() {
trace(js.lib.Object.getPrototypeOf(B) == A);// true with -D js_es=6, false otherwise
trace(untyped B.foo);// 123 with -D js_es=6, undefined otherwise
}
} Note that without the |
I came across an issue while using the closure compiler
--compilation_level ADVANCED_OPTIMIZATIONS
but I would expect other minification utilities like uglifyjs to break as well.Casting to classes works fine, but casting to interfaces doesn't work anymore. I tracked the breaking change down to this commit: 3e46bfa#diff-b82d472d6b1e1b69e1560649a3bf52d7
I recently switched to from Haxe 3.4.7 to 4.0.5 and found our minified production JavaScript throws an
Cannot cast IMPLEMENTATION to INTERFACE
error.Here is a Haxe code example:
Which compiles to nicely to JavaScript and works just fine ( I only paste the necessary part ):
But if we let closure compiler minify the JavaScript, there is never a property called " __ interfaces __ ":
var intf = cc.__interfaces__;
becomesvar d = a.m
.I'm not a 100% sure what to do next - I just wanted to open an issue.
My very first fix is to avoid save casting to Interfaces, but since it worked with 3.4.7 I think it might be a good idea so ensure advanced minification support?
The text was updated successfully, but these errors were encountered: