porffor 0.22.5 → 0.22.7

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.
@@ -230,7 +230,7 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
230
230
  // };
231
231
  // }
232
232
 
233
- const exports = funcs.filter(x => x.export).map((x, i) => [ ...encodeString(x.name === 'main' ? 'm' : x.name), ExportDesc.func, x.index ]);
233
+ const exports = funcs.filter(x => x.export).map((x, i) => [ ...encodeString(x.name === 'main' ? 'm' : x.name), ExportDesc.func, ...unsignedLEB128(x.index) ]);
234
234
 
235
235
  if (Prefs.alwaysMemory && pages.size === 0) pages.set('--always-memory', 0);
236
236
  if (optLevel === 0) pages.set('O0 precaution', 0);
@@ -276,7 +276,26 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
276
276
 
277
277
  if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
278
278
 
279
- return encodeVector([ ...encodeVector(localDecl), ...x.wasm.flat().filter(x => x != null && x <= 0xff), Opcodes.end ]);
279
+ // todo: move const, call transforms here too?
280
+
281
+ const wasm = [];
282
+ for (let i = 0; i < x.wasm.length; i++) {
283
+ let o = x.wasm[i];
284
+
285
+ if (
286
+ (o[0] === Opcodes.local_get || o[0] === Opcodes.local_set || o[0] === Opcodes.local_tee || o[0] === Opcodes.global_get || o[0] === Opcodes.global_set) &&
287
+ o[1] > 127
288
+ ) {
289
+ const n = o[1];
290
+ o = [...o];
291
+ o.pop();
292
+ unsignedLEB128_into(n, o);
293
+ }
294
+
295
+ wasm.push(...o);
296
+ }
297
+
298
+ return encodeVector([ ...encodeVector(localDecl), ...wasm.flat().filter(x => x != null && x <= 0xff), Opcodes.end ]);
280
299
  }))
281
300
  );
282
301
 
@@ -269,6 +269,51 @@ local.set ${err}`;
269
269
  0, 12);
270
270
  };
271
271
 
272
+ export const __Porffor_object_delete = (_this: object, key: any): boolean => {
273
+ const entryPtr: i32 = __Porffor_object_lookup(_this, key);
274
+ if (entryPtr == -1) {
275
+ // not found, stop
276
+ return true;
277
+ }
278
+
279
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
280
+ if (!(tail & 0b0010)) {
281
+ // not configurable
282
+ // todo: throw in strict mode
283
+ return false;
284
+ }
285
+
286
+ const ind: i32 = (entryPtr - Porffor.wasm`local.get ${_this}`) / 14;
287
+
288
+ // decrement size
289
+ let size: i32 = Porffor.wasm.i32.load(_this, 0, 0);
290
+ Porffor.wasm.i32.store(_this, --size, 0, 0);
291
+
292
+ if (size > ind) {
293
+ // offset all elements after by -1 ind
294
+ Porffor.wasm`
295
+ ;; dst = entryPtr
296
+ local.get ${entryPtr}
297
+
298
+ ;; src = entryPtr + 14 (+ 1 entry)
299
+ local.get ${entryPtr}
300
+ i32.const 14
301
+ i32.add
302
+
303
+ ;; size = (size - ind) * 14
304
+ local.get ${size}
305
+ local.get ${ind}
306
+ i32.sub
307
+ i32.const 14
308
+ i32.mul
309
+
310
+ memory.copy 0 0`;
311
+ }
312
+
313
+ return true;
314
+ };
315
+
316
+
272
317
  export const __Porffor_object_isEnumerable = (entryPtr: i32): boolean => {
273
318
  const out: boolean = Porffor.wasm.i32.load8_u(entryPtr, 0, 12) & 0b0100;
274
319
  return out;
@@ -280,7 +325,6 @@ export const __Porffor_object_isObject = (arg: any): boolean => {
280
325
  return Porffor.fastAnd(
281
326
  arg != 0, // null
282
327
  t > 0x05,
283
- t != Porffor.TYPES.undefined,
284
328
  t != Porffor.TYPES.string,
285
329
  t != Porffor.TYPES.bytestring,
286
330
  );
@@ -291,7 +335,6 @@ export const __Porffor_object_isObjectOrSymbol = (arg: any): boolean => {
291
335
  return Porffor.fastAnd(
292
336
  arg != 0, // null
293
337
  t > 0x04,
294
- t != Porffor.TYPES.undefined,
295
338
  t != Porffor.TYPES.string,
296
339
  t != Porffor.TYPES.bytestring,
297
340
  );
@@ -0,0 +1,132 @@
1
+ import type {} from './porffor.d.ts';
2
+
3
+ // todo: support receiver
4
+ export const __Reflect_get = (target: any, prop: any) => {
5
+ if (!Porffor.object.isObject(target)) throw new TypeError('Target is a non-object');
6
+
7
+ return target[prop];
8
+ };
9
+
10
+ // todo: support receiver
11
+ export const __Reflect_set = (target: any, prop: any, value: any) => {
12
+ if (!Porffor.object.isObject(target)) throw new TypeError('Target is a non-object');
13
+
14
+ try {
15
+ target[prop] = value;
16
+ return true;
17
+ } catch {
18
+ return false;
19
+ }
20
+ };
21
+
22
+ export const __Reflect_has = (target: any, prop: any) => {
23
+ if (!Porffor.object.isObject(target)) throw new TypeError('Target is a non-object');
24
+
25
+ return prop in target;
26
+ };
27
+
28
+ export const __Reflect_defineProperty = (target: any, prop: any, descriptor: any) => {
29
+ if (!Porffor.object.isObject(target)) throw new TypeError('Target is a non-object');
30
+ if (!Porffor.object.isObject(descriptor)) throw new TypeError('Descriptor is a non-object');
31
+
32
+ try {
33
+ Object.defineProperty(target, prop, descriptor);
34
+ return true;
35
+ } catch {
36
+ return false;
37
+ }
38
+ };
39
+
40
+ export const __Reflect_deleteProperty = (target: any, prop: any) => {
41
+ if (!Porffor.object.isObject(target)) throw new TypeError('Target is a non-object');
42
+
43
+ return delete target[prop];
44
+ };
45
+
46
+ export const __Reflect_getOwnPropertyDescriptor = (target: any, prop: any) => {
47
+ if (!Porffor.object.isObject(target)) throw new TypeError('Target is a non-object');
48
+
49
+ return Object.getOwnPropertyDescriptor(target, prop);
50
+ };
51
+
52
+ export const __Reflect_isExtensible = (target: any) => {
53
+ if (!Porffor.object.isObject(target)) throw new TypeError('Target is a non-object');
54
+
55
+ return Object.isExtensible(target);
56
+ };
57
+
58
+ export const __Reflect_preventExtensions = (target: any) => {
59
+ if (!Porffor.object.isObject(target)) throw new TypeError('Target is a non-object');
60
+
61
+ try {
62
+ Object.preventExtensions(target);
63
+ return true;
64
+ } catch {
65
+ return false;
66
+ }
67
+ };
68
+
69
+ export const __Reflect_ownKeys = (target: any) => {
70
+ if (!Porffor.object.isObject(target)) throw new TypeError('Target is a non-object');
71
+
72
+ const out: any[] = Porffor.allocate();
73
+
74
+ const t: i32 = Porffor.rawType(target);
75
+ if (t == Porffor.TYPES.object) {
76
+ let ptr: i32 = Porffor.wasm`local.get ${target}` + 5;
77
+ const endPtr: i32 = ptr + Porffor.wasm.i32.load(target, 0, 0) * 14;
78
+
79
+ let i: i32 = 0;
80
+ for (; ptr < endPtr; ptr += 14) {
81
+ let key: any;
82
+ Porffor.wasm`local raw i32
83
+ local msb i32
84
+ local.get ${ptr}
85
+ i32.to_u
86
+ i32.load 0 0
87
+ local.set raw
88
+
89
+ local.get raw
90
+ i32.const 30
91
+ i32.shr_u
92
+ local.tee msb
93
+ if 127
94
+ i32.const 5 ;; symbol
95
+ i32.const 67 ;; string
96
+ local.get msb
97
+ i32.const 3
98
+ i32.eq
99
+ select
100
+ local.set ${key+1}
101
+
102
+ local.get raw
103
+ i32.const 1073741823
104
+ i32.and ;; unset 2 MSBs
105
+ else
106
+ i32.const 195
107
+ local.set ${key+1}
108
+
109
+ local.get raw
110
+ end
111
+ i32.from_u
112
+ local.set ${key}`;
113
+
114
+ out[i++] = key;
115
+ }
116
+
117
+ out.length = i;
118
+ } else if (Porffor.fastOr(
119
+ t == Porffor.TYPES.array,
120
+ t == Porffor.TYPES.bytestring,
121
+ t == Porffor.TYPES.string
122
+ )) {
123
+ const len: i32 = target.length;
124
+ out.length = len;
125
+
126
+ for (let i: i32 = 0; i < len; i++) {
127
+ out[i] = __Number_prototype_toString(i);
128
+ }
129
+ }
130
+
131
+ return out;
132
+ };
@@ -39,7 +39,7 @@ const todo = (scope, msg, expectsValue = undefined) => {
39
39
  const isFuncType = type =>
40
40
  type === 'FunctionDeclaration' || type === 'FunctionExpression' || type === 'ArrowFunctionExpression';
41
41
  const hasFuncWithName = name =>
42
- Object.hasOwn(funcIndex, name) != null || Object.hasOwn(builtinFuncs, name) != null || Object.hasOwn(importedFuncs, name) != null || Object.hasOwn(internalConstrs, name) != null;
42
+ Object.hasOwn(funcIndex, name) || Object.hasOwn(builtinFuncs, name) || Object.hasOwn(importedFuncs, name) || Object.hasOwn(internalConstrs, name);
43
43
 
44
44
  const astCache = new WeakMap();
45
45
  const cacheAst = (decl, wasm) => {
@@ -164,6 +164,8 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
164
164
  return cacheAst(decl, generateMember(scope, decl, global, name));
165
165
 
166
166
  case 'ExportNamedDeclaration':
167
+ if (!decl.declaration) return todo(scope, 'unsupported export declaration');
168
+
167
169
  const funcsBefore = funcs.map(x => x.name);
168
170
  generate(scope, decl.declaration);
169
171
 
@@ -2835,14 +2837,20 @@ const generateVar = (scope, decl) => {
2835
2837
  scope.globalInits[name] = newOut;
2836
2838
  }
2837
2839
  }
2838
-
2839
- // hack: this follows spec properly but is mostly unneeded 😅
2840
- // out.push(...setType(scope, name, x.init ? getNodeType(scope, x.init) : TYPES.undefined));
2841
2840
  }
2842
2841
 
2843
2842
  return out;
2844
2843
  };
2845
2844
 
2845
+ const getMemberProperty = decl => {
2846
+ if (decl.computed) return decl.property;
2847
+
2848
+ return {
2849
+ type: 'Literal',
2850
+ value: decl.property.name
2851
+ };
2852
+ };
2853
+
2846
2854
  // todo: optimize this func for valueUnused
2847
2855
  const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2848
2856
  const { type, name } = decl.left;
@@ -2897,10 +2905,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2897
2905
  const pointerTmp = localTmp(scope, '#member_setter_ptr_tmp', Valtype.i32);
2898
2906
 
2899
2907
  const object = decl.left.object;
2900
- const property = decl.left.computed ? decl.left.property : {
2901
- type: 'Literal',
2902
- value: decl.left.property.name
2903
- };
2908
+ const property = getMemberProperty(decl.left);
2904
2909
 
2905
2910
  // todo/perf: use i32 object (and prop?) locals
2906
2911
  const objectWasm = [ [ Opcodes.local_get, localTmp(scope, '#member_obj') ] ];
@@ -3249,6 +3254,25 @@ const generateUnary = (scope, decl) => {
3249
3254
  }
3250
3255
 
3251
3256
  case 'delete': {
3257
+ if (decl.argument.type === 'MemberExpression') {
3258
+ const object = decl.argument.object;
3259
+ const property = getMemberProperty(decl.argument);
3260
+
3261
+ return [
3262
+ ...generate(scope, object),
3263
+ Opcodes.i32_to_u,
3264
+ ...getNodeType(scope, object),
3265
+
3266
+ ...generate(scope, property),
3267
+ ...getNodeType(scope, property),
3268
+ ...toPropertyKey(scope, true),
3269
+
3270
+ [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_delete').index) ],
3271
+ [ Opcodes.drop ],
3272
+ Opcodes.i32_from_u
3273
+ ];
3274
+ }
3275
+
3252
3276
  let toReturn = true, toGenerate = true;
3253
3277
 
3254
3278
  if (decl.argument.type === 'Identifier') {
@@ -3256,6 +3280,7 @@ const generateUnary = (scope, decl) => {
3256
3280
 
3257
3281
  // if ReferenceError (undeclared var), ignore and return true. otherwise false
3258
3282
  if (!out[1]) {
3283
+ // todo: throw in strict mode
3259
3284
  // exists
3260
3285
  toReturn = false;
3261
3286
  } else {
@@ -4654,20 +4679,29 @@ const generateMember = (scope, decl, _global, _name) => {
4654
4679
  return number(0);
4655
4680
  }
4656
4681
 
4682
+ const useTmp = !Prefs.lengthNoTmp;
4683
+ const tmp = useTmp && localTmp(scope, '#length_tmp', Valtype.i32);
4657
4684
  return [
4658
- ...out,
4659
- [ Opcodes.local_set, localTmp(scope, '#length_tmp', Valtype.i32) ],
4685
+ ...(useTmp ? [
4686
+ ...out,
4687
+ [ Opcodes.local_set, tmp ],
4688
+ ] : []),
4660
4689
 
4661
4690
  ...getNodeType(scope, decl.object),
4662
4691
  ...number(TYPE_FLAGS.length, Valtype.i32),
4663
4692
  [ Opcodes.i32_and ],
4664
4693
  [ Opcodes.if, valtypeBinary ],
4665
- [ Opcodes.local_get, localTmp(scope, '#length_tmp', Valtype.i32) ],
4694
+ ...(useTmp ? [ [ Opcodes.local_get, tmp ] ] : out),
4666
4695
  [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
4667
4696
  Opcodes.i32_from_u,
4668
4697
 
4669
4698
  ...setLastType(scope, TYPES.number),
4670
4699
  [ Opcodes.else ],
4700
+ ...(useTmp ? [] : [
4701
+ ...out,
4702
+ [ Opcodes.drop ]
4703
+ ]),
4704
+
4671
4705
  ...number(0),
4672
4706
  ...setLastType(scope, TYPES.undefined),
4673
4707
  [ Opcodes.end ]
@@ -4703,10 +4737,7 @@ const generateMember = (scope, decl, _global, _name) => {
4703
4737
  }
4704
4738
 
4705
4739
  const object = decl.object;
4706
- const property = decl.computed ? decl.property : {
4707
- type: 'Literal',
4708
- value: decl.property.name
4709
- };
4740
+ const property = getMemberProperty(decl);
4710
4741
 
4711
4742
  // todo/perf: use i32 object (and prop?) locals
4712
4743
  const objectWasm = [ [ Opcodes.local_get, localTmp(scope, '#member_obj') ] ];