@@ -590,29 +590,41 @@ impl LiftIntrinsic {
590590 Self :: LiftFlatFloat64 => {
591591 let debug_log_fn = Intrinsic :: DebugLog . name ( ) ;
592592 let lift_flat_f64_fn = self . name ( ) ;
593- output. push_str ( & format ! ( "
594- function {lift_flat_f64_fn}(ctx) {{
595- {debug_log_fn}('[{lift_flat_f64_fn}()] args', {{ ctx }});
596- let val;
597-
598- if (ctx.useDirectParams) {{
599- if (ctx.params.length === 0) {{ throw new Error('expected at least one single f64 argument'); }}
600- val = ctx.params[0];
601- ctx.params = ctx.params.slice(1);
602- return [val, ctx];
603- }}
604-
605- if (ctx.storageLen !== undefined && ctx.storageLen < 8) {{
606- throw new Error(`insufficient storage ([${{ctx.storageLen}}] bytes) for lift (f64 requires 8 bytes)`);
607- }}
608-
609- val = new DataView(ctx.memory.buffer).getFloat64(ctx.storagePtr, true);
610- ctx.storagePtr += 8;
611- if (ctx.storageLen !== undefined) {{ ctx.storageLen -= 8; }}
612-
613- return [val, ctx];
614- }}
615- " ) ) ;
593+ uwriteln ! (
594+ output,
595+ r#"
596+ function {lift_flat_f64_fn}(ctx) {{
597+ {debug_log_fn}('[{lift_flat_f64_fn}()] args', {{ ctx }});
598+ let val;
599+
600+ if (ctx.useDirectParams) {{
601+ if (ctx.params.length === 0) {{
602+ throw new Error('expected at least one single f64 argument');
603+ }}
604+ val = ctx.params[0];
605+ ctx.params = ctx.params.slice(1);
606+
607+ if (ctx.inVariant) {{
608+ const dv = new DataView(new ArrayBuffer(8));
609+ dv.setBigInt64(0, val);
610+ val = dv.getFloat64(0);
611+ }}
612+
613+ return [val, ctx];
614+ }}
615+
616+ if (ctx.storageLen !== undefined && ctx.storageLen < 8) {{
617+ throw new Error(`insufficient storage ([${{ctx.storageLen}}] bytes) for lift (f64 requires 8 bytes)`);
618+ }}
619+
620+ val = new DataView(ctx.memory.buffer).getFloat64(ctx.storagePtr, true);
621+ ctx.storagePtr += 8;
622+ if (ctx.storageLen !== undefined) {{ ctx.storageLen -= 8; }}
623+
624+ return [val, ctx];
625+ }}
626+ "#
627+ ) ;
616628 }
617629
618630 Self :: LiftFlatChar => {
@@ -674,8 +686,9 @@ impl LiftIntrinsic {
674686
675687 if (ctx.useDirectParams) {{
676688 if (ctx.params.length < 2) {{ throw new Error('expected at least two u32 arguments'); }}
677- const offset = ctx.params[0];
678- if (!Number.isSafeInteger(offset)) {{ throw new Error('invalid offset'); }}
689+ let offset = ctx.params[0];
690+ if (typeof offset === 'bigint') {{ offset = Number(offset); }}
691+ if (!Number.isSafeInteger(offset)) {{ throw new Error('invalid offset'); }}
679692 const len = ctx.params[1];
680693 if (!Number.isSafeInteger(len)) {{ throw new Error('invalid len'); }}
681694 val = {decoder}.decode(new DataView(ctx.memory.buffer, offset, len));
@@ -712,6 +725,7 @@ impl LiftIntrinsic {
712725 if (ctx.useDirectParams) {{
713726 if (ctx.params.length < 2) {{ throw new Error('expected at least two u32 arguments'); }}
714727 const offset = ctx.params[0];
728+ if (typeof offset === 'bigint') {{ offset = Number(offset); }}
715729 if (!Number.isSafeInteger(offset)) {{ throw new Error('invalid offset'); }}
716730 const len = ctx.params[1];
717731 if (!Number.isSafeInteger(len)) {{ throw new Error('invalid len'); }}
@@ -797,11 +811,21 @@ impl LiftIntrinsic {
797811 let lift_u8 = Self :: LiftFlatU8 . name ( ) ;
798812 let lift_u16 = Self :: LiftFlatU16 . name ( ) ;
799813 let lift_u32 = Self :: LiftFlatU32 . name ( ) ;
814+ let lift_f64 = Self :: LiftFlatFloat64 . name ( ) ;
815+
800816 output. push_str ( & format ! ( r#"
801- function {lift_flat_variant_fn}(casesAndLiftFns) {{
817+ function {lift_flat_variant_fn}(meta) {{
818+ const {{
819+ caseMetas,
820+ variantSize32,
821+ variantAlign32,
822+ variantPayloadOffset32,
823+ variantFlatCount,
824+ isEnum,
825+ }} = meta;
826+
802827 return function {lift_flat_variant_fn}Inner(ctx) {{
803828 {debug_log_fn}('[{lift_flat_variant_fn}()] args', {{ ctx }});
804-
805829 const origUseParams = ctx.useDirectParams;
806830
807831 // If we're in the process of lifting a variant, we note
@@ -812,8 +836,8 @@ impl LiftIntrinsic {
812836 let caseIdx;
813837 let liftRes;
814838 const originalPtr = ctx.storagePtr;
815- const numCases = casesAndLiftFns .length;
816- if (casesAndLiftFns .length < 256) {{
839+ const numCases = caseMetas .length;
840+ if (caseMetas .length < 256) {{
817841 liftRes = {lift_u8}(ctx);
818842 }} else if (numCases >= 256 && numCases < 65536) {{
819843 liftRes = {lift_u16}(ctx);
@@ -825,11 +849,20 @@ impl LiftIntrinsic {
825849 caseIdx = liftRes[0];
826850 ctx = liftRes[1];
827851
828- const [ tag, liftFn, size32, align32, payloadOffset32, caseFlatCount, variantFlatCount ] = casesAndLiftFns[caseIdx];
829- if (payloadOffset32 === undefined) {{ throw new Error('unexpectedly missing payload offset'); }}
852+ const [
853+ tag,
854+ liftFn,
855+ caseSize32,
856+ caseAlign32,
857+ caseFlatCount,
858+ ] = caseMetas[caseIdx];
859+
860+ if (variantPayloadOffset32 === undefined) {{
861+ throw new Error('unexpectedly missing payload offset');
862+ }}
830863
831864 if (originalPtr !== undefined) {{
832- ctx.storagePtr = originalPtr + payloadOffset32 ;
865+ ctx.storagePtr = originalPtr + variantPayloadOffset32 ;
833866 }}
834867
835868 let val;
@@ -838,28 +871,32 @@ impl LiftIntrinsic {
838871 // NOTE: here we need to move past the entire object in memory
839872 // despite moving to the payload which we now know is missing/unnecessary
840873 if (originalPtr !== undefined) {{
841- ctx.storagePtr = originalPtr + size32 ;
874+ ctx.storagePtr = originalPtr + variantSize32 ;
842875 }}
843876 }} else {{
877+ if (ctx.useDirectParams && ctx.params && liftFn !== {lift_f64} && typeof ctx.params[0] === 'bigint') {{
878+ if (ctx.params[0] > BigInt(Number.MAX_SAFE_INTEGER)) {{
879+ throw new Error(`invalid value, reinterpreted i32/f32 too large: [${{ctx.params[0]}}]`);
880+ }}
881+ ctx.params[0] = Number(ctx.params[0]);
882+ }}
883+
844884 const [newVal, newCtx] = liftFn(ctx);
845885 val = {{ tag, val: newVal }};
846886 ctx = newCtx;
847-
848- // NOTE: Padding can be left over after doing the lift if it was less than
849- // space left for the payload normally.
850- if (originalPtr !== undefined) {{
851- ctx.storagePtr = Math.max(ctx.storagePtr, originalPtr + size32);
852- }}
853887 }}
854888
855889 if (origUseParams) {{
856- if (caseFlatCount === undefined || variantFlatCount === undefined) {{
857- throw new Error('variant flat count metadata is missing');
858- }}
859- if (caseFlatCount === null || variantFlatCount === null) {{
890+ if (variantFlatCount === undefined || variantFlatCount === null) {{
891+ {debug_log_fn}('[{lift_flat_variant_fn}()] variant with unknown flat count', {{ ctx, meta }});
860892 throw new Error('cannot lift variant with unknown flat count');
861893 }}
862- const remainingPayloadParams = variantFlatCount - 1 - caseFlatCount;
894+ if (caseFlatCount === undefined || caseFlatCount === null) {{
895+ {debug_log_fn}('[{lift_flat_variant_fn}()] case with unknown flat count', {{ ctx, meta, case: meta.caseMetas[caseIdx] }});
896+ throw new Error('cannot lift case with unknown flat count');
897+ }}
898+ // NOTE: enums can be tightly packed and do not have a descriminant
899+ const remainingPayloadParams = variantFlatCount - caseFlatCount - (isEnum ? 0 : 1);
863900 if (remainingPayloadParams < 0) {{
864901 throw new Error(`invalid variant flat count metadata`);
865902 }}
@@ -870,8 +907,8 @@ impl LiftIntrinsic {
870907 }}
871908
872909 if (ctx.storagePtr !== undefined) {{
873- const rem = ctx.storagePtr % align32 ;
874- if (rem !== 0) {{ ctx.storagePtr += align32 - rem; }}
910+ const rem = ctx.storagePtr % variantAlign32 ;
911+ if (rem !== 0) {{ ctx.storagePtr += variantAlign32 - rem; }}
875912 }}
876913
877914 ctx.inVariant = wasInVariant;
@@ -1040,10 +1077,12 @@ impl LiftIntrinsic {
10401077 let lift_flat_enum_fn = self . name ( ) ;
10411078 output. push_str ( & format ! (
10421079 r#"
1043- function {lift_flat_enum_fn}(casesAndLiftFns) {{
1080+ function {lift_flat_enum_fn}(meta) {{
1081+ meta.isEnum = true;
1082+ const f = {lift_variant}(meta);
10441083 return function {lift_flat_enum_fn}Inner(ctx) {{
10451084 {debug_log_fn}('[{lift_flat_enum_fn}()] args', {{ ctx }});
1046- const res = {lift_variant}(casesAndLiftFns) (ctx);
1085+ const res = f (ctx);
10471086 res[0] = res[0].tag;
10481087 return res;
10491088 }}
@@ -1058,10 +1097,11 @@ impl LiftIntrinsic {
10581097 let lift_flat_option_fn = self . name ( ) ;
10591098 output. push_str ( & format ! (
10601099 r#"
1061- function {lift_flat_option_fn}(casesAndLiftFns) {{
1100+ function {lift_flat_option_fn}(meta) {{
1101+ const f = {lift_variant}(meta);
10621102 return function {lift_flat_option_fn}Inner(ctx) {{
10631103 {debug_log_fn}('[{lift_flat_option_fn}()] args', {{ ctx }});
1064- return {lift_variant}(casesAndLiftFns) (ctx);
1104+ return f (ctx);
10651105 }}
10661106 }}
10671107 "#
@@ -1074,10 +1114,11 @@ impl LiftIntrinsic {
10741114 let lift_flat_result_fn = self . name ( ) ;
10751115 output. push_str ( & format ! (
10761116 r#"
1077- function {lift_flat_result_fn}(casesAndLiftFns) {{
1117+ function {lift_flat_result_fn}(meta) {{
1118+ const f = {lift_variant}(meta);
10781119 return function {lift_flat_result_fn}Inner(ctx) {{
10791120 {debug_log_fn}('[{lift_flat_result_fn}()] args', {{ ctx }});
1080- return {lift_variant}(casesAndLiftFns) (ctx);
1121+ return f (ctx);
10811122 }}
10821123 }}
10831124 "#
0 commit comments