porffor 0.20.6 → 0.20.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.
@@ -0,0 +1,131 @@
1
+ // @porf --valtype=i32
2
+ import type {} from './porffor.d.ts';
3
+
4
+ // memory layout:
5
+ // size (i32, 4)
6
+ // per entry (14):
7
+ // key - value, type MSB encoded (u32, 4)
8
+ // value - value (f64, 8)
9
+ // value - type + obj flag (u16, 2)
10
+ // flags:
11
+ // accessor - 0b0001
12
+ // configurable - 0b0010
13
+ // enumerable - 0b0100
14
+ // writable - 0b1000
15
+
16
+ export const __Porffor_object_lookup = (_this: object, target: any): i32 => {
17
+ const targetType: i32 = Porffor.wasm`local.get ${target+1}`;
18
+
19
+ let ptr: i32 = Porffor.wasm`local.get ${_this}` + 4;
20
+
21
+ const size: i32 = Porffor.wasm.i32.load(_this, 0, 0);
22
+ const endPtr: i32 = ptr + size * 14;
23
+
24
+ if (targetType == Porffor.TYPES.bytestring) {
25
+ const targetStr: bytestring = target;
26
+ for (; ptr < endPtr; ptr += 14) {
27
+ const keyRaw: i32 = Porffor.wasm.i32.load(ptr, 0, 0);
28
+ if (keyRaw == 0) break; // ran out of keys
29
+ if (keyRaw >>> 31) continue; // MSB set, regular string type
30
+
31
+ const keyStr: bytestring = keyRaw;
32
+ if (keyStr == targetStr) return ptr;
33
+ }
34
+ } else {
35
+ const targetStr: string = target;
36
+ for (; ptr < endPtr; ptr += 14) {
37
+ const keyRaw: i32 = Porffor.wasm.i32.load(ptr, 0, 0);
38
+ if (keyRaw == 0) break; // ran out of keys
39
+ if (keyRaw >>> 31) { // MSB set, regular string type
40
+ const keyStr: string = keyRaw & 0x7FFFFFFF; // unset MSB
41
+ if (keyStr == targetStr) return ptr;
42
+ }
43
+ }
44
+ }
45
+
46
+ return -1;
47
+ };
48
+
49
+ export const __Porffor_object_get = (_this: object, key: any): any => {
50
+ const entryPtr: i32 = __Porffor_object_lookup(_this, key);
51
+ if (entryPtr == -1) {
52
+ Porffor.wasm`
53
+ f64.const 0
54
+ i32.const 128
55
+ return`;
56
+ }
57
+
58
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
59
+
60
+ if (tail & 0b0001) {
61
+ // accessor descriptor
62
+ // todo
63
+
64
+ Porffor.wasm`
65
+ f64.const 0
66
+ i32.const 128
67
+ return`;
68
+ }
69
+
70
+ // data descriptor
71
+ Porffor.wasm`
72
+ local.get ${entryPtr}
73
+ f64.load 0 4
74
+ local.get ${tail}
75
+ i32.const 8
76
+ i32.shr_u
77
+ return`;
78
+ };
79
+
80
+ export const __Porffor_object_set = (_this: object, key: any, value: any): any => {
81
+ let entryPtr: i32 = __Porffor_object_lookup(_this, key);
82
+ let flags: i32;
83
+ if (entryPtr == -1) {
84
+ // add new entry
85
+ // bump size +1
86
+ const size: i32 = Porffor.wasm.i32.load(_this, 0, 0);
87
+ Porffor.wasm.i32.store(_this, size + 1, 0, 0);
88
+
89
+ // entryPtr = current end of object
90
+ entryPtr = Porffor.wasm`local.get ${_this}` + 4 + size * 14;
91
+
92
+ // encode key type, set MSB if regular string
93
+ let keyEnc: i32 = Porffor.wasm`local.get ${key}`;
94
+ if (Porffor.wasm`local.get ${key+1}` == Porffor.TYPES.string) keyEnc |= 0x80000000;
95
+
96
+ // write key value and type (MSB)
97
+ Porffor.wasm.i32.store(entryPtr, keyEnc, 0, 0);
98
+
99
+ // flags = writable, enumerable, configurable, not accessor
100
+ flags = 0b1110;
101
+ } else {
102
+ // existing entry, modify it
103
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
104
+
105
+ if (tail & 0b0001) {
106
+ // accessor descriptor
107
+ // todo
108
+
109
+ return value;
110
+ }
111
+
112
+ // data descriptor
113
+ if (!(tail & 0b1000)) {
114
+ // not writable, return now
115
+ return value;
116
+ }
117
+
118
+ // flags = same flags as before
119
+ flags = tail & 0xff;
120
+ }
121
+
122
+ // write new value value (lol)
123
+ Porffor.wasm.f64.store(entryPtr, value, 0, 4);
124
+
125
+ // write new tail (value type + flags)
126
+ Porffor.wasm.i32.store16(entryPtr,
127
+ flags + (Porffor.wasm`local.get ${value+1}` << 8),
128
+ 0, 12);
129
+
130
+ return value;
131
+ };
@@ -62,7 +62,7 @@ export const __Porffor_miniLog = (arg: any) => {
62
62
  } else {
63
63
  printStatic('[ ');
64
64
  for (let i: i32 = 0; i <= arrLen; i++) {
65
- __Porffor_miniPrint(arg[i]);
65
+ __Porffor_miniLog(arg[i]);
66
66
  if (i != arrLen) printStatic(', ');
67
67
  }
68
68
  printStatic(' ]');
@@ -2,8 +2,8 @@ export default () => {
2
2
  let out = '';
3
3
 
4
4
  const error = name => out += `export const ${name} = function (message: bytestring) {
5
- new.target;
6
- return Object();
5
+ new.target; // trick compiler into allowing as constructor
6
+ return {};
7
7
  };`;
8
8
 
9
9
  error('Error');
@@ -1,5 +1,19 @@
1
1
  import type {} from './porffor.d.ts';
2
2
 
3
+ export const Object = function (value: any): object {
4
+ new.target; // trick compiler into allowing as constructor
5
+
6
+ if (value == null) {
7
+ // if nullish, return new empty object
8
+ const obj: object = Porffor.allocate();
9
+ return obj;
10
+ }
11
+
12
+ // todo: turn primitive args into objects
13
+ // return input
14
+ return value;
15
+ };
16
+
3
17
  export const __Object_keys = (obj: any): any[] => {
4
18
  if (obj == null) throw new TypeError('Argument is nullish, expected object');
5
19
 
@@ -7,13 +21,46 @@ export const __Object_keys = (obj: any): any[] => {
7
21
 
8
22
  const t: i32 = Porffor.rawType(obj);
9
23
  if (t == Porffor.TYPES.object) {
10
- const keys: Set = Porffor.wasm.i32.load(obj, 0, 0);
11
- const size: i32 = Porffor.wasm.i32.load(keys, 0, 0);
12
- out.length = size;
13
-
14
- for (let i: i32 = 0; i < size; i++) {
15
- out[i] = Porffor.set.read(keys, i);
24
+ const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
25
+ let len: i32 = size;
26
+
27
+ let ptr: i32 = Porffor.wasm`local.get ${obj}` + 4;
28
+ const endPtr: i32 = ptr + size * 14;
29
+
30
+ let i: i32 = 0;
31
+ for (; ptr < endPtr; ptr += 14) {
32
+ // todo: check enumerable flag
33
+
34
+ let key: any;
35
+ Porffor.wasm`local raw i32
36
+ local.get ${ptr}
37
+ i32.to_u
38
+ i32.load 0 0
39
+ local.set raw
40
+
41
+ local.get raw
42
+ i32.const 31
43
+ i32.shr_u
44
+ if 127
45
+ i32.const 67
46
+ local.set ${key+1}
47
+
48
+ local.get raw
49
+ i32.const 2147483647
50
+ i32.and
51
+ else
52
+ i32.const 195
53
+ local.set ${key+1}
54
+
55
+ local.get raw
56
+ end
57
+ i32.from_u
58
+ local.set ${key}`;
59
+
60
+ out[i++] = key;
16
61
  }
62
+
63
+ out.length = len;
17
64
  } else if (Porffor.fastOr(
18
65
  t == Porffor.TYPES.array,
19
66
  t == Porffor.TYPES.bytestring,
@@ -37,13 +84,33 @@ export const __Object_values = (obj: any): any[] => {
37
84
 
38
85
  const t: i32 = Porffor.rawType(obj);
39
86
  if (t == Porffor.TYPES.object) {
40
- const size: i32 = Porffor.wasm.i32.load(Porffor.wasm.i32.load(obj, 0, 0), 0, 0);
41
- const vals: any[] = Porffor.wasm.i32.load(obj, 0, 4);
87
+ const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
88
+ let len: i32 = size;
42
89
 
43
- out.length = size;
44
- for (let i: i32 = 0; i < size; i++) {
45
- out[i] = vals[i];
90
+ let ptr: i32 = Porffor.wasm`local.get ${obj}` + 4;
91
+ const endPtr: i32 = ptr + size * 14;
92
+
93
+ let i: i32 = 0;
94
+ for (; ptr < endPtr; ptr += 14) {
95
+ // todo: check enumerable flag
96
+
97
+ let val: any;
98
+ Porffor.wasm`local ptr32 i32
99
+ local.get ${ptr}
100
+ i32.to_u
101
+ local.tee ptr32
102
+
103
+ f64.load 0 4
104
+ local.set ${val}
105
+
106
+ local.get ptr32
107
+ i32.load8_u 0 13
108
+ local.set ${val+1}`;
109
+
110
+ out[i++] = val;
46
111
  }
112
+
113
+ out.length = len;
47
114
  } else if (Porffor.fastOr(
48
115
  t == Porffor.TYPES.array,
49
116
  t == Porffor.TYPES.bytestring,
@@ -83,14 +150,24 @@ export const __Object_entries = (obj: any): any[] => {
83
150
  return out;
84
151
  };
85
152
 
153
+ export const __Object_fromEntries = (iterable: any): object => {
154
+ const out: object = {};
155
+
156
+ for (const x of iterable) {
157
+ if (Porffor.rawType(x) < 0x06) throw new TypeError('Iterator contains non-object');
158
+ out[ecma262.ToPropertyKey(x[0])] = x[1];
159
+ }
160
+
161
+ return out;
162
+ };
163
+
86
164
 
87
165
  export const __Object_prototype_hasOwnProperty = (_this: any, prop: any) => {
88
166
  const p: any = ecma262.ToPropertyKey(prop);
89
167
 
90
168
  const t: i32 = Porffor.rawType(_this);
91
169
  if (t == Porffor.TYPES.object) {
92
- const keys: Set = Porffor.wasm.i32.load(_this, 0, 0);
93
- return __Set_prototype_has(keys, p);
170
+ return __Porffor_object_lookup(_this, prop) != -1;
94
171
  }
95
172
 
96
173
  const keys: any[] = __Object_keys(_this);
@@ -103,6 +180,23 @@ export const __Object_hasOwn = (obj: any, prop: any) => {
103
180
  };
104
181
 
105
182
 
183
+ export const __Object_assign = (target: any, ...sources: any[]) => {
184
+ if (target == null) throw new TypeError('Argument is nullish, expected object');
185
+
186
+ for (const x of sources) {
187
+ const keys: any[] = __Object_keys(x);
188
+ const vals: any[] = __Object_values(x);
189
+
190
+ const len: i32 = keys.length;
191
+ for (let i: i32 = 0; i < len; i++) {
192
+ target[keys[i]] = vals[i];
193
+ }
194
+ }
195
+
196
+ return target;
197
+ };
198
+
199
+
106
200
  export const __Object_prototype_toString = (_this: object) => {
107
201
  let out: bytestring = '[object Object]';
108
202
  return out;
@@ -1,17 +1,6 @@
1
1
  import type {} from './porffor.d.ts';
2
2
 
3
3
  // dark wasm magic for dealing with memory, sorry.
4
- export const __Porffor_allocate = (): number => {
5
- Porffor.wasm`
6
- i32.const 1
7
- memory.grow 0
8
- i32.const 65536
9
- i32.mul
10
- i32.from_u
11
- i32.const 1
12
- return`;
13
- };
14
-
15
4
  export const __Porffor_set_read = (_this: Set, index: number): any => {
16
5
  Porffor.wasm`
17
6
  local offset i32
@@ -184,10 +173,7 @@ export const Set = function (iterable: any): Set {
184
173
 
185
174
  const out: Set = __Porffor_allocate();
186
175
 
187
- if (Porffor.fastAnd(
188
- Porffor.rawType(iterable) != Porffor.TYPES.undefined,
189
- iterable !== null
190
- )) for (const x of iterable) {
176
+ if (iterable != null) for (const x of iterable) {
191
177
  __Set_prototype_add(out, x);
192
178
  }
193
179
 
@@ -3,7 +3,7 @@ import type {} from './porffor.d.ts';
3
3
  export const WeakRef = function (target: any): WeakRef {
4
4
  if (!new.target) throw new TypeError("Constructor WeakRef requires 'new'");
5
5
 
6
- if (Porffor.rawType(target) < 0x04) throw new TypeError('Target for WeakRef needs to be an object or symbol');
6
+ if (Porffor.rawType(target) < 0x05) throw new TypeError('Target for WeakRef needs to be an object or symbol');
7
7
 
8
8
  const out: WeakRef = Porffor.allocateBytes(9);
9
9
 
@@ -26,7 +26,6 @@ export const __ecma262_ToIntegerOrInfinity = (argument: unknown): number => {
26
26
  // 7.1.17 ToString (argument)
27
27
  // https://tc39.es/ecma262/#sec-tostring
28
28
  export const __ecma262_ToString = (argument: unknown): bytestring => {
29
- let out: bytestring = Porffor.allocate();
30
29
  const type: i32 = Porffor.rawType(argument);
31
30
 
32
31
  // 1. If argument is a String, return argument.
@@ -37,6 +36,8 @@ export const __ecma262_ToString = (argument: unknown): bytestring => {
37
36
  // 2. If argument is a Symbol, throw a TypeError exception.
38
37
  if (type == Porffor.TYPES.symbol) throw new TypeError('Cannot convert a Symbol value to a string');
39
38
 
39
+ let out: bytestring = Porffor.allocate();
40
+
40
41
  // 3. If argument is undefined, return "undefined".
41
42
  if (Porffor.fastOr(
42
43
  type == Porffor.TYPES.undefined,
@@ -68,14 +69,14 @@ export const __ecma262_ToString = (argument: unknown): bytestring => {
68
69
  // https://tc39.es/ecma262/#sec-topropertykey
69
70
  export const __ecma262_ToPropertyKey = (argument: any): any => {
70
71
  // 1. Let key be ? ToPrimitive(argument, string).
71
- const key: any = argument;
72
+ // argument = key
72
73
 
73
74
  // 2. If key is a Symbol, then
74
- if (Porffor.rawType(key) == Porffor.TYPES.symbol) {
75
+ if (Porffor.rawType(argument) == Porffor.TYPES.symbol) {
75
76
  // a. Return key.
76
- return key;
77
+ return argument;
77
78
  }
78
79
 
79
80
  // 3. Return ! ToString(key).
80
- return __ecma262_ToString(key);
81
+ return __ecma262_ToString(argument);
81
82
  };
@@ -97,10 +97,8 @@ export const Map = function (iterable: any): Map {
97
97
  const vals: any[] = Porffor.allocate();
98
98
  Porffor.wasm.i32.store(out, vals, 0, 4);
99
99
 
100
- if (Porffor.fastAnd(
101
- Porffor.rawType(iterable) != Porffor.TYPES.undefined,
102
- iterable !== null
103
- )) for (const x of iterable) {
100
+ if (iterable != null) for (const x of iterable) {
101
+ if (Porffor.rawType(x) < 0x06) throw new TypeError('Iterator contains non-object');
104
102
  __Map_prototype_set(out, x[0], x[1]);
105
103
  }
106
104
 
@@ -3,7 +3,7 @@ import type {} from './porffor.d.ts';
3
3
  export const __WeakMap_prototype_has = (_this: WeakMap, key: any) => __Map_prototype_has(_this, key);
4
4
 
5
5
  export const __WeakMap_prototype_set = (_this: WeakMap, key: any, value: any) => {
6
- if (Porffor.rawType(key) < 0x04) throw new TypeError('Value in WeakSet needs to be an object or symbol');
6
+ if (Porffor.rawType(key) < 0x05) throw new TypeError('Value in WeakSet needs to be an object or symbol');
7
7
 
8
8
  __Map_prototype_set(_this, key, value);
9
9
  return _this;
@@ -22,10 +22,8 @@ export const WeakMap = function (iterable: any): WeakMap {
22
22
  const vals: any[] = Porffor.allocate();
23
23
  Porffor.wasm.i32.store(out, vals, 0, 4);
24
24
 
25
- if (Porffor.fastAnd(
26
- Porffor.rawType(iterable) != Porffor.TYPES.undefined,
27
- iterable !== null
28
- )) for (const x of iterable) {
25
+ if (iterable != null) for (const x of iterable) {
26
+ if (Porffor.rawType(x) < 0x06) throw new TypeError('Iterator contains non-object');
29
27
  __WeakMap_prototype_set(out, x[0], x[1]);
30
28
  }
31
29
 
@@ -3,7 +3,7 @@ import type {} from './porffor.d.ts';
3
3
  export const __WeakSet_prototype_has = (_this: WeakSet, value: any) => __Set_prototype_has(_this, value);
4
4
 
5
5
  export const __WeakSet_prototype_add = (_this: WeakSet, value: any) => {
6
- if (Porffor.rawType(value) < 0x04) throw new TypeError('Value in WeakSet needs to be an object or symbol');
6
+ if (Porffor.rawType(value) < 0x05) throw new TypeError('Value in WeakSet needs to be an object or symbol');
7
7
 
8
8
  __Set_prototype_add(_this, value);
9
9
  return _this;
@@ -16,10 +16,7 @@ export const WeakSet = function (iterable: any): WeakSet {
16
16
 
17
17
  const out: WeakSet = __Porffor_allocate();
18
18
 
19
- if (Porffor.fastAnd(
20
- Porffor.rawType(iterable) != Porffor.TYPES.undefined,
21
- iterable !== null
22
- )) for (const x of iterable) {
19
+ if (iterable != null) for (const x of iterable) {
23
20
  __WeakSet_prototype_add(out, x);
24
21
  }
25
22
 
@@ -248,19 +248,6 @@ export const BuiltinFuncs = function() {
248
248
  constr: true
249
249
  };
250
250
 
251
- // just return given (default 0) for (new) Object() as we somewhat supports object just not constructor
252
- this.Object = {
253
- params: [ valtypeBinary ],
254
- locals: [],
255
- returns: [ valtypeBinary ],
256
- returnType: TYPES.object,
257
- wasm: [
258
- // [ Opcodes.local_get, 0 ]
259
- ...number(1)
260
- ],
261
- constr: true
262
- };
263
-
264
251
  this.isNaN = {
265
252
  floatOnly: true,
266
253
  params: [ valtypeBinary ],
@@ -427,7 +414,7 @@ export const BuiltinFuncs = function() {
427
414
  returnType: TYPES.number,
428
415
  wasm: [
429
416
  [ Opcodes.local_get, 0 ],
430
- Opcodes.i32_trunc_sat_f64_u,
417
+ Opcodes.i32_to_u,
431
418
  [ Opcodes.i32_clz ],
432
419
  Opcodes.i32_from
433
420
  ]
@@ -455,9 +442,9 @@ export const BuiltinFuncs = function() {
455
442
  returnType: TYPES.number,
456
443
  wasm: [
457
444
  [ Opcodes.local_get, 0 ],
458
- Opcodes.i32_trunc_sat_f64_s,
445
+ Opcodes.i32_to,
459
446
  [ Opcodes.local_get, 1 ],
460
- Opcodes.i32_trunc_sat_f64_s,
447
+ Opcodes.i32_to,
461
448
  [ Opcodes.i32_mul ],
462
449
  Opcodes.i32_from
463
450
  ]
@@ -980,6 +967,19 @@ export const BuiltinFuncs = function() {
980
967
  ]
981
968
  };
982
969
 
970
+ this.__Porffor_allocate = {
971
+ params: [],
972
+ locals: [],
973
+ returns: [ Valtype.i32 ],
974
+ returnType: TYPES.number,
975
+ wasm: [
976
+ ...number(1, Valtype.i32),
977
+ [ Opcodes.memory_grow, 0 ],
978
+ ...number(65536, Valtype.i32),
979
+ [ Opcodes.i32_mul ]
980
+ ]
981
+ };
982
+
983
983
  this.__Porffor_allocateBytes = {
984
984
  params: [ Valtype.i32 ],
985
985
  locals: [],