porffor 0.59.2 → 0.59.4

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/AGENT.md CHANGED
@@ -1,22 +1,20 @@
1
1
  you are an assistant coder for Porffor - an early javascript and typescript to webassembly and native ahead-of-time compiler. the codebase is written in js and ts.
2
2
 
3
- IMPORTANT:
4
3
  - built-ins apis (Date, String.prototype, etc) are written in ts inside `compiler/builtins`
5
4
  - once you update a file inside that directory, you MUST run `./porf precompile` to compile to make your changes effective
6
-
7
- Test your work using the test262 tools available, iterate independently but do not get stuck on one chain of thought or approach. Paths for test262 tools should be relative to the 'test262/test' directory (e.g., 'built-ins/RegExp' NOT 'test262/test/built-ins/RegExp').
8
-
9
- You can also do the following via bash/shell commands:
10
- - To get an overview of the most failing directories, use the command: `node test262/fails.cjs`
11
- - To just evaluate code in the engine, use the command: `./porf -p "..."`
12
-
13
- ## Code Style
14
- - After finishing, check if your work/diff could be simplified
15
- - Always use single quotes (unless double is required)
5
+ - test your work using the test262 tools available, iterate independently but do not get stuck on one chain of thought or approach. paths for test262 tools should be relative to the 'test262/test' directory (e.g., 'built-ins/RegExp' NOT 'test262/test/built-ins/RegExp').
6
+ - to get an overview of the most failing directories, use the command: `node test262/fails.cjs`
7
+ - to just evaluate code in the engine, use the command: `./porf -p "..."`
8
+ - after finishing, check if your work/diff could be simplified
9
+ - always use single quotes (unless double is required)
16
10
  - 2-space indentation, LF line endings, no trailing whitespace
17
- - Built-in APIs in `compiler/builtins/` written in TypeScript
18
- - Inline code in built-ins, avoid helper functions
19
- - Use semicolons
20
- - Do not use trailing commas
21
- - Use const/let, avoid var
22
- - Follow existing naming: camelCase for variables, PascalCase for types
11
+ - built-in APIs in `compiler/builtins/` written in TypeScript
12
+ - inline code in built-ins, avoid helper functions
13
+ - use semicolons
14
+ - do not use trailing commas
15
+ - use const/let, avoid var
16
+ - follow existing naming: camelCase for variables, PascalCase for types
17
+
18
+ memories:
19
+ - The user prefers that prototype functions not have explicit return types in this codebase.
20
+ - The user prefers not to use global variables in built-in functions.
@@ -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 = undefined): RegExp {
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
- const out: ArrayBuffer = Porffor.wasm.i32.load(_this, 0, 4) - Porffor.wasm.i32.load(_this, 0, 8);
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
+ };