porffor 0.21.7 → 0.21.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -149,7 +149,7 @@ export const __Object_fromEntries = (iterable: any): object => {
149
149
 
150
150
  for (const x of iterable) {
151
151
  if (!Porffor.object.isObject(x)) throw new TypeError('Iterator contains non-object');
152
- out[ecma262.ToPropertyKey(x[0])] = x[1];
152
+ out[x[0]] = x[1];
153
153
  }
154
154
 
155
155
  return out;
@@ -390,6 +390,41 @@ export const __Object_isSealed = (obj: any): any => {
390
390
  };
391
391
 
392
392
 
393
+ export const __Object_getOwnPropertyDescriptor = (obj: any, prop: any): any => {
394
+ if (!Porffor.object.isObjectOrSymbol(obj)) throw new TypeError('Object should be an object or symbol');
395
+
396
+ const p: any = ecma262.ToPropertyKey(prop);
397
+ const entryPtr: i32 = Porffor.object.lookup(obj, p);
398
+ if (entryPtr == -1) return undefined;
399
+
400
+ const out: object = {};
401
+
402
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
403
+ out.configurable = Boolean(tail & 0b0010);
404
+ out.enumerable = Boolean(tail & 0b0100);
405
+
406
+ if (tail & 0b0001) {
407
+ // accessor descriptor
408
+
409
+ return out;
410
+ }
411
+
412
+ // data descriptor
413
+ const value: any = Porffor.wasm.f64.load(entryPtr, 0, 4);
414
+ Porffor.wasm`
415
+ local.get ${tail}
416
+ i32.to_u
417
+ i32.const 8
418
+ i32.shr_u
419
+ local.set ${value+1}`;
420
+
421
+ out.writable = Boolean(tail & 0b1000);
422
+ out.value = value;
423
+
424
+ return out;
425
+ };
426
+
427
+
393
428
  export const __Object_prototype_toString = (_this: object) => {
394
429
  let out: bytestring = '[object Object]';
395
430
  return out;
@@ -2881,231 +2881,242 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2881
2881
  value: decl.left.property.name
2882
2882
  };
2883
2883
 
2884
- // todo: review last type usage here
2884
+ // todo/perf: use i32 object (and prop?) locals
2885
+ const objectWasm = [ [ Opcodes.local_get, localTmp(scope, '#member_obj') ] ];
2886
+ const propertyWasm = [ [ Opcodes.local_get, localTmp(scope, '#member_prop_assign') ] ];
2885
2887
 
2886
- return typeSwitch(scope, getNodeType(scope, decl.left.object), {
2887
- [TYPES.array]: [
2888
- ...generate(scope, object),
2889
- Opcodes.i32_to_u,
2890
-
2891
- // get index as valtype
2892
- ...generate(scope, property),
2893
- Opcodes.i32_to_u,
2894
-
2895
- // turn into byte offset by * valtypeSize + 1
2896
- ...number(ValtypeSize[valtype] + 1, Valtype.i32),
2897
- [ Opcodes.i32_mul ],
2898
- [ Opcodes.i32_add ],
2899
- [ Opcodes.local_tee, pointerTmp ],
2900
-
2901
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2902
- [ Opcodes.local_get, pointerTmp ],
2903
- [ Opcodes.load, 0, ValtypeSize.i32 ]
2904
- ], generate(scope, decl.right), [
2905
- [ Opcodes.local_get, pointerTmp ],
2906
- [ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
2907
- ], getNodeType(scope, decl.right), false, name, true)),
2908
- [ Opcodes.local_tee, newValueTmp ],
2909
- [ Opcodes.store, 0, ValtypeSize.i32 ],
2910
-
2911
- [ Opcodes.local_get, pointerTmp ],
2912
- ...getNodeType(scope, decl),
2913
- [ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
2888
+ return [
2889
+ ...generate(scope, object),
2890
+ [ Opcodes.local_set, localTmp(scope, '#member_obj') ],
2914
2891
 
2915
- [ Opcodes.local_get, newValueTmp ]
2916
- ],
2892
+ ...generate(scope, property, false, '#member_prop_assign'),
2893
+ [ Opcodes.local_set, localTmp(scope, '#member_prop_assign') ],
2917
2894
 
2918
- [TYPES.object]: [
2919
- ...generate(scope, object),
2920
- Opcodes.i32_to_u,
2921
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, localTmp(scope, '#objset_object', Valtype.i32) ] ]),
2922
- ...getNodeType(scope, object),
2923
-
2924
- ...generate(scope, property, false, '#member_prop'),
2925
- ...getNodeType(scope, property),
2926
- ...toPropertyKey(scope, op === '='),
2927
- ...(op === '=' ? [] : [ [ Opcodes.local_set, localTmp(scope, '#objset_property_type', Valtype.i32) ] ]),
2928
- ...(op === '=' ? [] : [
2895
+ // todo: review last type usage here
2896
+ ...typeSwitch(scope, getNodeType(scope, decl.left.object), {
2897
+ [TYPES.array]: [
2898
+ ...objectWasm,
2929
2899
  Opcodes.i32_to_u,
2930
- [ Opcodes.local_tee, localTmp(scope, '#objset_property', Valtype.i32) ]
2931
- ]),
2932
- ...(op === '=' ? [] : [ [ Opcodes.local_get, localTmp(scope, '#objset_property_type', Valtype.i32) ] ]),
2933
2900
 
2934
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2935
- [ Opcodes.local_get, localTmp(scope, '#objset_object', Valtype.i32) ],
2936
- ...getNodeType(scope, object),
2937
-
2938
- [ Opcodes.local_get, localTmp(scope, '#objset_property', Valtype.i32) ],
2939
- [ Opcodes.local_get, localTmp(scope, '#objset_property_type', Valtype.i32) ],
2940
-
2941
- [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_get').index) ],
2942
- ...setLastType(scope)
2943
- ], generate(scope, decl.right), getLastType(scope), getNodeType(scope, decl.right), false, name, true)),
2944
- ...getNodeType(scope, decl),
2945
-
2946
- [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_set').index) ],
2947
- [ Opcodes.drop ],
2948
- // ...setLastType(scope, getNodeType(scope, decl)),
2949
- ],
2901
+ // get index as valtype
2902
+ ...propertyWasm,
2903
+ Opcodes.i32_to_u,
2950
2904
 
2951
- ...wrapBC({
2952
- [TYPES.uint8array]: [
2905
+ // turn into byte offset by * valtypeSize + 1
2906
+ ...number(ValtypeSize[valtype] + 1, Valtype.i32),
2907
+ [ Opcodes.i32_mul ],
2953
2908
  [ Opcodes.i32_add ],
2954
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
2909
+ [ Opcodes.local_tee, pointerTmp ],
2955
2910
 
2956
2911
  ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2957
2912
  [ Opcodes.local_get, pointerTmp ],
2958
- [ Opcodes.i32_load8_u, 0, 4 ],
2959
- Opcodes.i32_from_u
2960
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
2913
+ [ Opcodes.load, 0, ValtypeSize.i32 ]
2914
+ ], generate(scope, decl.right), [
2915
+ [ Opcodes.local_get, pointerTmp ],
2916
+ [ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
2917
+ ], getNodeType(scope, decl.right), false, name, true)),
2961
2918
  [ Opcodes.local_tee, newValueTmp ],
2919
+ [ Opcodes.store, 0, ValtypeSize.i32 ],
2962
2920
 
2963
- Opcodes.i32_to_u,
2964
- [ Opcodes.i32_store8, 0, 4 ]
2965
- ],
2966
- [TYPES.uint8clampedarray]: [
2967
- [ Opcodes.i32_add ],
2968
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
2921
+ [ Opcodes.local_get, pointerTmp ],
2922
+ ...getNodeType(scope, decl),
2923
+ [ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
2969
2924
 
2970
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2971
- [ Opcodes.local_get, pointerTmp ],
2972
- [ Opcodes.i32_load8_u, 0, 4 ],
2973
- Opcodes.i32_from_u
2974
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
2975
- [ Opcodes.local_tee, newValueTmp ],
2925
+ [ Opcodes.local_get, newValueTmp ]
2926
+ ],
2976
2927
 
2977
- ...number(0),
2978
- [ Opcodes.f64_max ],
2979
- ...number(255),
2980
- [ Opcodes.f64_min ],
2928
+ [TYPES.object]: [
2929
+ ...objectWasm,
2981
2930
  Opcodes.i32_to_u,
2982
- [ Opcodes.i32_store8, 0, 4 ]
2983
- ],
2984
- [TYPES.int8array]: [
2985
- [ Opcodes.i32_add ],
2986
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
2931
+ ...(op === '=' ? [] : [ [ Opcodes.local_tee, localTmp(scope, '#objset_object', Valtype.i32) ] ]),
2932
+ ...getNodeType(scope, object),
2933
+
2934
+ ...propertyWasm,
2935
+ ...getNodeType(scope, property),
2936
+ ...toPropertyKey(scope, op === '='),
2937
+ ...(op === '=' ? [] : [ [ Opcodes.local_set, localTmp(scope, '#objset_property_type', Valtype.i32) ] ]),
2938
+ ...(op === '=' ? [] : [
2939
+ Opcodes.i32_to_u,
2940
+ [ Opcodes.local_tee, localTmp(scope, '#objset_property', Valtype.i32) ]
2941
+ ]),
2942
+ ...(op === '=' ? [] : [ [ Opcodes.local_get, localTmp(scope, '#objset_property_type', Valtype.i32) ] ]),
2987
2943
 
2988
2944
  ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2989
- [ Opcodes.local_get, pointerTmp ],
2990
- [ Opcodes.i32_load8_s, 0, 4 ],
2991
- Opcodes.i32_from
2992
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
2993
- [ Opcodes.local_tee, newValueTmp ],
2945
+ [ Opcodes.local_get, localTmp(scope, '#objset_object', Valtype.i32) ],
2946
+ ...getNodeType(scope, object),
2994
2947
 
2995
- Opcodes.i32_to,
2996
- [ Opcodes.i32_store8, 0, 4 ]
2997
- ],
2998
- [TYPES.uint16array]: [
2999
- ...number(2, Valtype.i32),
3000
- [ Opcodes.i32_mul ],
3001
- [ Opcodes.i32_add ],
3002
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
2948
+ [ Opcodes.local_get, localTmp(scope, '#objset_property', Valtype.i32) ],
2949
+ [ Opcodes.local_get, localTmp(scope, '#objset_property_type', Valtype.i32) ],
3003
2950
 
3004
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3005
- [ Opcodes.local_get, pointerTmp ],
3006
- [ Opcodes.i32_load16_u, 0, 4 ],
3007
- Opcodes.i32_from_u
3008
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3009
- [ Opcodes.local_tee, newValueTmp ],
2951
+ [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_get').index) ],
2952
+ ...setLastType(scope)
2953
+ ], generate(scope, decl.right), getLastType(scope), getNodeType(scope, decl.right), false, name, true)),
2954
+ ...getNodeType(scope, decl),
3010
2955
 
3011
- Opcodes.i32_to_u,
3012
- [ Opcodes.i32_store16, 0, 4 ]
2956
+ [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_set').index) ],
2957
+ [ Opcodes.drop ],
2958
+ // ...setLastType(scope, getNodeType(scope, decl)),
3013
2959
  ],
3014
- [TYPES.int16array]: [
3015
- ...number(2, Valtype.i32),
3016
- [ Opcodes.i32_mul ],
3017
- [ Opcodes.i32_add ],
3018
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3019
2960
 
3020
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3021
- [ Opcodes.local_get, pointerTmp ],
3022
- [ Opcodes.i32_load16_s, 0, 4 ],
3023
- Opcodes.i32_from
3024
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3025
- [ Opcodes.local_tee, newValueTmp ],
2961
+ ...wrapBC({
2962
+ [TYPES.uint8array]: [
2963
+ [ Opcodes.i32_add ],
2964
+ ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3026
2965
 
3027
- Opcodes.i32_to,
3028
- [ Opcodes.i32_store16, 0, 4 ]
3029
- ],
3030
- [TYPES.uint32array]: [
3031
- ...number(4, Valtype.i32),
3032
- [ Opcodes.i32_mul ],
3033
- [ Opcodes.i32_add ],
3034
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
2966
+ ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2967
+ [ Opcodes.local_get, pointerTmp ],
2968
+ [ Opcodes.i32_load8_u, 0, 4 ],
2969
+ Opcodes.i32_from_u
2970
+ ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
2971
+ [ Opcodes.local_tee, newValueTmp ],
3035
2972
 
3036
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3037
- [ Opcodes.local_get, pointerTmp ],
3038
- [ Opcodes.i32_load, 0, 4 ],
3039
- Opcodes.i32_from_u
3040
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3041
- [ Opcodes.local_tee, newValueTmp ],
2973
+ Opcodes.i32_to_u,
2974
+ [ Opcodes.i32_store8, 0, 4 ]
2975
+ ],
2976
+ [TYPES.uint8clampedarray]: [
2977
+ [ Opcodes.i32_add ],
2978
+ ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
2979
+
2980
+ ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2981
+ [ Opcodes.local_get, pointerTmp ],
2982
+ [ Opcodes.i32_load8_u, 0, 4 ],
2983
+ Opcodes.i32_from_u
2984
+ ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
2985
+ [ Opcodes.local_tee, newValueTmp ],
2986
+
2987
+ ...number(0),
2988
+ [ Opcodes.f64_max ],
2989
+ ...number(255),
2990
+ [ Opcodes.f64_min ],
2991
+ Opcodes.i32_to_u,
2992
+ [ Opcodes.i32_store8, 0, 4 ]
2993
+ ],
2994
+ [TYPES.int8array]: [
2995
+ [ Opcodes.i32_add ],
2996
+ ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3042
2997
 
3043
- Opcodes.i32_to_u,
3044
- [ Opcodes.i32_store, 0, 4 ]
3045
- ],
3046
- [TYPES.int32array]: [
3047
- ...number(4, Valtype.i32),
3048
- [ Opcodes.i32_mul ],
3049
- [ Opcodes.i32_add ],
3050
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
2998
+ ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2999
+ [ Opcodes.local_get, pointerTmp ],
3000
+ [ Opcodes.i32_load8_s, 0, 4 ],
3001
+ Opcodes.i32_from
3002
+ ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3003
+ [ Opcodes.local_tee, newValueTmp ],
3051
3004
 
3052
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3053
- [ Opcodes.local_get, pointerTmp ],
3054
- [ Opcodes.i32_load, 0, 4 ],
3055
- Opcodes.i32_from
3056
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3057
- [ Opcodes.local_tee, newValueTmp ],
3005
+ Opcodes.i32_to,
3006
+ [ Opcodes.i32_store8, 0, 4 ]
3007
+ ],
3008
+ [TYPES.uint16array]: [
3009
+ ...number(2, Valtype.i32),
3010
+ [ Opcodes.i32_mul ],
3011
+ [ Opcodes.i32_add ],
3012
+ ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3058
3013
 
3059
- Opcodes.i32_to,
3060
- [ Opcodes.i32_store, 0, 4 ]
3061
- ],
3062
- [TYPES.float32array]: [
3063
- ...number(4, Valtype.i32),
3064
- [ Opcodes.i32_mul ],
3065
- [ Opcodes.i32_add ],
3066
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3014
+ ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3015
+ [ Opcodes.local_get, pointerTmp ],
3016
+ [ Opcodes.i32_load16_u, 0, 4 ],
3017
+ Opcodes.i32_from_u
3018
+ ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3019
+ [ Opcodes.local_tee, newValueTmp ],
3067
3020
 
3068
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3069
- [ Opcodes.local_get, pointerTmp ],
3070
- [ Opcodes.f32_load, 0, 4 ],
3071
- [ Opcodes.f64_promote_f32 ]
3072
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3073
- [ Opcodes.local_tee, newValueTmp ],
3021
+ Opcodes.i32_to_u,
3022
+ [ Opcodes.i32_store16, 0, 4 ]
3023
+ ],
3024
+ [TYPES.int16array]: [
3025
+ ...number(2, Valtype.i32),
3026
+ [ Opcodes.i32_mul ],
3027
+ [ Opcodes.i32_add ],
3028
+ ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3074
3029
 
3075
- [ Opcodes.f32_demote_f64 ],
3076
- [ Opcodes.f32_store, 0, 4 ]
3077
- ],
3078
- [TYPES.float64array]: [
3079
- ...number(8, Valtype.i32),
3080
- [ Opcodes.i32_mul ],
3081
- [ Opcodes.i32_add ],
3082
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3030
+ ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3031
+ [ Opcodes.local_get, pointerTmp ],
3032
+ [ Opcodes.i32_load16_s, 0, 4 ],
3033
+ Opcodes.i32_from
3034
+ ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3035
+ [ Opcodes.local_tee, newValueTmp ],
3083
3036
 
3084
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3085
- [ Opcodes.local_get, pointerTmp ],
3086
- [ Opcodes.f64_load, 0, 4 ]
3087
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3088
- [ Opcodes.local_tee, newValueTmp ],
3037
+ Opcodes.i32_to,
3038
+ [ Opcodes.i32_store16, 0, 4 ]
3039
+ ],
3040
+ [TYPES.uint32array]: [
3041
+ ...number(4, Valtype.i32),
3042
+ [ Opcodes.i32_mul ],
3043
+ [ Opcodes.i32_add ],
3044
+ ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3089
3045
 
3090
- [ Opcodes.f64_store, 0, 4 ]
3091
- ],
3092
- }, {
3093
- prelude: [
3094
- ...generate(scope, object),
3095
- Opcodes.i32_to_u,
3096
- [ Opcodes.i32_load, 0, 4 ],
3046
+ ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3047
+ [ Opcodes.local_get, pointerTmp ],
3048
+ [ Opcodes.i32_load, 0, 4 ],
3049
+ Opcodes.i32_from_u
3050
+ ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3051
+ [ Opcodes.local_tee, newValueTmp ],
3097
3052
 
3098
- ...generate(scope, property),
3099
- Opcodes.i32_to_u,
3100
- ],
3101
- postlude: [
3102
- // setLastType(scope, TYPES.number)
3103
- [ Opcodes.local_get, newValueTmp ]
3104
- ]
3105
- }),
3053
+ Opcodes.i32_to_u,
3054
+ [ Opcodes.i32_store, 0, 4 ]
3055
+ ],
3056
+ [TYPES.int32array]: [
3057
+ ...number(4, Valtype.i32),
3058
+ [ Opcodes.i32_mul ],
3059
+ [ Opcodes.i32_add ],
3060
+ ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3106
3061
 
3107
- default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
3108
- }, valtypeBinary);
3062
+ ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3063
+ [ Opcodes.local_get, pointerTmp ],
3064
+ [ Opcodes.i32_load, 0, 4 ],
3065
+ Opcodes.i32_from
3066
+ ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3067
+ [ Opcodes.local_tee, newValueTmp ],
3068
+
3069
+ Opcodes.i32_to,
3070
+ [ Opcodes.i32_store, 0, 4 ]
3071
+ ],
3072
+ [TYPES.float32array]: [
3073
+ ...number(4, Valtype.i32),
3074
+ [ Opcodes.i32_mul ],
3075
+ [ Opcodes.i32_add ],
3076
+ ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3077
+
3078
+ ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3079
+ [ Opcodes.local_get, pointerTmp ],
3080
+ [ Opcodes.f32_load, 0, 4 ],
3081
+ [ Opcodes.f64_promote_f32 ]
3082
+ ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3083
+ [ Opcodes.local_tee, newValueTmp ],
3084
+
3085
+ [ Opcodes.f32_demote_f64 ],
3086
+ [ Opcodes.f32_store, 0, 4 ]
3087
+ ],
3088
+ [TYPES.float64array]: [
3089
+ ...number(8, Valtype.i32),
3090
+ [ Opcodes.i32_mul ],
3091
+ [ Opcodes.i32_add ],
3092
+ ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3093
+
3094
+ ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3095
+ [ Opcodes.local_get, pointerTmp ],
3096
+ [ Opcodes.f64_load, 0, 4 ]
3097
+ ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3098
+ [ Opcodes.local_tee, newValueTmp ],
3099
+
3100
+ [ Opcodes.f64_store, 0, 4 ]
3101
+ ],
3102
+ }, {
3103
+ prelude: [
3104
+ ...objectWasm,
3105
+ Opcodes.i32_to_u,
3106
+ [ Opcodes.i32_load, 0, 4 ],
3107
+
3108
+ ...propertyWasm,
3109
+ Opcodes.i32_to_u,
3110
+ ],
3111
+ postlude: [
3112
+ // setLastType(scope, TYPES.number)
3113
+ [ Opcodes.local_get, newValueTmp ]
3114
+ ]
3115
+ }),
3116
+
3117
+ default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
3118
+ }, valtypeBinary)
3119
+ ];
3109
3120
  }
3110
3121
 
3111
3122
  if (!name) return todo(scope, 'destructuring is not supported yet', true);
@@ -4329,7 +4340,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
4329
4340
  const local = global ? globals[name] : scope.locals?.[name];
4330
4341
  if (
4331
4342
  Prefs.data && firstAssign && useRawElements &&
4332
- name !== '#member_prop' &&
4343
+ name !== '#member_prop' && name !== '#member_prop_assign' &&
4333
4344
  (!globalThis.precompile || !global)
4334
4345
  ) {
4335
4346
  makeData(scope, elements, rawPtr, itemType, initEmpty);
@@ -4339,10 +4350,32 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
4339
4350
  }
4340
4351
 
4341
4352
  if (local != null) {
4353
+ // hack: handle allocation for #member_prop's here instead of in several places /shrug
4354
+ let shouldGet = true;
4355
+ if (name === '#member_prop') {
4356
+ if (!scope._allocatedMemberProp) {
4357
+ out.push(
4358
+ ...number(rawPtr),
4359
+ [ global ? Opcodes.global_set : Opcodes.local_set, local.idx ]
4360
+ );
4361
+
4362
+ scope._allocatedMemberProp = true;
4363
+ }
4364
+ }
4365
+
4366
+ if (name === '#member_prop_assign') {
4367
+ out.push(
4368
+ [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_allocate').index) ]
4369
+ );
4370
+ shouldGet = false;
4371
+ }
4372
+
4342
4373
  const pointerTmp = localTmp(scope, '#makearray_pointer_tmp', Valtype.i32);
4343
4374
  out.push(
4344
- [ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
4345
- Opcodes.i32_to_u,
4375
+ ...(shouldGet ? [
4376
+ [ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
4377
+ Opcodes.i32_to_u
4378
+ ] : []),
4346
4379
  [ Opcodes.local_set, pointerTmp ]
4347
4380
  );
4348
4381
 
@@ -4654,6 +4687,7 @@ const generateMember = (scope, decl, _global, _name) => {
4654
4687
  value: decl.property.name
4655
4688
  };
4656
4689
 
4690
+ // todo/perf: use i32 object (and prop?) locals
4657
4691
  const objectWasm = [ [ Opcodes.local_get, localTmp(scope, '#member_obj') ] ];
4658
4692
  const propertyWasm = [ [ Opcodes.local_get, localTmp(scope, '#member_prop') ] ];
4659
4693