@@ -949,6 +949,7 @@ export class JSBuilder extends ExportsWalker {
949949 /** Lifts a WebAssembly value to a JavaScript value. */
950950 makeLiftFromValue ( name : string , type : Type , sb : string [ ] = this . sb ) : void {
951951 if ( type . isInternalReference ) {
952+ // Lift reference types
952953 const clazz = assert ( type . getClassOrWrapper ( this . program ) ) ;
953954 if ( clazz . extends ( this . program . arrayBufferInstance . prototype ) ) {
954955 sb . push ( "__liftBuffer(" ) ;
@@ -1005,18 +1006,21 @@ export class JSBuilder extends ExportsWalker {
10051006 }
10061007 sb . push ( ")" ) ;
10071008 } else {
1008- sb . push ( name ) ;
1009- if ( type . isUnsignedIntegerValue && type . size == 32 ) {
1010- sb . push ( " >>> 0" ) ;
1011- } else if ( type == Type . bool ) {
1012- sb . push ( " != 0" ) ;
1009+ // Lift basic plain types
1010+ if ( type == Type . bool ) {
1011+ sb . push ( `${ name } != 0` ) ;
1012+ } else if ( type . isUnsignedIntegerValue && type . size >= 32 ) {
1013+ sb . push ( type . size == 64 ? `BigInt.asUintN(64, ${ name } )` : `${ name } >>> 0` ) ;
1014+ } else {
1015+ sb . push ( name ) ;
10131016 }
10141017 }
10151018 }
10161019
10171020 /** Lowers a JavaScript value to a WebAssembly value. */
10181021 makeLowerToValue ( name : string , type : Type , sb : string [ ] = this . sb ) : void {
10191022 if ( type . isInternalReference ) {
1023+ // Lower reference types
10201024 const clazz = assert ( type . getClass ( ) ) ;
10211025 if ( clazz . extends ( this . program . arrayBufferInstance . prototype ) ) {
10221026 sb . push ( "__lowerBuffer(" ) ;
@@ -1082,6 +1086,7 @@ export class JSBuilder extends ExportsWalker {
10821086 sb . push ( " || __notnull()" ) ;
10831087 }
10841088 } else {
1089+ // Lower basic types
10851090 sb . push ( name ) ; // basic value
10861091 if ( type . isIntegerValue && type . size == 64 ) {
10871092 sb . push ( " || 0n" ) ;
@@ -1278,26 +1283,27 @@ enum Mode {
12781283
12791284function isPlainValue ( type : Type , kind : Mode ) : bool {
12801285 if ( kind == Mode . IMPORT ) {
1281- // requires coercion of undefined to 0n
1282- if ( type . isIntegerValue && type . size == 64 ) return false ;
12831286 // may be stored to an Uint8Array, make sure to store 1/0
12841287 if ( type == Type . bool ) return false ;
1288+ // requires coercion of undefined to 0n
1289+ if ( type . isIntegerValue && type . size == 64 ) return false ;
12851290 } else {
1286- // requires coercion from signed to unsigned
1287- if ( type . isUnsignedIntegerValue && type . size == 32 ) return false ;
12881291 // requires coercion from 1/0 to true/false
12891292 if ( type == Type . bool ) return false ;
1293+ // requires coercion from signed to unsigned for u32 and u64.
1294+ // Note, u8 and u16 doesn't overflow in native type so mark as plain
1295+ if ( type . isUnsignedIntegerValue && type . size >= 32 ) return false ;
12901296 }
12911297 return ! type . isInternalReference ;
12921298}
12931299
12941300function isPlainFunction ( signature : Signature , mode : Mode ) : bool {
12951301 var parameterTypes = signature . parameterTypes ;
12961302 var inverseMode = mode == Mode . IMPORT ? Mode . EXPORT : Mode . IMPORT ;
1303+ if ( ! isPlainValue ( signature . returnType , mode ) ) return false ;
12971304 for ( let i = 0 , k = parameterTypes . length ; i < k ; ++ i ) {
12981305 if ( ! isPlainValue ( parameterTypes [ i ] , inverseMode ) ) return false ;
12991306 }
1300- if ( ! isPlainValue ( signature . returnType , mode ) ) return false ;
13011307 return true ;
13021308}
13031309
0 commit comments