porffor 0.59.2 → 0.59.3
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/builtins/regexp.ts +1 -1
- package/compiler/builtins/typedarray.js +2 -3
- package/compiler/builtins/uint8array_base64.ts +634 -0
- package/compiler/builtins_precompiled.js +1247 -1194
- package/compiler/codegen.js +88 -86
- package/compiler/index.js +0 -3
- package/compiler/precompile.js +1 -1
- package/package.json +1 -1
- package/runtime/index.js +1 -1
- package/AGENT.md +0 -22
@@ -1349,7 +1349,7 @@ export const __RegExp_prototype_toString = (_this: RegExp) => {
|
|
1349
1349
|
};
|
1350
1350
|
|
1351
1351
|
|
1352
|
-
export const RegExp = function (pattern: any, flags: any
|
1352
|
+
export const RegExp = function (pattern: any, flags: any): RegExp {
|
1353
1353
|
let patternSrc, flagsSrc;
|
1354
1354
|
if (Porffor.type(pattern) === Porffor.TYPES.regexp) {
|
1355
1355
|
patternSrc = __RegExp_prototype_source$get(pattern);
|
@@ -102,9 +102,8 @@ export const __${name}_from = (arg: any, mapFn: any): ${name} => {
|
|
102
102
|
return new ${name}(arr);
|
103
103
|
};
|
104
104
|
|
105
|
-
export const __${name}_prototype_buffer$get = (_this: ${name}) => {
|
106
|
-
|
107
|
-
return out;
|
105
|
+
export const __${name}_prototype_buffer$get = (_this: ${name}): any|ArrayBuffer => {
|
106
|
+
return Porffor.wasm.i32.load(_this, 0, 4) - Porffor.wasm.i32.load(_this, 0, 8) as ArrayBuffer;
|
108
107
|
};
|
109
108
|
|
110
109
|
export const __${name}_prototype_byteLength$get = (_this: ${name}) => {
|
@@ -0,0 +1,634 @@
|
|
1
|
+
// @porf --valtype=i32
|
2
|
+
import type {} from './porffor.d.ts';
|
3
|
+
|
4
|
+
export const __Porffor_uint8array_validate = (ta: any) => {
|
5
|
+
if (Porffor.type(ta) != Porffor.TYPES.uint8array) {
|
6
|
+
throw new TypeError('Method called on incompatible receiver');
|
7
|
+
}
|
8
|
+
|
9
|
+
if (Porffor.wasm.i32.load(Porffor.wasm.i32.load(Porffor.wasm`local.get ${ta}`, 0, 4), 0, 0) == 4294967295) {
|
10
|
+
throw new TypeError('Uint8Array has a detached ArrayBuffer');
|
11
|
+
}
|
12
|
+
};
|
13
|
+
|
14
|
+
export const __Uint8Array_prototype_toBase64 = (_this: Uint8Array, options: any = undefined) => {
|
15
|
+
let alphabet: string = 'base64';
|
16
|
+
let omitPadding: boolean = false;
|
17
|
+
|
18
|
+
if (Porffor.type(options) != Porffor.TYPES.undefined) {
|
19
|
+
if (Porffor.type(options) != Porffor.TYPES.object) {
|
20
|
+
throw new TypeError('Options must be an object');
|
21
|
+
}
|
22
|
+
|
23
|
+
const alphabetProp: any = options.alphabet;
|
24
|
+
if (Porffor.type(alphabetProp) != Porffor.TYPES.undefined) {
|
25
|
+
alphabet = alphabetProp;
|
26
|
+
}
|
27
|
+
|
28
|
+
const paddingProp: any = options.omitPadding;
|
29
|
+
if (Porffor.type(paddingProp) != Porffor.TYPES.undefined) {
|
30
|
+
omitPadding = !!paddingProp;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
if (!Porffor.strcmp(alphabet, 'base64') && !Porffor.strcmp(alphabet, 'base64url')) {
|
35
|
+
throw new TypeError('Invalid alphabet');
|
36
|
+
}
|
37
|
+
|
38
|
+
__Porffor_uint8array_validate(_this);
|
39
|
+
const taPtr: i32 = Porffor.wasm`local.get ${_this}`;
|
40
|
+
const len: i32 = Porffor.wasm.i32.load(taPtr, 0, 0);
|
41
|
+
const bufferPtr: i32 = Porffor.wasm.i32.load(taPtr, 0, 4);
|
42
|
+
|
43
|
+
const output: bytestring = Porffor.allocate();
|
44
|
+
const outPtr: i32 = Porffor.wasm`local.get ${output}`;
|
45
|
+
|
46
|
+
let alphabetStr: bytestring;
|
47
|
+
if (Porffor.strcmp(alphabet, 'base64url')) {
|
48
|
+
alphabetStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
49
|
+
} else {
|
50
|
+
alphabetStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
51
|
+
}
|
52
|
+
const alphabetPtr: i32 = Porffor.wasm`local.get ${alphabetStr}`;
|
53
|
+
|
54
|
+
let i: i32 = 0;
|
55
|
+
let j: i32 = outPtr;
|
56
|
+
|
57
|
+
const fullChunks: i32 = (len / 3) * 3;
|
58
|
+
while (i < fullChunks) {
|
59
|
+
const b1: i32 = Porffor.wasm.i32.load8_u(bufferPtr + i++, 0, 4);
|
60
|
+
const b2: i32 = Porffor.wasm.i32.load8_u(bufferPtr + i++, 0, 4);
|
61
|
+
const b3: i32 = Porffor.wasm.i32.load8_u(bufferPtr + i++, 0, 4);
|
62
|
+
|
63
|
+
const enc1: i32 = b1 >> 2;
|
64
|
+
const enc2: i32 = ((b1 & 3) << 4) | (b2 >> 4);
|
65
|
+
const enc3: i32 = ((b2 & 15) << 2) | (b3 >> 6);
|
66
|
+
const enc4: i32 = b3 & 63;
|
67
|
+
|
68
|
+
Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(alphabetPtr + enc1, 0, 4), 0, 4);
|
69
|
+
Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(alphabetPtr + enc2, 0, 4), 0, 4);
|
70
|
+
Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(alphabetPtr + enc3, 0, 4), 0, 4);
|
71
|
+
Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(alphabetPtr + enc4, 0, 4), 0, 4);
|
72
|
+
}
|
73
|
+
|
74
|
+
const remaining: i32 = len - i;
|
75
|
+
if (remaining == 1) {
|
76
|
+
const b1: i32 = Porffor.wasm.i32.load8_u(bufferPtr + i, 0, 4);
|
77
|
+
const enc1: i32 = b1 >> 2;
|
78
|
+
const enc2: i32 = (b1 & 3) << 4;
|
79
|
+
|
80
|
+
Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(alphabetPtr + enc1, 0, 4), 0, 4);
|
81
|
+
Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(alphabetPtr + enc2, 0, 4), 0, 4);
|
82
|
+
if (!omitPadding) {
|
83
|
+
Porffor.wasm.i32.store8(j++, 61, 0, 4); // '='
|
84
|
+
Porffor.wasm.i32.store8(j++, 61, 0, 4); // '='
|
85
|
+
}
|
86
|
+
} else if (remaining == 2) {
|
87
|
+
const b1: i32 = Porffor.wasm.i32.load8_u(bufferPtr + i, 0, 4);
|
88
|
+
const b2: i32 = Porffor.wasm.i32.load8_u(bufferPtr + i + 1, 0, 4);
|
89
|
+
const enc1: i32 = b1 >> 2;
|
90
|
+
const enc2: i32 = ((b1 & 3) << 4) | (b2 >> 4);
|
91
|
+
const enc3: i32 = (b2 & 15) << 2;
|
92
|
+
|
93
|
+
Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(alphabetPtr + enc1, 0, 4), 0, 4);
|
94
|
+
Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(alphabetPtr + enc2, 0, 4), 0, 4);
|
95
|
+
Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(alphabetPtr + enc3, 0, 4), 0, 4);
|
96
|
+
if (!omitPadding) {
|
97
|
+
Porffor.wasm.i32.store8(j++, 61, 0, 4); // '='
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
output.length = j - Porffor.wasm`local.get ${output}`;
|
102
|
+
return output;
|
103
|
+
};
|
104
|
+
|
105
|
+
export const __Uint8Array_prototype_toHex = (_this: Uint8Array) => {
|
106
|
+
__Porffor_uint8array_validate(_this);
|
107
|
+
const taPtr: i32 = Porffor.wasm`local.get ${_this}`;
|
108
|
+
const len: i32 = Porffor.wasm.i32.load(taPtr, 0, 0);
|
109
|
+
const bufferPtr: i32 = Porffor.wasm.i32.load(taPtr, 0, 4);
|
110
|
+
|
111
|
+
const output: bytestring = Porffor.allocate();
|
112
|
+
const outPtr: i32 = Porffor.wasm`local.get ${output}`;
|
113
|
+
|
114
|
+
const hexChars: bytestring = '0123456789abcdef';
|
115
|
+
const hexPtr: i32 = Porffor.wasm`local.get ${hexChars}`;
|
116
|
+
|
117
|
+
let i: i32 = 0;
|
118
|
+
let j: i32 = outPtr;
|
119
|
+
while (i < len) {
|
120
|
+
const byte: i32 = Porffor.wasm.i32.load8_u(bufferPtr + i++, 0, 4);
|
121
|
+
Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(hexPtr + (byte >> 4), 0, 4), 0, 4);
|
122
|
+
Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(hexPtr + (byte & 15), 0, 4), 0, 4);
|
123
|
+
}
|
124
|
+
|
125
|
+
output.length = j - Porffor.wasm`local.get ${output}`;
|
126
|
+
return output;
|
127
|
+
};
|
128
|
+
|
129
|
+
// Returns packed: (charsRead << 16) | bytesWritten
|
130
|
+
export const __Porffor_fromBase64 = (str: any, alphabet: any, lastChunkHandling: any, destPtr: i32, maxLength: i32) => {
|
131
|
+
const strPtr: i32 = Porffor.wasm`local.get ${str}`;
|
132
|
+
const strLen: i32 = str.length;
|
133
|
+
|
134
|
+
if (!Porffor.strcmp(alphabet, 'base64') && !Porffor.strcmp(alphabet, 'base64url')) {
|
135
|
+
throw new TypeError('Invalid alphabet');
|
136
|
+
}
|
137
|
+
|
138
|
+
const isBase64Url: boolean = Porffor.strcmp(alphabet, 'base64url');
|
139
|
+
|
140
|
+
let j: i32 = destPtr;
|
141
|
+
|
142
|
+
let i: i32 = 0;
|
143
|
+
while (i < strLen) {
|
144
|
+
let c1: i32 = 0, c2: i32 = 0, c3: i32 = 0, c4: i32 = 0;
|
145
|
+
let chunkLength: i32 = 0;
|
146
|
+
let chunkStartPos: i32 = i;
|
147
|
+
|
148
|
+
while (i < strLen) {
|
149
|
+
const ch: i32 = Porffor.wasm.i32.load8_u(strPtr + i++, 0, 4);
|
150
|
+
if (ch >= 65 && ch <= 90) { // A-Z
|
151
|
+
c1 = ch - 65;
|
152
|
+
chunkLength = 1;
|
153
|
+
break;
|
154
|
+
}
|
155
|
+
if (ch >= 97 && ch <= 122) { // a-z
|
156
|
+
c1 = ch - 71;
|
157
|
+
chunkLength = 1;
|
158
|
+
break;
|
159
|
+
}
|
160
|
+
if (ch >= 48 && ch <= 57) { // 0-9
|
161
|
+
c1 = ch + 4;
|
162
|
+
chunkLength = 1;
|
163
|
+
break;
|
164
|
+
}
|
165
|
+
if (ch == 43) { // +
|
166
|
+
if (isBase64Url) {
|
167
|
+
throw new SyntaxError('Invalid base64url character');
|
168
|
+
}
|
169
|
+
c1 = 62;
|
170
|
+
chunkLength = 1;
|
171
|
+
break;
|
172
|
+
}
|
173
|
+
if (ch == 47) { // /
|
174
|
+
if (isBase64Url) {
|
175
|
+
throw new SyntaxError('Invalid base64url character');
|
176
|
+
}
|
177
|
+
c1 = 63;
|
178
|
+
chunkLength = 1;
|
179
|
+
break;
|
180
|
+
}
|
181
|
+
if (ch == 45) { // -
|
182
|
+
if (!isBase64Url) {
|
183
|
+
throw new SyntaxError('Invalid base64 character');
|
184
|
+
}
|
185
|
+
c1 = 62;
|
186
|
+
chunkLength = 1;
|
187
|
+
break;
|
188
|
+
}
|
189
|
+
if (ch == 95) { // _
|
190
|
+
if (!isBase64Url) {
|
191
|
+
throw new SyntaxError('Invalid base64 character');
|
192
|
+
}
|
193
|
+
c1 = 63;
|
194
|
+
chunkLength = 1;
|
195
|
+
break;
|
196
|
+
}
|
197
|
+
if (ch == 61) { // =
|
198
|
+
return (i << 16) | (j - destPtr);
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|
202
|
+
while (i < strLen) {
|
203
|
+
const ch: i32 = Porffor.wasm.i32.load8_u(strPtr + i++, 0, 4);
|
204
|
+
if (ch >= 65 && ch <= 90) { // A-Z
|
205
|
+
c2 = ch - 65;
|
206
|
+
chunkLength = 2;
|
207
|
+
break;
|
208
|
+
}
|
209
|
+
if (ch >= 97 && ch <= 122) { // a-z
|
210
|
+
c2 = ch - 71;
|
211
|
+
chunkLength = 2;
|
212
|
+
break;
|
213
|
+
}
|
214
|
+
if (ch >= 48 && ch <= 57) { // 0-9
|
215
|
+
c2 = ch + 4;
|
216
|
+
chunkLength = 2;
|
217
|
+
break;
|
218
|
+
}
|
219
|
+
if (ch == 43) { // +
|
220
|
+
if (isBase64Url) {
|
221
|
+
throw new SyntaxError('Invalid base64url character');
|
222
|
+
}
|
223
|
+
c2 = 62;
|
224
|
+
chunkLength = 2;
|
225
|
+
break;
|
226
|
+
}
|
227
|
+
if (ch == 47) { // /
|
228
|
+
if (isBase64Url) {
|
229
|
+
throw new SyntaxError('Invalid base64url character');
|
230
|
+
}
|
231
|
+
c2 = 63;
|
232
|
+
chunkLength = 2;
|
233
|
+
break;
|
234
|
+
}
|
235
|
+
if (ch == 45) { // -
|
236
|
+
if (!isBase64Url) {
|
237
|
+
throw new SyntaxError('Invalid base64 character');
|
238
|
+
}
|
239
|
+
c2 = 62;
|
240
|
+
chunkLength = 2;
|
241
|
+
break;
|
242
|
+
}
|
243
|
+
if (ch == 95) { // _
|
244
|
+
if (!isBase64Url) {
|
245
|
+
throw new SyntaxError('Invalid base64 character');
|
246
|
+
}
|
247
|
+
c2 = 63;
|
248
|
+
chunkLength = 2;
|
249
|
+
break;
|
250
|
+
}
|
251
|
+
if (ch == 61) { // =
|
252
|
+
return (i << 16) | (j - destPtr);
|
253
|
+
}
|
254
|
+
}
|
255
|
+
|
256
|
+
while (i < strLen) {
|
257
|
+
const ch: i32 = Porffor.wasm.i32.load8_u(strPtr + i++, 0, 4);
|
258
|
+
if (ch >= 65 && ch <= 90) { // A-Z
|
259
|
+
c3 = ch - 65;
|
260
|
+
chunkLength = 3;
|
261
|
+
break;
|
262
|
+
}
|
263
|
+
if (ch >= 97 && ch <= 122) { // a-z
|
264
|
+
c3 = ch - 71;
|
265
|
+
chunkLength = 3;
|
266
|
+
break;
|
267
|
+
}
|
268
|
+
if (ch >= 48 && ch <= 57) { // 0-9
|
269
|
+
c3 = ch + 4;
|
270
|
+
chunkLength = 3;
|
271
|
+
break;
|
272
|
+
}
|
273
|
+
if (ch == 43) { // +
|
274
|
+
if (isBase64Url) {
|
275
|
+
throw new SyntaxError('Invalid base64url character');
|
276
|
+
}
|
277
|
+
c3 = 62;
|
278
|
+
chunkLength = 3;
|
279
|
+
break;
|
280
|
+
}
|
281
|
+
if (ch == 47) { // /
|
282
|
+
if (isBase64Url) {
|
283
|
+
throw new SyntaxError('Invalid base64url character');
|
284
|
+
}
|
285
|
+
c3 = 63;
|
286
|
+
chunkLength = 3;
|
287
|
+
break;
|
288
|
+
}
|
289
|
+
if (ch == 45) { // -
|
290
|
+
if (!isBase64Url) {
|
291
|
+
throw new SyntaxError('Invalid base64 character');
|
292
|
+
}
|
293
|
+
c3 = 62;
|
294
|
+
chunkLength = 3;
|
295
|
+
break;
|
296
|
+
}
|
297
|
+
if (ch == 95) { // _
|
298
|
+
if (!isBase64Url) {
|
299
|
+
throw new SyntaxError('Invalid base64 character');
|
300
|
+
}
|
301
|
+
c3 = 63;
|
302
|
+
chunkLength = 3;
|
303
|
+
break;
|
304
|
+
}
|
305
|
+
if (ch == 61) { // =
|
306
|
+
if (j - destPtr + 1 > maxLength) {
|
307
|
+
return (chunkStartPos << 16) | (j - destPtr); // Not enough space
|
308
|
+
}
|
309
|
+
if (Porffor.strcmp(lastChunkHandling, 'strict') && (c2 & 15) != 0) {
|
310
|
+
throw new SyntaxError('Invalid base64 padding');
|
311
|
+
}
|
312
|
+
const b1: i32 = (c1 << 2) | (c2 >> 4);
|
313
|
+
Porffor.wasm.i32.store8(j++, b1, 0, 4);
|
314
|
+
|
315
|
+
// Check if there's a second padding character and consume it
|
316
|
+
if (i < strLen && Porffor.wasm.i32.load8_u(strPtr + i, 0, 4) == 61) {
|
317
|
+
i++;
|
318
|
+
}
|
319
|
+
|
320
|
+
return (i << 16) | (j - destPtr);
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
while (i < strLen) {
|
325
|
+
const ch: i32 = Porffor.wasm.i32.load8_u(strPtr + i++, 0, 4);
|
326
|
+
if (ch >= 65 && ch <= 90) { // A-Z
|
327
|
+
c4 = ch - 65;
|
328
|
+
chunkLength = 4;
|
329
|
+
break;
|
330
|
+
}
|
331
|
+
if (ch >= 97 && ch <= 122) { // a-z
|
332
|
+
c4 = ch - 71;
|
333
|
+
chunkLength = 4;
|
334
|
+
break;
|
335
|
+
}
|
336
|
+
if (ch >= 48 && ch <= 57) { // 0-9
|
337
|
+
c4 = ch + 4;
|
338
|
+
chunkLength = 4;
|
339
|
+
break;
|
340
|
+
}
|
341
|
+
if (ch == 43) { // +
|
342
|
+
if (isBase64Url) {
|
343
|
+
throw new SyntaxError('Invalid base64url character');
|
344
|
+
}
|
345
|
+
c4 = 62;
|
346
|
+
chunkLength = 4;
|
347
|
+
break;
|
348
|
+
}
|
349
|
+
if (ch == 47) { // /
|
350
|
+
if (isBase64Url) {
|
351
|
+
throw new SyntaxError('Invalid base64url character');
|
352
|
+
}
|
353
|
+
c4 = 63;
|
354
|
+
chunkLength = 4;
|
355
|
+
break;
|
356
|
+
}
|
357
|
+
if (ch == 45) { // -
|
358
|
+
if (!isBase64Url) {
|
359
|
+
throw new SyntaxError('Invalid base64 character');
|
360
|
+
}
|
361
|
+
c4 = 62;
|
362
|
+
chunkLength = 4;
|
363
|
+
break;
|
364
|
+
}
|
365
|
+
if (ch == 95) { // _
|
366
|
+
if (!isBase64Url) {
|
367
|
+
throw new SyntaxError('Invalid base64 character');
|
368
|
+
}
|
369
|
+
c4 = 63;
|
370
|
+
chunkLength = 4;
|
371
|
+
break;
|
372
|
+
}
|
373
|
+
if (ch == 61) { // =
|
374
|
+
if (j - destPtr + 2 > maxLength) {
|
375
|
+
return (chunkStartPos << 16) | (j - destPtr); // Not enough space
|
376
|
+
}
|
377
|
+
if (Porffor.strcmp(lastChunkHandling, 'strict') && (c3 & 3) != 0) {
|
378
|
+
throw new SyntaxError('Invalid base64 padding');
|
379
|
+
}
|
380
|
+
const b1: i32 = (c1 << 2) | (c2 >> 4);
|
381
|
+
const b2: i32 = ((c2 & 15) << 4) | (c3 >> 2);
|
382
|
+
Porffor.wasm.i32.store8(j++, b1, 0, 4);
|
383
|
+
Porffor.wasm.i32.store8(j++, b2, 0, 4);
|
384
|
+
return (i << 16) | (j - destPtr);
|
385
|
+
}
|
386
|
+
}
|
387
|
+
|
388
|
+
// Only check if we have space for 3 bytes if we actually have a complete 4-character chunk
|
389
|
+
if (chunkLength == 4) {
|
390
|
+
if (j - destPtr + 3 > maxLength) {
|
391
|
+
return (chunkStartPos << 16) | (j - destPtr); // Stop if not enough space
|
392
|
+
}
|
393
|
+
|
394
|
+
const b1: i32 = (c1 << 2) | (c2 >> 4);
|
395
|
+
const b2: i32 = ((c2 & 15) << 4) | (c3 >> 2);
|
396
|
+
const b3: i32 = ((c3 & 3) << 6) | c4;
|
397
|
+
|
398
|
+
Porffor.wasm.i32.store8(j++, b1, 0, 4);
|
399
|
+
Porffor.wasm.i32.store8(j++, b2, 0, 4);
|
400
|
+
Porffor.wasm.i32.store8(j++, b3, 0, 4);
|
401
|
+
}
|
402
|
+
}
|
403
|
+
|
404
|
+
// Handle end-of-string with partial chunk according to lastChunkHandling
|
405
|
+
if (chunkLength > 0) {
|
406
|
+
if (Porffor.strcmp(lastChunkHandling, 'stop-before-partial')) {
|
407
|
+
return (chunkStartPos << 16) | (j - destPtr); // Don't decode partial chunk
|
408
|
+
}
|
409
|
+
|
410
|
+
if (Porffor.strcmp(lastChunkHandling, 'strict')) {
|
411
|
+
throw new SyntaxError('Invalid base64 string');
|
412
|
+
}
|
413
|
+
|
414
|
+
// 'loose' handling - decode partial chunk
|
415
|
+
if (chunkLength == 1) {
|
416
|
+
throw new SyntaxError('Invalid base64 string'); // 1 char is always invalid
|
417
|
+
}
|
418
|
+
|
419
|
+
if (chunkLength == 2) {
|
420
|
+
if (j - destPtr + 1 > maxLength) {
|
421
|
+
return (chunkStartPos << 16) | (j - destPtr); // Not enough space for 1 byte
|
422
|
+
}
|
423
|
+
if (Porffor.strcmp(lastChunkHandling, 'strict') && (c2 & 15) != 0) {
|
424
|
+
throw new SyntaxError('Invalid base64 padding');
|
425
|
+
}
|
426
|
+
const b1: i32 = (c1 << 2) | (c2 >> 4);
|
427
|
+
Porffor.wasm.i32.store8(j++, b1, 0, 4);
|
428
|
+
} else if (chunkLength == 3) {
|
429
|
+
if (j - destPtr + 2 > maxLength) {
|
430
|
+
return (chunkStartPos << 16) | (j - destPtr); // Not enough space for 2 bytes
|
431
|
+
}
|
432
|
+
if (Porffor.strcmp(lastChunkHandling, 'strict') && (c3 & 3) != 0) {
|
433
|
+
throw new SyntaxError('Invalid base64 padding');
|
434
|
+
}
|
435
|
+
const b1: i32 = (c1 << 2) | (c2 >> 4);
|
436
|
+
const b2: i32 = ((c2 & 15) << 4) | (c3 >> 2);
|
437
|
+
Porffor.wasm.i32.store8(j++, b1, 0, 4);
|
438
|
+
Porffor.wasm.i32.store8(j++, b2, 0, 4);
|
439
|
+
}
|
440
|
+
}
|
441
|
+
|
442
|
+
return (strLen << 16) | (j - destPtr);
|
443
|
+
};
|
444
|
+
|
445
|
+
export const __Uint8Array_fromBase64 = (str: any, options: any = undefined) => {
|
446
|
+
if (Porffor.type(str) != Porffor.TYPES.bytestring) {
|
447
|
+
throw new TypeError('First argument must be a string');
|
448
|
+
}
|
449
|
+
|
450
|
+
let alphabet: string = 'base64';
|
451
|
+
let lastChunkHandling: string = 'loose';
|
452
|
+
|
453
|
+
if (Porffor.type(options) != Porffor.TYPES.undefined) {
|
454
|
+
if (Porffor.type(options) != Porffor.TYPES.object) {
|
455
|
+
throw new TypeError('Options must be an object');
|
456
|
+
}
|
457
|
+
|
458
|
+
const alphabetProp: any = options.alphabet;
|
459
|
+
if (Porffor.type(alphabetProp) != Porffor.TYPES.undefined) {
|
460
|
+
alphabet = alphabetProp;
|
461
|
+
}
|
462
|
+
|
463
|
+
const lastChunkProp: any = options.lastChunkHandling;
|
464
|
+
if (Porffor.type(lastChunkProp) != Porffor.TYPES.undefined) {
|
465
|
+
lastChunkHandling = lastChunkProp;
|
466
|
+
}
|
467
|
+
}
|
468
|
+
|
469
|
+
if (!Porffor.strcmp(alphabet, 'base64') && !Porffor.strcmp(alphabet, 'base64url')) {
|
470
|
+
throw new TypeError('Invalid alphabet');
|
471
|
+
}
|
472
|
+
|
473
|
+
if (!Porffor.strcmp(lastChunkHandling, 'loose') && !Porffor.strcmp(lastChunkHandling, 'strict') && !Porffor.strcmp(lastChunkHandling, 'stop-before-partial')) {
|
474
|
+
throw new TypeError('Invalid lastChunkHandling');
|
475
|
+
}
|
476
|
+
|
477
|
+
// Calculate exact output size based on input length and padding
|
478
|
+
let exactSize: i32 = 0;
|
479
|
+
const strLen: i32 = str.length;
|
480
|
+
|
481
|
+
if (strLen == 0) {
|
482
|
+
exactSize = 0;
|
483
|
+
} else {
|
484
|
+
// Count padding characters from the end
|
485
|
+
let paddingCount: i32 = 0;
|
486
|
+
const strPtr: i32 = Porffor.wasm`local.get ${str}`;
|
487
|
+
let i: i32 = strLen - 1;
|
488
|
+
while (i >= 0 && Porffor.wasm.i32.load8_u(strPtr + i, 0, 4) == 61) {
|
489
|
+
paddingCount++;
|
490
|
+
i--;
|
491
|
+
}
|
492
|
+
|
493
|
+
// Calculate exact size: 4 chars -> 3 bytes, minus padding
|
494
|
+
const nonPaddingChars: i32 = strLen - paddingCount;
|
495
|
+
exactSize = (nonPaddingChars * 3) / 4;
|
496
|
+
}
|
497
|
+
|
498
|
+
const ta: Uint8Array = new Uint8Array(exactSize);
|
499
|
+
const taPtr: i32 = Porffor.wasm`local.get ${ta}`;
|
500
|
+
const bufferPtr: i32 = Porffor.wasm.i32.load(taPtr, 0, 4);
|
501
|
+
|
502
|
+
__Porffor_fromBase64(str, alphabet, lastChunkHandling, bufferPtr, exactSize);
|
503
|
+
|
504
|
+
return ta;
|
505
|
+
};
|
506
|
+
|
507
|
+
export const __Uint8Array_prototype_setFromBase64 = (_this: Uint8Array, str: any, options: any = undefined) => {
|
508
|
+
if (Porffor.type(str) != Porffor.TYPES.bytestring) {
|
509
|
+
throw new TypeError('First argument must be a string');
|
510
|
+
}
|
511
|
+
|
512
|
+
let alphabet: string = 'base64';
|
513
|
+
let lastChunkHandling: string = 'loose';
|
514
|
+
|
515
|
+
if (Porffor.type(options) != Porffor.TYPES.undefined) {
|
516
|
+
if (Porffor.type(options) != Porffor.TYPES.object) {
|
517
|
+
throw new TypeError('Options must be an object');
|
518
|
+
}
|
519
|
+
|
520
|
+
const alphabetProp: any = options.alphabet;
|
521
|
+
if (Porffor.type(alphabetProp) != Porffor.TYPES.undefined) {
|
522
|
+
alphabet = alphabetProp;
|
523
|
+
}
|
524
|
+
|
525
|
+
const lastChunkProp: any = options.lastChunkHandling;
|
526
|
+
if (Porffor.type(lastChunkProp) != Porffor.TYPES.undefined) {
|
527
|
+
lastChunkHandling = lastChunkProp;
|
528
|
+
}
|
529
|
+
}
|
530
|
+
|
531
|
+
if (!Porffor.strcmp(alphabet, 'base64') && !Porffor.strcmp(alphabet, 'base64url')) {
|
532
|
+
throw new TypeError('Invalid alphabet');
|
533
|
+
}
|
534
|
+
|
535
|
+
if (!Porffor.strcmp(lastChunkHandling, 'loose') && !Porffor.strcmp(lastChunkHandling, 'strict') && !Porffor.strcmp(lastChunkHandling, 'stop-before-partial')) {
|
536
|
+
throw new TypeError('Invalid lastChunkHandling');
|
537
|
+
}
|
538
|
+
|
539
|
+
__Porffor_uint8array_validate(_this);
|
540
|
+
const taPtr: i32 = Porffor.wasm`local.get ${_this}`;
|
541
|
+
const byteLength: i32 = Porffor.wasm.i32.load(taPtr, 0, 0);
|
542
|
+
const bufferPtr: i32 = Porffor.wasm.i32.load(taPtr, 0, 4);
|
543
|
+
|
544
|
+
const result: i32 = __Porffor_fromBase64(str, alphabet, lastChunkHandling, bufferPtr, byteLength);
|
545
|
+
const charsRead: i32 = result >> 16;
|
546
|
+
const bytesWritten: i32 = result & 0xFFFF;
|
547
|
+
|
548
|
+
const resultObj: object = {};
|
549
|
+
resultObj.read = charsRead;
|
550
|
+
resultObj.written = bytesWritten;
|
551
|
+
|
552
|
+
return resultObj;
|
553
|
+
};
|
554
|
+
|
555
|
+
// Returns packed: (charsRead << 16) | bytesWritten
|
556
|
+
export const __Porffor_fromHex = (str: bytestring, destPtr: i32, maxLength: i32) => {
|
557
|
+
const strPtr: i32 = Porffor.wasm`local.get ${str}`;
|
558
|
+
const strLen: i32 = str.length;
|
559
|
+
|
560
|
+
if ((strLen & 1) != 0) {
|
561
|
+
throw new SyntaxError('Hex string must have even length');
|
562
|
+
}
|
563
|
+
|
564
|
+
let j: i32 = destPtr;
|
565
|
+
|
566
|
+
let i: i32 = 0;
|
567
|
+
const maxBytes: i32 = strLen / 2;
|
568
|
+
const limit: i32 = maxBytes < maxLength ? maxBytes : maxLength;
|
569
|
+
|
570
|
+
while (i < limit) {
|
571
|
+
const h1: i32 = Porffor.wasm.i32.load8_u(strPtr + i * 2, 0, 4);
|
572
|
+
const h2: i32 = Porffor.wasm.i32.load8_u(strPtr + i * 2 + 1, 0, 4);
|
573
|
+
|
574
|
+
let v1: i32 = -1;
|
575
|
+
let v2: i32 = -1;
|
576
|
+
|
577
|
+
if (h1 >= 48 && h1 <= 57) v1 = h1 - 48; // 0-9
|
578
|
+
else if (h1 >= 97 && h1 <= 102) v1 = h1 - 87; // a-f
|
579
|
+
else if (h1 >= 65 && h1 <= 70) v1 = h1 - 55; // A-F
|
580
|
+
|
581
|
+
if (h2 >= 48 && h2 <= 57) v2 = h2 - 48; // 0-9
|
582
|
+
else if (h2 >= 97 && h2 <= 102) v2 = h2 - 87; // a-f
|
583
|
+
else if (h2 >= 65 && h2 <= 70) v2 = h2 - 55; // A-F
|
584
|
+
|
585
|
+
if (v1 == -1 || v2 == -1) {
|
586
|
+
throw new SyntaxError('Invalid hex character');
|
587
|
+
}
|
588
|
+
|
589
|
+
const byte: i32 = (v1 << 4) | v2;
|
590
|
+
Porffor.wasm.i32.store8(j++, byte, 0, 4);
|
591
|
+
|
592
|
+
i++;
|
593
|
+
}
|
594
|
+
|
595
|
+
const charsRead: i32 = i * 2;
|
596
|
+
return (charsRead << 16) | (j - destPtr);
|
597
|
+
};
|
598
|
+
|
599
|
+
export const __Uint8Array_fromHex = (str: any) => {
|
600
|
+
if (Porffor.type(str) != Porffor.TYPES.bytestring) {
|
601
|
+
throw new TypeError('First argument must be a string');
|
602
|
+
}
|
603
|
+
|
604
|
+
// Hex decoding: 2 chars -> 1 byte exactly
|
605
|
+
const exactSize: i32 = str.length / 2;
|
606
|
+
const ta: Uint8Array = new Uint8Array(exactSize);
|
607
|
+
const taPtr: i32 = Porffor.wasm`local.get ${ta}`;
|
608
|
+
const bufferPtr: i32 = Porffor.wasm.i32.load(taPtr, 0, 4);
|
609
|
+
|
610
|
+
__Porffor_fromHex(str, bufferPtr, exactSize);
|
611
|
+
|
612
|
+
return ta;
|
613
|
+
};
|
614
|
+
|
615
|
+
export const __Uint8Array_prototype_setFromHex = (_this: Uint8Array, str: any) => {
|
616
|
+
if (Porffor.type(str) != Porffor.TYPES.bytestring) {
|
617
|
+
throw new TypeError('First argument must be a string');
|
618
|
+
}
|
619
|
+
|
620
|
+
__Porffor_uint8array_validate(_this);
|
621
|
+
const taPtr: i32 = Porffor.wasm`local.get ${_this}`;
|
622
|
+
const byteLength: i32 = Porffor.wasm.i32.load(taPtr, 0, 0);
|
623
|
+
const bufferPtr: i32 = Porffor.wasm.i32.load(taPtr, 0, 4);
|
624
|
+
|
625
|
+
const result: i32 = __Porffor_fromHex(str, bufferPtr, byteLength);
|
626
|
+
const charsRead: i32 = result >> 16;
|
627
|
+
const bytesWritten: i32 = result & 0xFFFF;
|
628
|
+
|
629
|
+
const resultObj: object = {};
|
630
|
+
resultObj.read = charsRead;
|
631
|
+
resultObj.written = bytesWritten;
|
632
|
+
|
633
|
+
return resultObj;
|
634
|
+
};
|