-
-
Notifications
You must be signed in to change notification settings - Fork 670
Writing portable code
When targeting both WebAssembly with asc
and JavaScript with tsc
, there are a few semantic differences to take care of.
While asc
understands the meaning of
// non-portable
let someFloat: f32 = 1.5;
let someInt: i32 = <i32>someFloat;
and then inserts the correct conversion steps, tsc
does not because all numeric types are just aliases of number
. Hence, when targeting JavaScript with tsc
, the above will result in
// js
var someFloat = 1.5;
var someInt = someFloat;
which is obviously wrong. To account for this, explicit conversions can be inserted, resulting in actually portable code. For example
// portable
let someFloat: f32 = 1.5;
let someInt: i32 = (<i32>someFloat) | 0;
will result in
// js
var someFloat = 1.5;
var someInt = 1.5 | 0;
which is correct.
Additionally, an equally named portable conversion function is present for each built-in type that transforms any other built-in type to a value of the target type:
// using a portable conversion function
let someFloat: f32 = 1.5;
let someInt: i32 = i32(someFloat);
Likewise, again because asc
knows the meaning but tsc
does not, overflows must be handled explicitly:
// non-portable
let someU8: u8 = 255;
let someOtherU8: u8 = someU8 + 1;
// portable
let someU8: u8 = 255;
let someOtherU8: u8 = (someU8 + 1) & 0xff;
// using a portable conversion function
let someU8: u8 = 255;
let someOtherU8: u8 = u8(someU8 + 1);
In JavaScript, all numeric values are IEEE754 doubles that cannot represent the full range of values fitting in a 64-bit integer (max. safe integer is 2^53-1). Hence i64
and u64
are not portable and not present in std/portable.d.ts
. There are several ways to deal with this. One is to use an i64 polyfill like in this example.
Other than that, some generic built-in functions do not support the full range of type arguments. For example:
-
load<
T = u8
>(offset:usize
):T
- and - store<T = u8
>(offset:usize
, value:T
):void
are limited tou8
because the type argument cannot be evaluated in JS.