Closed NickIliev closed 5 years ago
@bguijt - I'm not sure they can change those back. The NativeScript iOS engine now supports accessing 64 bit numbers from the iOS side properly (which is a REALLY REALLY REALLY good thing :grinning:). I suspect all the ANY values where changed to the highest value now accepted.
However, I don't understand what a Obfuscator would be accessing the .d.ts files; those files SHOULD NOT be included with the app; they are purely used by TypeScript to output JS code... So this is probably a bug in your rules for the Obfuscator...
Hi @NathanaelA,
I agree the ability to use full 64-bit integers is a big plus!
Our obfuscator is not applied to the *.d.ts files at all - it is applied to the output from webpack, in this case vendor.js
, which contains this large numeric literal.
However, despite our obfuscator unable to parse this, there is still a problem: These 64-bit literals are NOT processed correctly through the Typescript compiler. For instance, the source for this enum value assigns the value 18446744073709551615 to the Any/All enum values. After compiling TS to JS, this literal is rounded to 18446744073709552000 (0x10000000000000180) which flips almost all bits to 0.
The offending compiled source is this (tns-core-modules/ui/html-view/html-view.ios.js
):
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
var html_view_common_1 = require("./html-view-common");
__export(require("./html-view-common"));
var HtmlView = (function (_super) {
__extends(HtmlView, _super);
function HtmlView() {
return _super !== null && _super.apply(this, arguments) || this;
}
HtmlView.prototype.createNativeView = function () {
var view = UITextView.new();
view.scrollEnabled = false;
view.editable = false;
view.selectable = true;
view.userInteractionEnabled = true;
view.dataDetectorTypes = 18446744073709552000;
return view;
};
Object.defineProperty(HtmlView.prototype, "ios", {
get: function () {
return this.nativeViewProtected;
},
enumerable: true,
configurable: true
});
HtmlView.prototype.onMeasure = function (widthMeasureSpec, heightMeasureSpec) {
var nativeView = this.nativeViewProtected;
if (nativeView) {
var width = html_view_common_1.layout.getMeasureSpecSize(widthMeasureSpec);
var widthMode = html_view_common_1.layout.getMeasureSpecMode(widthMeasureSpec);
var height = html_view_common_1.layout.getMeasureSpecSize(heightMeasureSpec);
var heightMode = html_view_common_1.layout.getMeasureSpecMode(heightMeasureSpec);
var desiredSize = html_view_common_1.layout.measureNativeView(nativeView, width, widthMode, height, heightMode);
var labelWidth = widthMode === html_view_common_1.layout.AT_MOST ? Math.min(desiredSize.width, width) : desiredSize.width;
var measureWidth = Math.max(labelWidth, this.effectiveMinWidth);
var measureHeight = Math.max(desiredSize.height, this.effectiveMinHeight);
var widthAndState = html_view_common_1.View.resolveSizeAndState(measureWidth, width, widthMode, 0);
var heightAndState = html_view_common_1.View.resolveSizeAndState(measureHeight, height, heightMode, 0);
this.setMeasuredDimension(widthAndState, heightAndState);
}
};
HtmlView.prototype[html_view_common_1.htmlProperty.getDefault] = function () {
return "";
};
HtmlView.prototype[html_view_common_1.htmlProperty.setNative] = function (value) {
var _a;
var htmlString = NSString.stringWithString(value + "");
var nsData = htmlString.dataUsingEncoding(NSUnicodeStringEncoding);
this.nativeViewProtected.attributedText = NSAttributedString.alloc().initWithDataOptionsDocumentAttributesError(nsData, (_a = {}, _a[NSDocumentTypeDocumentAttribute] = NSHTMLTextDocumentType, _a), null);
};
return HtmlView;
}(html_view_common_1.HtmlViewBase));
exports.HtmlView = HtmlView;
//# sourceMappingURL=html-view.ios.js.map
NOTE: This is not all. Further down the build, this file is bundled into vendor.js
and is assigned yet another literal, which is 0x10000000000000000
(dec: 18446744073709551616, or 2^64) in this snippet:
t.prototype.createNativeView=function(){var e=UITextView.new();return e.scrollEnabled=!1,e.editable=!1,e.selectable=!0,e.userInteractionEnabled=!0,e.dataDetectorTypes=0x10000000000000000,e}
What could be the right solution to this problem? We use Typescript 3.1.1, nativescript 5.3.2, tns-core-modules 5.3.1 and tns-ios 5.2.0. Build is running in Node v10.15.3 on macOS 10.14.5.
@bguijt You're right, these constants overflow the JSValues and indeed are not represented correctly. Since JSC still doesn't support BigInt
s, I think that the best way to fix it is to convert all constants in the .d.ts
files to their signed equivalents. This way 0xFFFFFFFFFFFFFFFF
will become -1
and will be correctly marshaled to native without losing precision.
@mbektchiev Would Number.MAX_SAFE_INTEGER
not be a safer integer?
I tried your suggested literal by adding the following snippet to my Webpack config.module.rules
(which replaces all large numeric literals with 0xFFFFFFFFFFFFFFFF
):
{
test: /\.js$|\.ts$/,
loader: StringReplacePlugin.replace({
replacements: [
{
pattern: /0x[0-9a-fA-F]{13,100}|[0-9]{16,100}/mg,
replacement: (match) => {
if (match != "340282346638528859811704183484516925440") {
console.warn(`\x1b[1m\x1b[33mWARNING: Javascript source error: Large numeric literal ${match} found - replacing with 0xFFFFFFFFFFFFFFFF\x1b[39m\x1b[21m`);
return "0xFFFFFFFFFFFFFFFF";
} else {
// 340282346638528859811704183484516925440.000000 is a max float value from animation.ios.js
return match;
}
}
}
]
})
}
This gives me the following console warning:
WARNING: Javascript source error: Large numeric literal 18446744073709552000 found - replacing with 0xFFFFFFFFFFFFFFFF
However, my bundledvendor.js
(still) contains the literal 0x10000000000000000
.
I tried with Number.MAX_SAFE_INTEGER
, and this works well!
0xFFFFFFFFFFFFFFFF
is actually the same number written as hexadecimal. To workaround the issue you can simply replace it with -1
@bguijt commented on Mon Jun 03 2019
Please check this diff: https://github.com/NativeScript/NativeScript/commit/f54f71bc60df8ba0772fe82f2fc911c2c3494e9d#diff-a4508a7cbf4cc46900ecccb75a31c03d
and find all value changes from 4294967295 (which is 0xFFFFFFFF) to 18446744073709551615 (which is 0xFFFFFFFFFFFFFFFF) which is an overflow to the JS numerical system and therefore incorrect.
This is probably OK for regular JS projects, however we use a commercial code obfuscator which is unable to handle these literals.
Please change these literals back to what they were ;-)