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.
- package/compiler/assemble.js +34 -1
- package/compiler/builtins/array.ts +32 -1
- package/compiler/builtins/arraybuffer.ts +226 -1
- package/compiler/builtins/dataview.ts +261 -0
- package/compiler/builtins/porffor.d.ts +2 -0
- package/compiler/builtins/typedarray.js +58 -9
- package/compiler/builtins.js +6 -0
- package/compiler/codegen.js +3 -3
- package/compiler/generated_builtins.js +594 -231
- package/compiler/types.js +2 -0
- package/compiler/wasmSpec.js +1 -0
- package/compiler/wrap.js +33 -8
- package/package.json +1 -1
- package/runner/index.js +1 -1
@@ -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(
|
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 (
|
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('
|
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 >
|
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
|
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
|
-
|
151
|
+
const out: ${name} = Porffor.allocate();
|
103
152
|
|
104
153
|
if (start > end) return out;
|
105
154
|
|
package/compiler/builtins.js
CHANGED
package/compiler/codegen.js
CHANGED
@@ -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
|
}
|