porffor 0.60.11 → 0.60.13

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.
@@ -489,6 +489,9 @@ i32.load 0 4
489
489
  local.set ${obj}
490
490
  i32.load8_u 0 3
491
491
  local.set ${obj+1}`;
492
+
493
+ // if undefined, prototype is object.prototype
494
+ if (Porffor.type(obj) == Porffor.TYPES.undefined) obj = __Object_prototype;
492
495
  } else obj = __Porffor_object_getPrototype(obj);
493
496
  if (Porffor.type(obj) != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
494
497
 
@@ -555,6 +558,9 @@ i32.load 0 4
555
558
  local.set ${obj}
556
559
  i32.load8_u 0 3
557
560
  local.set ${obj+1}`;
561
+
562
+ // if undefined, prototype is object.prototype
563
+ if (Porffor.type(obj) == Porffor.TYPES.undefined) obj = __Object_prototype;
558
564
  } else obj = __Porffor_object_getPrototype(obj);
559
565
  if (Porffor.type(obj) != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
560
566
 
@@ -1,5 +1,14 @@
1
1
  import type {} from './porffor.d.ts';
2
2
 
3
+ // `eval` is invalid syntax so work around
4
+ export const _eval = (source: string) => {
5
+ throw new SyntaxError('Dynamic code evaluation is not supported');
6
+ };
7
+
8
+ export const Function = function (source: string) {
9
+ throw new SyntaxError('Dynamic code evaluation is not supported');
10
+ };
11
+
3
12
  export const __Function_prototype_toString = (_this: Function) => {
4
13
  const out: bytestring = Porffor.allocate();
5
14
 
@@ -23,7 +23,7 @@ export const __Porffor_object_getHiddenPrototype = (trueType: i32): any => {
23
23
  }`;
24
24
 
25
25
  for (const x in TYPES) {
26
- if (['undefined', 'string', 'bytestring', 'stringobject', 'number', 'numberobject', 'boolean', 'booleanobject'].includes(x)) continue;
26
+ if (['object', 'undefined', 'string', 'bytestring', 'stringobject', 'number', 'numberobject', 'boolean', 'booleanobject'].includes(x)) continue;
27
27
 
28
28
  const name = TYPE_NAMES[TYPES[x]];
29
29
  out += `
@@ -989,26 +989,15 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
989
989
  const sticky: boolean = (flags & 0b00100000) != 0;
990
990
 
991
991
  const inputLen: i32 = Porffor.wasm.i32.load(input, 0, 0);
992
- let searchStart: i32 = 0;
992
+ let lastIndex: i32 = 0;
993
993
  if (global || sticky) {
994
- searchStart = Porffor.wasm.i32.load16_u(regexp, 0, 8);
994
+ lastIndex = Porffor.wasm.i32.load16_u(regexp, 0, 8);
995
995
  }
996
996
 
997
- if (searchStart > inputLen) {
998
- if (global || sticky) Porffor.wasm.i32.store16(regexp, 0, 0, 8);
999
- return null;
1000
- }
1001
-
1002
- // todo: free all at the end (or statically allocate but = [] causes memory corruption)
1003
- const backtrackStack: i32[] = Porffor.allocate();
1004
- const captures: i32[] = Porffor.allocateBytes(6144);
1005
-
1006
- for (let i: i32 = searchStart; i <= inputLen; i++) {
1007
- if (sticky && i != searchStart) {
1008
- if (isTest) return false;
1009
- return null;
1010
- }
997
+ const backtrackStack: i32[] = [];
998
+ const captures: i32[] = [];
1011
999
 
1000
+ for (let i: i32 = lastIndex; i <= inputLen; i++) {
1012
1001
  backtrackStack.length = 0;
1013
1002
  captures.length = 0;
1014
1003
 
@@ -1065,7 +1054,6 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
1065
1054
 
1066
1055
  if (op == 0x01) { // single
1067
1056
  if (sp >= inputLen) {
1068
- // Porffor.log(`single: oob`);
1069
1057
  backtrack = true;
1070
1058
  } else {
1071
1059
  let c1: i32 = Porffor.wasm.i32.load8_u(pc, 0, 1);
@@ -1075,11 +1063,9 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
1075
1063
  if (c2 >= 97 && c2 <= 122) c2 -= 32;
1076
1064
  }
1077
1065
  if (c1 == c2) {
1078
- // Porffor.log(`single: matched ${c1}`);
1079
1066
  pc += 2;
1080
1067
  sp += 1;
1081
1068
  } else {
1082
- // Porffor.log(`single: failed, expected ${c1}, got ${c2}`);
1083
1069
  backtrack = true;
1084
1070
  }
1085
1071
  }
@@ -1291,7 +1277,6 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
1291
1277
  const lookaheadEndPc = pc + jumpOffset + 3;
1292
1278
  const savedSp = sp; // Save current string position
1293
1279
 
1294
-
1295
1280
  // Use fork to test the lookahead pattern
1296
1281
  Porffor.array.fastPushI32(backtrackStack, lookaheadEndPc); // Continue point after lookahead
1297
1282
  Porffor.array.fastPushI32(backtrackStack, savedSp); // Restore original sp
@@ -1320,7 +1305,6 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
1320
1305
  const capIndex = Porffor.wasm.i32.load8_u(pc, 0, 1);
1321
1306
  const arrIndex = capIndex + 255; // + 255 offset for temp start, as it could never end properly
1322
1307
  captures[arrIndex] = sp;
1323
- // Porffor.log(`startCapture: captures[${arrIndex}] = ${sp} | captures.length = ${captures.length}`);
1324
1308
  pc += 2;
1325
1309
  } else if (op == 0x31) { // end capture
1326
1310
  const capIndex = Porffor.wasm.i32.load8_u(pc, 0, 1);
@@ -1328,7 +1312,6 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
1328
1312
  while (captures.length <= arrIndex) Porffor.array.fastPushI32(captures, -1);
1329
1313
  captures[arrIndex - 1] = captures[capIndex + 255];
1330
1314
  captures[arrIndex] = sp;
1331
- // Porffor.log(`endCapture: captures[${arrIndex}] = ${sp} | captures.length = ${captures.length}`);
1332
1315
  pc += 2;
1333
1316
  } else { // unknown op
1334
1317
  backtrack = true;
@@ -1337,7 +1320,6 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
1337
1320
  if (backtrack) {
1338
1321
  if (backtrackStack.length == 0) break;
1339
1322
 
1340
-
1341
1323
  // Check if we're backtracking from a lookahead
1342
1324
  if (backtrackStack.length >= 4) {
1343
1325
  const marker = backtrackStack[backtrackStack.length - 1];
@@ -1365,11 +1347,9 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
1365
1347
  }
1366
1348
 
1367
1349
  // Normal backtracking
1368
- // Porffor.log(`backtrack! before: captures.length = ${captures.length}, sp = ${sp}, pc = ${pc}`);
1369
1350
  captures.length = Porffor.array.fastPopI32(backtrackStack);
1370
1351
  sp = Porffor.array.fastPopI32(backtrackStack);
1371
1352
  pc = Porffor.array.fastPopI32(backtrackStack);
1372
- // Porffor.log(`backtrack! after: captures.length = ${captures.length}, sp = ${sp}, pc = ${pc}`);
1373
1353
  }
1374
1354
  }
1375
1355
 
@@ -1378,7 +1358,7 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
1378
1358
 
1379
1359
  const matchStart: i32 = i;
1380
1360
  if (global || sticky) {
1381
- Porffor.wasm.i32.store(regexp, finalSp, 0, 8);
1361
+ Porffor.wasm.i32.store16(regexp, finalSp, 0, 8); // write last index
1382
1362
  }
1383
1363
 
1384
1364
  const result: any[] = Porffor.allocateBytes(4096);
@@ -1404,10 +1384,16 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
1404
1384
 
1405
1385
  return result;
1406
1386
  }
1387
+
1388
+ if (sticky) { // sticky, do not go forward in string
1389
+ Porffor.wasm.i32.store16(regexp, 0, 0, 8); // failed, write 0 last index
1390
+ if (isTest) return false;
1391
+ return null;
1392
+ }
1407
1393
  }
1408
1394
 
1409
1395
  if (global || sticky) {
1410
- Porffor.wasm.i32.store(regexp, 0, 0, 8);
1396
+ Porffor.wasm.i32.store16(regexp, 0, 0, 8); // failed, write 0 last index
1411
1397
  }
1412
1398
 
1413
1399
  if (isTest) return false;
@@ -1419,6 +1405,10 @@ export const __RegExp_prototype_source$get = (_this: RegExp) => {
1419
1405
  return Porffor.wasm.i32.load(_this, 0, 0) as bytestring;
1420
1406
  };
1421
1407
 
1408
+ export const __RegExp_prototype_lastIndex$get = (_this: RegExp) => {
1409
+ return Porffor.wasm.i32.load16_u(_this, 0, 8);
1410
+ };
1411
+
1422
1412
  // 22.2.6.4 get RegExp.prototype.flags
1423
1413
  // https://tc39.es/ecma262/multipage/text-processing.html#sec-get-regexp.prototype.flags
1424
1414
  export const __RegExp_prototype_flags$get = (_this: RegExp) => {
@@ -1532,12 +1522,63 @@ export const __RegExp_prototype_test = (_this: RegExp, input: any) => {
1532
1522
  return __Porffor_regex_interpret(_this, input, true);
1533
1523
  };
1534
1524
 
1535
- export const __String_prototype_match = (_this: string, regexp: any) => {
1525
+
1526
+ export const __Porffor_regex_match = (regexp: any, input: any) => {
1536
1527
  if (Porffor.type(regexp) !== Porffor.TYPES.regexp) regexp = new RegExp(regexp);
1537
- return __RegExp_prototype_exec(regexp, _this);
1528
+ if (Porffor.type(input) !== Porffor.TYPES.bytestring) input = ecma262.ToString(input);
1529
+
1530
+ if (__RegExp_prototype_global$get(regexp)) {
1531
+ // global should return all matches as just complete string result
1532
+ const result: any[] = Porffor.allocateBytes(4096);
1533
+ let match: any;
1534
+ while (match = __Porffor_regex_interpret(regexp, input, false)) {
1535
+ // read ourselves as we are in i32 space
1536
+ Porffor.wasm`
1537
+ local.get ${result}
1538
+ f64.convert_i32_u
1539
+ local.get ${result+1}
1540
+
1541
+ local.get ${match}
1542
+ f64.load 0 4
1543
+ local.get ${match}
1544
+ i32.load8_u 0 12
1545
+
1546
+ call __Porffor_array_fastPush`;
1547
+ }
1548
+ return result;
1549
+ }
1550
+
1551
+ return __Porffor_regex_interpret(regexp, input, false);
1552
+ };
1553
+
1554
+ export const __String_prototype_match = (_this: string, regexp: any) => {
1555
+ return __Porffor_regex_match(regexp, _this);
1538
1556
  };
1539
1557
 
1540
1558
  export const __ByteString_prototype_match = (_this: bytestring, regexp: any) => {
1559
+ return __Porffor_regex_match(regexp, _this);
1560
+ };
1561
+
1562
+
1563
+ // todo: use actual iterator not array
1564
+ export const __Porffor_regex_matchAll = (regexp: any, input: any) => {
1541
1565
  if (Porffor.type(regexp) !== Porffor.TYPES.regexp) regexp = new RegExp(regexp);
1542
- return __RegExp_prototype_exec(regexp, _this);
1566
+ if (Porffor.type(input) !== Porffor.TYPES.bytestring) input = ecma262.ToString(input);
1567
+
1568
+ if (!__RegExp_prototype_global$get(regexp)) throw new TypeError('matchAll used with non-global RegExp');
1569
+
1570
+ const result: any[] = Porffor.allocateBytes(4096);
1571
+ let match: any;
1572
+ while (match = __Porffor_regex_interpret(regexp, input, false)) {
1573
+ Porffor.array.fastPush(result, match);
1574
+ }
1575
+ return result;
1576
+ };
1577
+
1578
+ export const __String_prototype_matchAll = (_this: string, regexp: any) => {
1579
+ return __Porffor_regex_matchAll(regexp, _this);
1580
+ };
1581
+
1582
+ export const __ByteString_prototype_matchAll = (_this: bytestring, regexp: any) => {
1583
+ return __Porffor_regex_matchAll(regexp, _this);
1543
1584
  };