porffor 0.21.7 → 0.22.0

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,118 @@ export const __Object_isSealed = (obj: any): any => {
390
390
  };
391
391
 
392
392
 
393
+ export const __Object_getOwnPropertyDescriptor = (obj: any, prop: any): any => {
394
+ // todo: support non-pure-objects
395
+ if (Porffor.rawType(obj) != Porffor.TYPES.object) {
396
+ return undefined;
397
+ }
398
+
399
+ const p: any = ecma262.ToPropertyKey(prop);
400
+ const entryPtr: i32 = Porffor.object.lookup(obj, p);
401
+ if (entryPtr == -1) return undefined;
402
+
403
+ const out: object = {};
404
+
405
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
406
+ out.configurable = Boolean(tail & 0b0010);
407
+ out.enumerable = Boolean(tail & 0b0100);
408
+
409
+ if (tail & 0b0001) {
410
+ // accessor descriptor
411
+
412
+ return out;
413
+ }
414
+
415
+ // data descriptor
416
+ const value: any = Porffor.wasm.f64.load(entryPtr, 0, 4);
417
+ Porffor.wasm`
418
+ local.get ${tail}
419
+ i32.to_u
420
+ i32.const 8
421
+ i32.shr_u
422
+ local.set ${value+1}`;
423
+
424
+ out.writable = Boolean(tail & 0b1000);
425
+ out.value = value;
426
+
427
+ return out;
428
+ };
429
+
430
+ export const __Object_getOwnPropertyDescriptors = (obj: any): any => {
431
+ const out: object = {};
432
+
433
+ // todo: support non-pure-objects
434
+ if (Porffor.rawType(obj) != Porffor.TYPES.object) {
435
+ return out;
436
+ }
437
+
438
+ for (const x in obj) {
439
+ out[x] = __Object_getOwnPropertyDescriptor(obj, x);
440
+ }
441
+
442
+ return out;
443
+ };
444
+
445
+
446
+ export const __Object_getOwnPropertyNames = (obj: any): any[] => {
447
+ if (obj == null) throw new TypeError('Argument is nullish, expected object');
448
+
449
+ const out: any[] = Porffor.allocate();
450
+
451
+ const t: i32 = Porffor.rawType(obj);
452
+ if (t == Porffor.TYPES.object) {
453
+ let ptr: i32 = Porffor.wasm`local.get ${obj}` + 5;
454
+ const endPtr: i32 = ptr + Porffor.wasm.i32.load(obj, 0, 0) * 14;
455
+
456
+ let i: i32 = 0;
457
+ for (; ptr < endPtr; ptr += 14) {
458
+ let key: any;
459
+ Porffor.wasm`local raw i32
460
+ local.get ${ptr}
461
+ i32.to_u
462
+ i32.load 0 0
463
+ local.set raw
464
+
465
+ local.get raw
466
+ i32.const 31
467
+ i32.shr_u
468
+ if 127
469
+ i32.const 67
470
+ local.set ${key+1}
471
+
472
+ local.get raw
473
+ i32.const 2147483647
474
+ i32.and
475
+ else
476
+ i32.const 195
477
+ local.set ${key+1}
478
+
479
+ local.get raw
480
+ end
481
+ i32.from_u
482
+ local.set ${key}`;
483
+
484
+ out[i++] = key;
485
+ }
486
+
487
+ out.length = i;
488
+ } else if (Porffor.fastOr(
489
+ t == Porffor.TYPES.array,
490
+ t == Porffor.TYPES.bytestring,
491
+ t == Porffor.TYPES.string
492
+ )) {
493
+ const len: i32 = obj.length;
494
+ out.length = len;
495
+
496
+ for (let i: i32 = 0; i < len; i++) {
497
+ out[i] = __Number_prototype_toString(i);
498
+ }
499
+ }
500
+
501
+ return out;
502
+ };
503
+
504
+
393
505
  export const __Object_prototype_toString = (_this: object) => {
394
506
  let out: bytestring = '[object Object]';
395
507
  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