porffor 0.18.22 → 0.18.24

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.
@@ -6,31 +6,39 @@ export default async () => {
6
6
 
7
7
  // TypedArrays are stored like this in memory:
8
8
  // length (i32)
9
- // bufferPtr (i32)
9
+ // bufferPtr (i32) - buffer + byteOffset
10
+ // byteOffset (i32) - only used for getter
10
11
 
11
12
  const constr = name => out += `export const ${name} = function (arg: any, byteOffset: any, length: any): ${name} {
12
13
  if (!new.target) throw new TypeError("Constructor ${name} requires 'new'");
13
14
 
14
- const out: ${name} = Porffor.allocateBytes(8);
15
+ const out: ${name} = Porffor.allocateBytes(12);
15
16
  const outPtr: i32 = Porffor.wasm\`local.get \${out}\`;
16
17
 
17
18
  let len: i32 = 0;
18
19
  let bufferPtr: i32;
19
20
 
20
21
  const type: i32 = Porffor.rawType(arg);
21
- if (type == Porffor.TYPES.arraybuffer) {
22
+ if (Porffor.fastOr(
23
+ type == Porffor.TYPES.arraybuffer,
24
+ type == Porffor.TYPES.sharedarraybuffer
25
+ )) {
22
26
  bufferPtr = Porffor.wasm\`local.get \${arg}\`;
23
27
 
28
+ if (arg.detached) throw new TypeError('Constructed ${name} with a detached ArrayBuffer');
29
+
24
30
  let offset: i32 = 0;
25
31
  if (Porffor.rawType(byteOffset) != Porffor.TYPES.undefined) offset = Math.trunc(byteOffset);
32
+ if (offset < 0) throw new RangeError('Invalid DataView byte offset (negative)');
26
33
 
34
+ Porffor.wasm.i32.store(outPtr, offset, 0, 8);
27
35
  Porffor.wasm.i32.store(outPtr, bufferPtr + offset, 0, 4);
28
36
 
29
37
  if (Porffor.rawType(length) == Porffor.TYPES.undefined) {
30
38
  const bufferLen: i32 = Porffor.wasm.i32.load(bufferPtr, 0, 0);
31
39
  len = (bufferLen - byteOffset) / ${name}.BYTES_PER_ELEMENT;
32
40
 
33
- if (!Number.isInteger(len)) throw new RangeError('byte length of ${name} should be divisible by BYTES_PER_ELEMENT');
41
+ if (!Number.isInteger(len)) throw new RangeError('Byte length of ${name} should be divisible by BYTES_PER_ELEMENT');
34
42
  } else len = Math.trunc(length);
35
43
  } else {
36
44
  bufferPtr = Porffor.allocate();
@@ -39,7 +47,8 @@ export default async () => {
39
47
  if (Porffor.fastOr(
40
48
  type == Porffor.TYPES.array,
41
49
  type == Porffor.TYPES.string, type == Porffor.TYPES.bytestring,
42
- type == Porffor.TYPES.set
50
+ type == Porffor.TYPES.set,
51
+ Porffor.fastAnd(type >= Porffor.TYPES.uint8array, type <= Porffor.TYPES.float64array)
43
52
  )) {
44
53
  let i: i32 = 0;
45
54
  for (const x of arg) {
@@ -54,19 +63,59 @@ export default async () => {
54
63
  }
55
64
 
56
65
  if (len < 0) throw new RangeError('Invalid TypedArray length (negative)');
57
- if (len > 34359738368) throw new RangeError('Invalid TypedArray length (>32GiB)');
66
+ if (len > 4294967295) throw new RangeError('Invalid ArrayBuffer length (over 32 bit address space)');
58
67
 
59
68
  Porffor.wasm.i32.store(outPtr, len, 0, 0);
60
69
  return out;
61
70
  };
62
71
 
72
+ export const __${name}_of = (...items: any[]): ${name} => new ${name}(items);
73
+
74
+ export const __${name}_from = (arg: any, mapFn: any): ${name} => {
75
+ const arr: any[] = Porffor.allocate();
76
+ let len: i32 = 0;
77
+
78
+ const type = Porffor.rawType(arg);
79
+ if (Porffor.fastOr(
80
+ type == Porffor.TYPES.array,
81
+ type == Porffor.TYPES.string, type == Porffor.TYPES.bytestring,
82
+ type == Porffor.TYPES.set,
83
+ Porffor.fastAnd(type >= Porffor.TYPES.uint8array, type <= Porffor.TYPES.float64array)
84
+ )) {
85
+ const hasMapFn = Porffor.rawType(mapFn) != Porffor.TYPES.undefined;
86
+
87
+ let i: i32 = 0;
88
+ if (hasMapFn) {
89
+ if (Porffor.rawType(mapFn) != Porffor.TYPES.function) throw new TypeError('Called Array.from with a non-function mapFn');
90
+
91
+ for (const x of arg) {
92
+ arr[i] = mapFn(x, i);
93
+ i++;
94
+ }
95
+ } else {
96
+ for (const x of arg) {
97
+ arr[i++] = x;
98
+ }
99
+ }
100
+ len = i;
101
+ }
102
+
103
+ arr.length = len;
104
+
105
+ return new ${name}(arr);
106
+ };
107
+
63
108
  export const __${name}_prototype_buffer$get = (_this: ${name}) => {
64
- const out: ArrayBuffer = Porffor.wasm.i32.load(_this, 0, 4);
109
+ const out: ArrayBuffer = Porffor.wasm.i32.load(_this, 0, 4) - Porffor.wasm.i32.load(_this, 0, 8);
65
110
  return out;
66
111
  };
67
112
 
68
113
  export const __${name}_prototype_byteLength$get = (_this: ${name}) => {
69
- return _this.length * ${name}.BYTES_PER_ELEMENT;
114
+ return Porffor.wasm.i32.load(_this, 0, 0) * ${name}.BYTES_PER_ELEMENT;
115
+ };
116
+
117
+ export const __${name}_prototype_byteOffset$get = (_this: ${name}) => {
118
+ return Porffor.wasm.i32.load(_this, 0, 8);
70
119
  };
71
120
 
72
121
  export const __${name}_prototype_at = (_this: ${name}, index: number) => {
@@ -99,7 +148,7 @@ export const __${name}_prototype_slice = (_this: ${name}, start: number, end: nu
99
148
  }
100
149
  if (end > len) end = len;
101
150
 
102
- let out: ${name} = Porffor.allocate();
151
+ const out: ${name} = Porffor.allocate();
103
152
 
104
153
  if (start > end) return out;
105
154
 
@@ -52,6 +52,12 @@ export const importedFuncs = [
52
52
  import: 'q',
53
53
  params: 2,
54
54
  returns: 1
55
+ },
56
+ {
57
+ name: 'debugger',
58
+ import: 'b',
59
+ params: 0,
60
+ returns: 0,
55
61
  }
56
62
  ];
57
63
 
@@ -137,7 +137,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
137
137
 
138
138
  case 'DebuggerStatement':
139
139
  // todo: hook into terminal debugger
140
- return [];
140
+ return [[ Opcodes.call, importedFuncs.debugger ]];
141
141
 
142
142
  case 'ArrayExpression':
143
143
  return generateArray(scope, decl, global, name);
@@ -4233,7 +4233,7 @@ const generateMember = (scope, decl, _global, _name) => {
4233
4233
  }
4234
4234
 
4235
4235
  // todo: generate this array procedurally during builtinFuncs creation
4236
- if (['size', 'description', 'byteLength', 'buffer'].includes(decl.property.name)) {
4236
+ if (['size', 'description', 'byteLength', 'byteOffset', 'buffer', 'detached', 'resizable', 'growable', 'maxByteLength'].includes(decl.property.name)) {
4237
4237
  const bc = {};
4238
4238
  const cands = Object.keys(builtinFuncs).filter(x => x.startsWith('__') && x.endsWith('_prototype_' + decl.property.name + '$get'));
4239
4239
 
@@ -4441,7 +4441,7 @@ const objectHack = node => {
4441
4441
  if (!objectName) objectName = objectHack(node.object)?.name?.slice?.(2);
4442
4442
 
4443
4443
  // if .name or .length, give up (hack within a hack!)
4444
- if (['name', 'length', 'size', 'description', 'byteLength', 'buffer'].includes(node.property.name)) {
4444
+ if (['name', 'length', 'size', 'description', 'byteLength', 'byteOffset', 'buffer', 'detached', 'resizable', 'growable', 'maxByteLength'].includes(node.property.name)) {
4445
4445
  node.object = objectHack(node.object);
4446
4446
  return;
4447
4447
  }