porffor 0.2.0-5ad562e → 0.2.0-5c24120

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.
@@ -37,7 +37,7 @@ export const __String_prototype_toUpperCase = (_this: string) => {
37
37
  return out;
38
38
  };
39
39
 
40
- export const ___bytestring_prototype_toUpperCase = (_this: bytestring) => {
40
+ export const __ByteString_prototype_toUpperCase = (_this: bytestring) => {
41
41
  const len: i32 = _this.length;
42
42
 
43
43
  let out: bytestring = '';
@@ -83,7 +83,7 @@ export const __String_prototype_toLowerCase = (_this: string) => {
83
83
  return out;
84
84
  };
85
85
 
86
- export const ___bytestring_prototype_toLowerCase = (_this: bytestring) => {
86
+ export const __ByteString_prototype_toLowerCase = (_this: bytestring) => {
87
87
  const len: i32 = _this.length;
88
88
 
89
89
  let out: bytestring = '';
@@ -134,10 +134,10 @@ export const __String_prototype_startsWith = (_this: string, searchString: strin
134
134
  return true;
135
135
  };
136
136
 
137
- export const ___bytestring_prototype_startsWith = (_this: bytestring, searchString: bytestring, position: number) => {
137
+ export const __ByteString_prototype_startsWith = (_this: bytestring, searchString: bytestring, position: number) => {
138
138
  // if searching non-bytestring, bytestring will not start with it
139
139
  // todo: change this to just check if = string and ToString others
140
- if (Porffor.wasm`local.get ${searchString+1}` != Porffor.TYPES._bytestring) return false;
140
+ if (Porffor.wasm`local.get ${searchString+1}` != Porffor.TYPES.bytestring) return false;
141
141
 
142
142
  // todo/perf: investigate whether for counter vs while ++s are faster
143
143
 
@@ -204,10 +204,10 @@ export const __String_prototype_endsWith = (_this: string, searchString: string,
204
204
  return true;
205
205
  };
206
206
 
207
- export const ___bytestring_prototype_endsWith = (_this: bytestring, searchString: bytestring, endPosition: number) => {
207
+ export const __ByteString_prototype_endsWith = (_this: bytestring, searchString: bytestring, endPosition: number) => {
208
208
  // if searching non-bytestring, bytestring will not start with it
209
209
  // todo: change this to just check if = string and ToString others
210
- if (Porffor.wasm`local.get ${searchString+1}` != Porffor.TYPES._bytestring) return false;
210
+ if (Porffor.wasm`local.get ${searchString+1}` != Porffor.TYPES.bytestring) return false;
211
211
 
212
212
  let i: i32 = Porffor.wasm`local.get ${_this}`,
213
213
  j: i32 = Porffor.wasm`local.get ${searchString}`;
@@ -282,10 +282,10 @@ export const __String_prototype_indexOf = (_this: string, searchString: string,
282
282
  return -1;
283
283
  };
284
284
 
285
- export const ___bytestring_prototype_indexOf = (_this: bytestring, searchString: bytestring, position: number) => {
285
+ export const __ByteString_prototype_indexOf = (_this: bytestring, searchString: bytestring, position: number) => {
286
286
  // if searching non-bytestring, bytestring will not start with it
287
287
  // todo: change this to just check if = string and ToString others
288
- if (Porffor.wasm`local.get ${searchString+1}` != Porffor.TYPES._bytestring) return -1;
288
+ if (Porffor.wasm`local.get ${searchString+1}` != Porffor.TYPES.bytestring) return -1;
289
289
 
290
290
  let thisPtr: i32 = Porffor.wasm`local.get ${_this}`;
291
291
  const searchPtr: i32 = Porffor.wasm`local.get ${searchString}`;
@@ -369,10 +369,10 @@ export const __String_prototype_lastIndexOf = (_this: string, searchString: stri
369
369
  return -1;
370
370
  };
371
371
 
372
- export const ___bytestring_prototype_lastIndexOf = (_this: bytestring, searchString: bytestring, position: number) => {
372
+ export const __ByteString_prototype_lastIndexOf = (_this: bytestring, searchString: bytestring, position: number) => {
373
373
  // if searching non-bytestring, bytestring will not start with it
374
374
  // todo: change this to just check if = string and ToString others
375
- if (Porffor.wasm`local.get ${searchString+1}` != Porffor.TYPES._bytestring) return -1;
375
+ if (Porffor.wasm`local.get ${searchString+1}` != Porffor.TYPES.bytestring) return -1;
376
376
 
377
377
  let thisPtr: i32 = Porffor.wasm`local.get ${_this}`;
378
378
  const searchPtr: i32 = Porffor.wasm`local.get ${searchString}`;
@@ -455,10 +455,10 @@ export const __String_prototype_includes = (_this: string, searchString: string,
455
455
  return false;
456
456
  };
457
457
 
458
- export const ___bytestring_prototype_includes = (_this: bytestring, searchString: bytestring, position: number) => {
458
+ export const __ByteString_prototype_includes = (_this: bytestring, searchString: bytestring, position: number) => {
459
459
  // if searching non-bytestring, bytestring will not start with it
460
460
  // todo: change this to just check if = string and ToString others
461
- if (Porffor.wasm`local.get ${searchString+1}` != Porffor.TYPES._bytestring) return -1;
461
+ if (Porffor.wasm`local.get ${searchString+1}` != Porffor.TYPES.bytestring) return -1;
462
462
 
463
463
  let thisPtr: i32 = Porffor.wasm`local.get ${_this}`;
464
464
  const searchPtr: i32 = Porffor.wasm`local.get ${searchString}`;
@@ -542,7 +542,7 @@ export const __String_prototype_padStart = (_this: string, targetLength: number,
542
542
  return out;
543
543
  };
544
544
 
545
- export const ___bytestring_prototype_padStart = (_this: bytestring, targetLength: number, padString: bytestring) => {
545
+ export const __ByteString_prototype_padStart = (_this: bytestring, targetLength: number, padString: bytestring) => {
546
546
  // todo: handle padString being non-bytestring
547
547
 
548
548
  let out: bytestring = Porffor.bs``;
@@ -631,7 +631,7 @@ export const __String_prototype_padEnd = (_this: string, targetLength: number, p
631
631
  return out;
632
632
  };
633
633
 
634
- export const ___bytestring_prototype_padEnd = (_this: bytestring, targetLength: number, padString: bytestring) => {
634
+ export const __ByteString_prototype_padEnd = (_this: bytestring, targetLength: number, padString: bytestring) => {
635
635
  // todo: handle padString being non-bytestring
636
636
 
637
637
  let out: bytestring = Porffor.bs``;
@@ -713,7 +713,7 @@ export const __String_prototype_substring = (_this: string, start: number, end:
713
713
  return out;
714
714
  };
715
715
 
716
- export const ___bytestring_prototype_substring = (_this: bytestring, start: number, end: number) => {
716
+ export const __ByteString_prototype_substring = (_this: bytestring, start: number, end: number) => {
717
717
  const len: i32 = _this.length;
718
718
  if (Porffor.wasm`local.get ${end+1}` == Porffor.TYPES.undefined) end = len;
719
719
  else if (start > end) {
@@ -786,7 +786,7 @@ export const __String_prototype_substr = (_this: string, start: number, length:
786
786
  return out;
787
787
  };
788
788
 
789
- export const ___bytestring_prototype_substr = (_this: string, start: number, length: number) => {
789
+ export const __ByteString_prototype_substr = (_this: string, start: number, length: number) => {
790
790
  const len: i32 = _this.length;
791
791
 
792
792
  start |= 0;
@@ -862,7 +862,7 @@ export const __String_prototype_slice = (_this: string, start: number, end: numb
862
862
  return out;
863
863
  };
864
864
 
865
- export const ___bytestring_prototype_slice = (_this: bytestring, start: number, end: number) => {
865
+ export const __ByteString_prototype_slice = (_this: bytestring, start: number, end: number) => {
866
866
  const len: i32 = _this.length;
867
867
  if (Porffor.wasm`local.get ${end+1}` == Porffor.TYPES.undefined) end = len;
868
868
 
@@ -935,7 +935,7 @@ export const __String_prototype_trimStart = (_this: string) => {
935
935
  return out;
936
936
  };
937
937
 
938
- export const ___bytestring_prototype_trimStart = (_this: bytestring) => {
938
+ export const __ByteString_prototype_trimStart = (_this: bytestring) => {
939
939
  let out: bytestring = Porffor.bs``;
940
940
 
941
941
  let outPtr: i32 = Porffor.wasm`local.get ${out}`;
@@ -1006,7 +1006,7 @@ export const __String_prototype_trimEnd = (_this: string) => {
1006
1006
  return out;
1007
1007
  };
1008
1008
 
1009
- export const ___bytestring_prototype_trimEnd = (_this: bytestring) => {
1009
+ export const __ByteString_prototype_trimEnd = (_this: bytestring) => {
1010
1010
  let out: bytestring = Porffor.bs``;
1011
1011
 
1012
1012
  let outPtr: i32 = Porffor.wasm`local.get ${out}`;
@@ -1049,7 +1049,32 @@ export const __String_prototype_trim = (_this: string) => {
1049
1049
  return __String_prototype_trimStart(__String_prototype_trimEnd(_this));
1050
1050
  };
1051
1051
 
1052
- export const ___bytestring_prototype_trim = (_this: bytestring) => {
1052
+ export const __ByteString_prototype_trim = (_this: bytestring) => {
1053
1053
  // todo/perf: optimize and not just reuse
1054
- return ___bytestring_prototype_trimStart(___bytestring_prototype_trimEnd(_this));
1054
+ return __ByteString_prototype_trimStart(__ByteString_prototype_trimEnd(_this));
1055
+ };
1056
+
1057
+ // 22.1.3.29 String.prototype.toString ()
1058
+ // https://tc39.es/ecma262/#sec-string.prototype.tostring
1059
+ export const __String_prototype_toString = (_this: string) => {
1060
+ // 1. Return ? ThisStringValue(this value).
1061
+ return _this;
1062
+ };
1063
+
1064
+ export const __ByteString_prototype_toString = (_this: bytestring) => {
1065
+ // 1. Return ? ThisStringValue(this value).
1066
+ return _this;
1067
+ };
1068
+
1069
+
1070
+ // 22.1.3.35 String.prototype.valueOf ()
1071
+ // https://tc39.es/ecma262/#sec-string.prototype.valueof
1072
+ export const __String_prototype_valueOf = (_this: string) => {
1073
+ // 1. Return ? ThisStringValue(this value).
1074
+ return _this;
1075
+ };
1076
+
1077
+ export const __ByteString_prototype_valueOf = (_this: bytestring) => {
1078
+ // 1. Return ? ThisStringValue(this value).
1079
+ return _this;
1055
1080
  };
@@ -141,7 +141,7 @@ export const BuiltinVars = function() {
141
141
 
142
142
  // wintercg(tm)
143
143
  this.__navigator_userAgent = (scope, { makeString }) => makeString(scope, `Porffor/0.2.0`, false, '__navigator_userAgent');
144
- this.__navigator_userAgent.type = Prefs.bytestring ? TYPES._bytestring : TYPES.string;
144
+ this.__navigator_userAgent.type = Prefs.bytestring ? TYPES.bytestring : TYPES.string;
145
145
 
146
146
  for (const x in TYPES) {
147
147
  this['__Porffor_TYPES_' + x] = number(TYPES[x]);
@@ -273,7 +273,7 @@ export const BuiltinFuncs = function() {
273
273
 
274
274
  [ Opcodes.end ]
275
275
  ],
276
- [TYPES._bytestring]: [
276
+ [TYPES.bytestring]: [
277
277
  // simply print a (byte)string :))
278
278
  // cache input pointer as i32
279
279
  [ Opcodes.local_get, 0 ],
@@ -307,7 +307,7 @@ export const BuiltinFuncs = function() {
307
307
 
308
308
  [ Opcodes.end ]
309
309
  ],
310
- [TYPES._array]: [
310
+ [TYPES.array]: [
311
311
  ...printStaticStr('[ '),
312
312
 
313
313
  // cache input pointer as i32
@@ -1039,7 +1039,7 @@ export const BuiltinFuncs = function() {
1039
1039
  typedParams: true,
1040
1040
  locals: [ Valtype.i32, Valtype.i32 ],
1041
1041
  returns: [ valtypeBinary ],
1042
- returnType: Prefs.bytestring ? TYPES._bytestring : TYPES.string,
1042
+ returnType: Prefs.bytestring ? TYPES.bytestring : TYPES.string,
1043
1043
  wasm: (scope, { TYPE_NAMES, typeSwitch, makeString }) => {
1044
1044
  const bc = {};
1045
1045
  for (const x in TYPE_NAMES) {
@@ -59,6 +59,10 @@ const todo = (scope, msg, expectsValue = undefined) => {
59
59
  };
60
60
 
61
61
  const isFuncType = type => type === 'FunctionDeclaration' || type === 'FunctionExpression' || type === 'ArrowFunctionExpression';
62
+ const hasFuncWithName = name => {
63
+ const func = funcs.find(x => x.name === name);
64
+ return !!(func || builtinFuncs[name] || importedFuncs[name] || internalConstrs[name]);
65
+ };
62
66
  const generate = (scope, decl, global = false, name = undefined, valueUnused = false) => {
63
67
  switch (decl.type) {
64
68
  case 'BinaryExpression':
@@ -219,8 +223,8 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
219
223
  __Porffor_bs: str => [
220
224
  ...makeString(scope, str, global, name, true),
221
225
 
222
- ...(name ? setType(scope, name, TYPES._bytestring) : [
223
- ...number(TYPES._bytestring, Valtype.i32),
226
+ ...(name ? setType(scope, name, TYPES.bytestring) : [
227
+ ...number(TYPES.bytestring, Valtype.i32),
224
228
  ...setLastType(scope)
225
229
  ])
226
230
  ],
@@ -723,7 +727,7 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false) => {
723
727
 
724
728
  ...typeSwitch(scope, type, {
725
729
  // [TYPES.number]: def,
726
- [TYPES._array]: [
730
+ [TYPES.array]: [
727
731
  // arrays are always truthy
728
732
  ...number(1, intOut ? Valtype.i32 : valtypeBinary)
729
733
  ],
@@ -739,7 +743,7 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false) => {
739
743
  [ Opcodes.i32_eqz ], */
740
744
  ...(intOut ? [] : [ Opcodes.i32_from_u ])
741
745
  ],
742
- [TYPES._bytestring]: [ // duplicate of string
746
+ [TYPES.bytestring]: [ // duplicate of string
743
747
  ...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
744
748
  ...(intIn ? [] : [ Opcodes.i32_to_u ]),
745
749
 
@@ -762,7 +766,7 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false) => {
762
766
  ...(!useTmp ? [] : [ [ Opcodes.local_set, tmp ] ]),
763
767
 
764
768
  ...typeSwitch(scope, type, {
765
- [TYPES._array]: [
769
+ [TYPES.array]: [
766
770
  // arrays are always truthy
767
771
  ...number(0, intOut ? Valtype.i32 : valtypeBinary)
768
772
  ],
@@ -777,7 +781,7 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false) => {
777
781
  [ Opcodes.i32_eqz ],
778
782
  ...(intOut ? [] : [ Opcodes.i32_from_u ])
779
783
  ],
780
- [TYPES._bytestring]: [ // duplicate of string
784
+ [TYPES.bytestring]: [ // duplicate of string
781
785
  ...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
782
786
  ...(intIn ? [] : [ Opcodes.i32_to_u ]),
783
787
 
@@ -922,7 +926,7 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
922
926
  }
923
927
  }
924
928
 
925
- if (knownLeft === TYPES._bytestring || knownRight === TYPES._bytestring) {
929
+ if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) {
926
930
  if (op === '+') {
927
931
  // todo: this should be dynamic too but for now only static
928
932
  // string concat (a + b)
@@ -1041,12 +1045,12 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
1041
1045
 
1042
1046
  // if left is bytestring
1043
1047
  ...leftType,
1044
- ...number(TYPES._bytestring, Valtype.i32),
1048
+ ...number(TYPES.bytestring, Valtype.i32),
1045
1049
  [ Opcodes.i32_eq ],
1046
1050
 
1047
1051
  // if right is bytestring
1048
1052
  ...rightType,
1049
- ...number(TYPES._bytestring, Valtype.i32),
1053
+ ...number(TYPES.bytestring, Valtype.i32),
1050
1054
  [ Opcodes.i32_eq ],
1051
1055
 
1052
1056
  // if both are true
@@ -1177,7 +1181,6 @@ const generateLogicExp = (scope, decl) => {
1177
1181
  // js type: 4 bits
1178
1182
  // internal type: ? bits
1179
1183
  // pointer: 32 bits
1180
-
1181
1184
  // generic
1182
1185
  // 1 23 4 5
1183
1186
  // 0 11111111111 11TTTTIIII??????????PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
@@ -1188,7 +1191,7 @@ const generateLogicExp = (scope, decl) => {
1188
1191
  // 5: pointer
1189
1192
 
1190
1193
  const isExistingProtoFunc = name => {
1191
- if (name.startsWith('__Array_prototype')) return !!prototypeFuncs[TYPES._array][name.slice(18)];
1194
+ if (name.startsWith('__Array_prototype')) return !!prototypeFuncs[TYPES.array][name.slice(18)];
1192
1195
  if (name.startsWith('__String_prototype_')) return !!prototypeFuncs[TYPES.string][name.slice(19)];
1193
1196
 
1194
1197
  return false;
@@ -1247,9 +1250,9 @@ const setLastType = scope => {
1247
1250
  const getNodeType = (scope, node) => {
1248
1251
  const inner = () => {
1249
1252
  if (node.type === 'Literal') {
1250
- if (node.regex) return TYPES._regexp;
1253
+ if (node.regex) return TYPES.regexp;
1251
1254
 
1252
- if (typeof node.value === 'string' && byteStringable(node.value)) return TYPES._bytestring;
1255
+ if (typeof node.value === 'string' && byteStringable(node.value)) return TYPES.bytestring;
1253
1256
 
1254
1257
  return TYPES[typeof node.value];
1255
1258
  }
@@ -1303,7 +1306,7 @@ const getNodeType = (scope, node) => {
1303
1306
  const spl = name.slice(2).split('_');
1304
1307
 
1305
1308
  const func = spl[spl.length - 1];
1306
- const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES._bytestring && prototypeFuncs[x][func] != null);
1309
+ const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
1307
1310
  if (protoFuncs.length === 1) return protoFuncs[0].returnType ?? TYPES.number;
1308
1311
  }
1309
1312
 
@@ -1355,7 +1358,7 @@ const getNodeType = (scope, node) => {
1355
1358
  }
1356
1359
 
1357
1360
  if (node.type === 'ArrayExpression') {
1358
- return TYPES._array;
1361
+ return TYPES.array;
1359
1362
  }
1360
1363
 
1361
1364
  if (node.type === 'BinaryExpression') {
@@ -1367,7 +1370,7 @@ const getNodeType = (scope, node) => {
1367
1370
 
1368
1371
  // todo: this should be dynamic but for now only static
1369
1372
  if (knownLeft === TYPES.string || knownRight === TYPES.string) return TYPES.string;
1370
- if (knownLeft === TYPES._bytestring || knownRight === TYPES._bytestring) return TYPES._bytestring;
1373
+ if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) return TYPES.bytestring;
1371
1374
 
1372
1375
  return TYPES.number;
1373
1376
 
@@ -1393,19 +1396,28 @@ const getNodeType = (scope, node) => {
1393
1396
  if (node.operator === '!') return TYPES.boolean;
1394
1397
  if (node.operator === 'void') return TYPES.undefined;
1395
1398
  if (node.operator === 'delete') return TYPES.boolean;
1396
- if (node.operator === 'typeof') return Prefs.bytestring ? TYPES._bytestring : TYPES.string;
1399
+ if (node.operator === 'typeof') return Prefs.bytestring ? TYPES.bytestring : TYPES.string;
1397
1400
 
1398
1401
  return TYPES.number;
1399
1402
  }
1400
1403
 
1401
1404
  if (node.type === 'MemberExpression') {
1405
+ // hack: if something.name, string type
1406
+ if (node.property.name === 'name') {
1407
+ if (hasFuncWithName(node.object.name)) {
1408
+ return TYPES.bytestring;
1409
+ } else {
1410
+ return TYPES.undefined;
1411
+ }
1412
+ }
1413
+
1402
1414
  // hack: if something.length, number type
1403
1415
  if (node.property.name === 'length') return TYPES.number;
1404
1416
 
1405
1417
  // ts hack
1406
1418
  if (scope.locals[node.object.name]?.metadata?.type === TYPES.string) return TYPES.string;
1407
- if (scope.locals[node.object.name]?.metadata?.type === TYPES._bytestring) return TYPES._bytestring;
1408
- if (scope.locals[node.object.name]?.metadata?.type === TYPES._array) return TYPES.number;
1419
+ if (scope.locals[node.object.name]?.metadata?.type === TYPES.bytestring) return TYPES.bytestring;
1420
+ if (scope.locals[node.object.name]?.metadata?.type === TYPES.array) return TYPES.number;
1409
1421
 
1410
1422
  if (scope.locals['#last_type']) return getLastType(scope);
1411
1423
 
@@ -2092,7 +2104,7 @@ const brTable = (input, bc, returns) => {
2092
2104
  };
2093
2105
 
2094
2106
  const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
2095
- if (!Prefs.bytestring) delete bc[TYPES._bytestring];
2107
+ if (!Prefs.bytestring) delete bc[TYPES.bytestring];
2096
2108
 
2097
2109
  const known = knownType(scope, type);
2098
2110
  if (known != null) {
@@ -2195,7 +2207,7 @@ const extractTypeAnnotation = decl => {
2195
2207
  const typeName = type;
2196
2208
  type = typeAnnoToPorfType(type);
2197
2209
 
2198
- if (type === TYPES._bytestring && !Prefs.bytestring) type = TYPES.string;
2210
+ if (type === TYPES.bytestring && !Prefs.bytestring) type = TYPES.string;
2199
2211
 
2200
2212
  // if (decl.name) console.log(decl.name, { type, elementType });
2201
2213
 
@@ -2325,7 +2337,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2325
2337
 
2326
2338
  return [
2327
2339
  ...typeSwitch(scope, getNodeType(scope, decl.left.object), {
2328
- [TYPES._array]: [
2340
+ [TYPES.array]: [
2329
2341
  ...(aotPointer ? [] : [
2330
2342
  ...generate(scope, decl.left.object),
2331
2343
  Opcodes.i32_to_u
@@ -2527,7 +2539,7 @@ const generateUnary = (scope, decl) => {
2527
2539
  [TYPES.undefined]: makeString(scope, 'undefined', false, '#typeof_result'),
2528
2540
  [TYPES.function]: makeString(scope, 'function', false, '#typeof_result'),
2529
2541
 
2530
- [TYPES._bytestring]: makeString(scope, 'string', false, '#typeof_result'),
2542
+ [TYPES.bytestring]: makeString(scope, 'string', false, '#typeof_result'),
2531
2543
 
2532
2544
  // object and internal types
2533
2545
  default: makeString(scope, 'object', false, '#typeof_result'),
@@ -2763,7 +2775,7 @@ const generateForOf = (scope, decl) => {
2763
2775
  // set type for local
2764
2776
  // todo: optimize away counter and use end pointer
2765
2777
  out.push(...typeSwitch(scope, getNodeType(scope, decl.right), {
2766
- [TYPES._array]: [
2778
+ [TYPES.array]: [
2767
2779
  ...setType(scope, leftName, TYPES.number),
2768
2780
 
2769
2781
  [ Opcodes.loop, Blocktype.void ],
@@ -2846,8 +2858,8 @@ const generateForOf = (scope, decl) => {
2846
2858
  [ Opcodes.end ],
2847
2859
  [ Opcodes.end ]
2848
2860
  ],
2849
- [TYPES._bytestring]: [
2850
- ...setType(scope, leftName, TYPES._bytestring),
2861
+ [TYPES.bytestring]: [
2862
+ ...setType(scope, leftName, TYPES.bytestring),
2851
2863
 
2852
2864
  [ Opcodes.loop, Blocktype.void ],
2853
2865
 
@@ -3229,6 +3241,20 @@ export const generateMember = (scope, decl, _global, _name) => {
3229
3241
 
3230
3242
  const aotPointer = Prefs.aotPointerOpt && pointer != null;
3231
3243
 
3244
+ // hack: .name
3245
+ if (decl.property.name === 'name') {
3246
+ if (hasFuncWithName(name)) {
3247
+ let nameProp = name;
3248
+
3249
+ // eg: __String_prototype_toLowerCase -> toLowerCase
3250
+ if (nameProp.startsWith('__')) nameProp = nameProp.split('_').pop();
3251
+
3252
+ return makeString(scope, nameProp, _global, _name, true);
3253
+ } else {
3254
+ return generate(scope, DEFAULT_VALUE);
3255
+ }
3256
+ }
3257
+
3232
3258
  // hack: .length
3233
3259
  if (decl.property.name === 'length') {
3234
3260
  const func = funcs.find(x => x.name === name);
@@ -3238,6 +3264,16 @@ export const generateMember = (scope, decl, _global, _name) => {
3238
3264
  return number(typedParams ? func.params.length / 2 : func.params.length);
3239
3265
  }
3240
3266
 
3267
+ if (builtinFuncs[name + '$constructor']) {
3268
+ const regularFunc = builtinFuncs[name];
3269
+ const regularParams = regularFunc.typedParams ? (regularFunc.params.length / 2) : regularFunc.params.length;
3270
+
3271
+ const constructorFunc = builtinFuncs[name + '$constructor'];
3272
+ const constructorParams = constructorFunc.typedParams ? (constructorFunc.params.length / 2) : constructorFunc.params.length;
3273
+
3274
+ return number(Math.max(regularParams, constructorParams));
3275
+ }
3276
+
3241
3277
  if (builtinFuncs[name]) return number(builtinFuncs[name].typedParams ? (builtinFuncs[name].params.length / 2) : builtinFuncs[name].params.length);
3242
3278
  if (importedFuncs[name]) return number(importedFuncs[name].params);
3243
3279
  if (internalConstrs[name]) return number(internalConstrs[name].length ?? 0);
@@ -3266,7 +3302,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3266
3302
  }
3267
3303
 
3268
3304
  return typeSwitch(scope, getNodeType(scope, decl.object), {
3269
- [TYPES._array]: [
3305
+ [TYPES.array]: [
3270
3306
  // get index as valtype
3271
3307
  ...property,
3272
3308
 
@@ -3319,7 +3355,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3319
3355
  ...number(TYPES.string, Valtype.i32),
3320
3356
  ...setLastType(scope)
3321
3357
  ],
3322
- [TYPES._bytestring]: [
3358
+ [TYPES.bytestring]: [
3323
3359
  // setup new/out array
3324
3360
  ...newOut,
3325
3361
  [ Opcodes.drop ],
@@ -3344,7 +3380,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3344
3380
  // return new string (page)
3345
3381
  ...number(newPointer),
3346
3382
 
3347
- ...number(TYPES._bytestring, Valtype.i32),
3383
+ ...number(TYPES.bytestring, Valtype.i32),
3348
3384
  ...setLastType(scope)
3349
3385
  ],
3350
3386
 
@@ -3369,8 +3405,8 @@ const objectHack = node => {
3369
3405
 
3370
3406
  if (!objectName) objectName = objectHack(node.object)?.name?.slice?.(2);
3371
3407
 
3372
- // if .length, give up (hack within a hack!)
3373
- if (node.property.name === 'length') {
3408
+ // if .name or .length, give up (hack within a hack!)
3409
+ if (['name', 'length'].includes(node.property.name)) {
3374
3410
  node.object = objectHack(node.object);
3375
3411
  return;
3376
3412
  }
@@ -3513,7 +3549,7 @@ const internalConstrs = {
3513
3549
  ...number(pointer)
3514
3550
  ];
3515
3551
  },
3516
- type: TYPES._array,
3552
+ type: TYPES.array,
3517
3553
  length: 1
3518
3554
  },
3519
3555
 
@@ -3525,7 +3561,7 @@ const internalConstrs = {
3525
3561
  elements: decl.arguments
3526
3562
  }, global, name);
3527
3563
  },
3528
- type: TYPES._array,
3564
+ type: TYPES.array,
3529
3565
  notConstr: true,
3530
3566
  length: 0
3531
3567
  },
@@ -3654,23 +3690,6 @@ const internalConstrs = {
3654
3690
  }
3655
3691
  };
3656
3692
 
3657
- // const _ = Array.prototype.push;
3658
- // Array.prototype.push = function (a) {
3659
- // const check = arr => {
3660
- // for (const x of arr) {
3661
- // if (x === undefined) {
3662
- // console.trace(arr);
3663
- // process.exit();
3664
- // }
3665
- // if (Array.isArray(x)) check(x);
3666
- // }
3667
- // };
3668
- // if (Array.isArray(a) && !new Error().stack.includes('node:')) check(a);
3669
- // // if (Array.isArray(a)) check(a);
3670
-
3671
- // return _.apply(this, arguments);
3672
- // };
3673
-
3674
3693
  export default program => {
3675
3694
  globals = {};
3676
3695
  globalInd = 0;