porffor 0.30.13 → 0.31.0

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/2c.js CHANGED
@@ -231,20 +231,6 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
231
231
  prependMain.set('argv', `_argc = argc; _argv = argv;`);
232
232
  }
233
233
 
234
- prepend.set('func decls', funcs.filter(x => x.name !== 'main').map(f => {
235
- const returns = f.returns.length > 0;
236
- const typedReturns = f.returnType == null;
237
-
238
- const invLocals = inv(f.locals, x => x.idx);
239
- for (const x in invLocals) {
240
- invLocals[x] = sanitize(invLocals[x]);
241
- }
242
-
243
- const shouldInline = false;
244
-
245
- return `${!typedReturns ? (returns ? CValtype[f.returns[0]] : 'void') : 'struct ReturnValue'} ${shouldInline ? 'inline ' : ''}${sanitize(f.name)}(${f.params.map((x, i) => `${CValtype[x]} ${invLocals[i]}`).join(', ')});`;
246
- }).join('\n'));
247
-
248
234
  if (out) out += '\n';
249
235
 
250
236
  const line = (str, semi = true) => out += `${str}${semi ? ';' : ''}\n`;
@@ -438,7 +424,7 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
438
424
 
439
425
  case Opcodes.f64_const: {
440
426
  const val = i[1];
441
- vals.push(val);
427
+ vals.push(val.toString());
442
428
  break;
443
429
  }
444
430
 
@@ -822,7 +808,7 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
822
808
  break;
823
809
  }
824
810
 
825
- // log.warning('2c', `unimplemented op: ${invOpcodes[i[0]]} \x1b[90m(${f.name})`);
811
+ if (Prefs.d) log.warning('2c', `unimplemented op: ${invOpcodes[i[0]]} \x1b[90m(${f.name})`);
826
812
  }
827
813
 
828
814
  lastCond = false;
@@ -844,6 +830,20 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
844
830
 
845
831
  cify(funcs.find(x => x.name === 'main'));
846
832
 
833
+ prepend.set('func decls', funcs.filter(x => x.name !== 'main' && cified.has(x.name)).map(f => {
834
+ const returns = f.returns.length > 0;
835
+ const typedReturns = f.returnType == null;
836
+
837
+ const invLocals = inv(f.locals, x => x.idx);
838
+ for (const x in invLocals) {
839
+ invLocals[x] = sanitize(invLocals[x]);
840
+ }
841
+
842
+ const shouldInline = false;
843
+
844
+ return `${!typedReturns ? (returns ? CValtype[f.returns[0]] : 'void') : 'struct ReturnValue'} ${shouldInline ? 'inline ' : ''}${sanitize(f.name)}(${f.params.map((x, i) => `${CValtype[x]} ${invLocals[i]}`).join(', ')});`;
845
+ }).join('\n'));
846
+
847
847
  const makeIncludes = includes => [...includes.keys()].map(x => `#include <${x}>\n`).join('');
848
848
  out = platformSpecific(makeIncludes(winIncludes), makeIncludes(unixIncludes), false) + '\n' + makeIncludes(includes) + '\n' + alwaysPreface + [...prepend.values()].join('\n') + '\n\n' + out;
849
849
 
@@ -39,6 +39,7 @@ export class StaticAllocator {
39
39
  if (globalThis.precompile && scopeName === 'main') scopeName = globalThis.precompile;
40
40
  const reason = `${this.allocType(itemType)}: ${Prefs.scopedPageNames ? (scopeName + '/') : ''}${name}`;
41
41
 
42
+ this.lastName = reason;
42
43
  if (pages.has(reason)) {
43
44
  const ptr = this.lastPtr = this.ptr(pages.get(reason).ind);
44
45
  return number(ptr, Valtype.i32);
@@ -203,7 +203,7 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
203
203
  }
204
204
 
205
205
  data.push({
206
- offset,
206
+ page: 'func lut',
207
207
  bytes
208
208
  });
209
209
  data.addedFuncArgcLut = true;
@@ -358,11 +358,18 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
358
358
  const dataSection = data.length === 0 ? [] : createSection(
359
359
  Section.data,
360
360
  encodeVector(data.map(x => {
361
- // type: active
362
- if (x.offset != null) return [ 0x00, Opcodes.i32_const, ...signedLEB128(x.offset), Opcodes.end, ...encodeVector(x.bytes) ];
361
+ const bytes = encodeVector(x.bytes);
362
+
363
+ if (x.page != null) {
364
+ // type: active
365
+ const offset = pages.get(x.page).ind * pageSize;
366
+ bytes.unshift(0x00, Opcodes.i32_const, ...signedLEB128(offset), Opcodes.end);
367
+ } else {
368
+ // type: passive
369
+ bytes.unshift(0x01);
370
+ }
363
371
 
364
- // type: passive
365
- return [ 0x01, ...encodeVector(x.bytes) ];
372
+ return bytes;
366
373
  }))
367
374
  );
368
375
 
@@ -174,9 +174,8 @@ export const __Porffor_object_get = (obj: any, key: any): any => {
174
174
  if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot get property of null');
175
175
 
176
176
  if (Porffor.wasm`local.get ${obj+1}` == Porffor.TYPES.function) {
177
- let tmp: bytestring = '';
178
- tmp = 'name';
179
- if (key == tmp) {
177
+ const tmp1: bytestring = 'name';
178
+ if (key == tmp1) {
180
179
  const o: bytestring = __Porffor_funcLut_name(obj);
181
180
  const t: i32 = Porffor.TYPES.bytestring;
182
181
  Porffor.wasm`
@@ -186,8 +185,8 @@ local.get ${t}
186
185
  return`;
187
186
  }
188
187
 
189
- tmp = 'length';
190
- if (key == tmp) {
188
+ const tmp2: bytestring = 'length';
189
+ if (key == tmp2) {
191
190
  const o: i32 = __Porffor_funcLut_length(obj);
192
191
  Porffor.wasm`
193
192
  local.get ${o}
@@ -198,12 +197,37 @@ return`;
198
197
  }
199
198
 
200
199
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_getObject(obj);
201
- const entryPtr: i32 = __Porffor_object_lookup(obj, key);
200
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key);
202
201
  if (entryPtr == -1) {
203
- Porffor.wasm`
202
+ const protoKey: bytestring = '__proto__';
203
+
204
+ if (Porffor.wasm`local.get ${obj+1}` == Porffor.TYPES.object) {
205
+ // check prototype chain
206
+ let lastProto = obj;
207
+ if (key != protoKey) {
208
+ while (true) {
209
+ obj = __Porffor_object_get(obj, protoKey);
210
+ if (Porffor.fastOr(obj == null, Porffor.wasm`local.get ${obj}` == Porffor.wasm`local.get ${lastProto}`)) break;
211
+ lastProto = obj;
212
+
213
+ if ((entryPtr = __Porffor_object_lookup(obj, key)) != -1) break;
214
+ }
215
+ } else {
216
+ const i: i32 = __Object_prototype;
217
+ Porffor.wasm`
218
+ local.get ${i}
219
+ f64.convert_i32_u
220
+ i32.const 7 ;; object type
221
+ return`;
222
+ }
223
+ }
224
+
225
+ if (entryPtr == -1) {
226
+ Porffor.wasm`
204
227
  f64.const 0
205
228
  i32.const 128
206
229
  return`;
230
+ }
207
231
  }
208
232
 
209
233
  const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
@@ -424,15 +448,14 @@ export const __Porffor_object_delete = (obj: any, key: any): boolean => {
424
448
  if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot delete property of null');
425
449
 
426
450
  if (Porffor.wasm`local.get ${obj+1}` == Porffor.TYPES.function) {
427
- let tmp: bytestring = '';
428
- tmp = 'name';
429
- if (key == tmp) {
451
+ const tmp1: bytestring = 'name';
452
+ if (key == tmp1) {
430
453
  __Porffor_funcLut_deleteName(obj);
431
454
  return true;
432
455
  }
433
456
 
434
- tmp = 'length';
435
- if (key == tmp) {
457
+ const tmp2: bytestring = 'length';
458
+ if (key == tmp2) {
436
459
  __Porffor_funcLut_deleteLength(obj);
437
460
  return true;
438
461
  }
@@ -1,7 +1,11 @@
1
1
  import type {} from './porffor.d.ts';
2
2
 
3
3
  export const __ArrayBuffer_isView = (value: any): boolean => {
4
- if (value.buffer) return true;
4
+ const t: i32 = Porffor.rawType(value);
5
+ if (Porffor.fastOr(
6
+ t == Porffor.TYPES.dataview,
7
+ Porffor.fastAnd(t >= Porffor.TYPES.uint8array, t <= Porffor.TYPES.float64array)
8
+ )) return true;
5
9
  return false;
6
10
  };
7
11
 
@@ -171,13 +171,11 @@ export const __Object_prototype_hasOwnProperty = (_this: any, prop: any) => {
171
171
  }
172
172
 
173
173
  if (t == Porffor.TYPES.function) {
174
- let tmp: bytestring = '';
174
+ const tmp1: bytestring = 'name';
175
+ if (p == tmp1) return !__Porffor_funcLut_isNameDeleted(_this);
175
176
 
176
- tmp = 'name';
177
- if (p == tmp) return !__Porffor_funcLut_isNameDeleted(_this);
178
-
179
- tmp = 'length';
180
- if (p == tmp) return !__Porffor_funcLut_isLengthDeleted(_this);
177
+ const tmp2: bytestring = 'length';
178
+ if (p == tmp2) return !__Porffor_funcLut_isLengthDeleted(_this);
181
179
 
182
180
  return false;
183
181
  }
@@ -190,6 +188,26 @@ export const __Object_hasOwn = (obj: any, prop: any) => {
190
188
  return __Object_prototype_hasOwnProperty(obj, prop);
191
189
  };
192
190
 
191
+ export const __Porffor_object_in = (obj: any, prop: any) => {
192
+ if (__Object_prototype_hasOwnProperty(obj, prop)) {
193
+ return true;
194
+ }
195
+
196
+ const t: i32 = Porffor.rawType(obj);
197
+ if (t != Porffor.TYPES.object) {
198
+ return false;
199
+ }
200
+
201
+ let lastProto = obj;
202
+ while (true) {
203
+ obj = obj.__proto__;
204
+ if (Porffor.fastOr(obj == null, Porffor.wasm`local.get ${obj}` == Porffor.wasm`local.get ${lastProto}`)) break;
205
+ lastProto = obj;
206
+
207
+ if (__Object_prototype_hasOwnProperty(obj, prop)) return true;
208
+ }
209
+ };
210
+
193
211
 
194
212
  export const __Object_assign = (target: any, ...sources: any[]) => {
195
213
  if (target == null) throw new TypeError('Argument is nullish, expected object');
@@ -601,11 +619,6 @@ export const __Object_groupBy = (items: any, callbackFn: any) => {
601
619
  export const __Object_getPrototypeOf = (obj: any) => {
602
620
  if (obj == null) throw new TypeError('Object is nullish, expected object');
603
621
 
604
- // todo: support non-pure-objects
605
- if (Porffor.rawType(obj) != Porffor.TYPES.object) {
606
- return {};
607
- }
608
-
609
622
  return obj.__proto__;
610
623
  };
611
624
 
@@ -3,10 +3,12 @@ import { TYPES } from './types.js';
3
3
  import { number } from './embedding.js';
4
4
 
5
5
  export default function({ builtinFuncs }, Prefs) {
6
+ const makePrefix = name => (name.startsWith('__') ? '' : '__') + name + '_';
7
+
6
8
  const done = new Set();
7
9
  const object = (name, props) => {
8
10
  done.add(name);
9
- const prefix = name === 'globalThis' ? '' : `__${name}_`;
11
+ const prefix = name === 'globalThis' ? '' : makePrefix(name);
10
12
 
11
13
  // already a func
12
14
  const existingFunc = builtinFuncs[name];
@@ -58,7 +60,7 @@ export default function({ builtinFuncs }, Prefs) {
58
60
  if (d.writable) flags |= 0b1000;
59
61
 
60
62
  // hack: do not generate objects inside of objects as it causes issues atm
61
- if (this[prefix + x]?.type === TYPES.object) value = { type: 'ObjectExpression', properties: [] };
63
+ if (this[prefix + x]?.type === TYPES.object && this[prefix + x] !== this.null) value = { type: 'ObjectExpression', properties: [] };
62
64
 
63
65
  out.push(
64
66
  [ Opcodes.global_get, 0 ],
@@ -124,6 +126,11 @@ export default function({ builtinFuncs }, Prefs) {
124
126
  continue;
125
127
  }
126
128
 
129
+ if (d.value === null) {
130
+ this[k] = this.null;
131
+ continue;
132
+ }
133
+
127
134
  throw new Error(`unsupported value type (${typeof d.value})`);
128
135
  }
129
136
  }
@@ -151,7 +158,10 @@ export default function({ builtinFuncs }, Prefs) {
151
158
  };
152
159
 
153
160
  const builtinFuncKeys = Object.keys(builtinFuncs);
154
- const autoFuncKeys = name => builtinFuncKeys.filter(x => x.startsWith('__' + name + '_')).map(x => x.slice(name.length + 3));
161
+ const autoFuncKeys = name => {
162
+ const prefix = makePrefix(name);
163
+ return builtinFuncKeys.filter(x => x.startsWith(prefix)).map(x => x.slice(prefix.length));
164
+ };
155
165
  const autoFuncs = name => props({
156
166
  writable: true,
157
167
  enumerable: false,
@@ -191,7 +201,12 @@ export default function({ builtinFuncs }, Prefs) {
191
201
  acc.add(x.slice(0, ind + 10));
192
202
  return acc;
193
203
  }, new Set())) {
194
- object(x, autoFuncs(x));
204
+ const props = autoFuncs(x);
205
+
206
+ // special case: Object.prototype.__proto__ = null
207
+ if (x === '__Object_prototype') Object.defineProperty(props, '__proto__', { value: { value: null }, enumerable: true });
208
+
209
+ object(x, props);
195
210
  }
196
211
 
197
212
 
@@ -291,7 +306,7 @@ export default function({ builtinFuncs }, Prefs) {
291
306
  }
292
307
  if (!t) continue;
293
308
 
294
- if (!done.has(name) && !done.has('__' + name)) {
309
+ if (!done.has(name)) {
295
310
  console.log(name.replaceAll('_', '.'), !!builtinFuncs[name]);
296
311
  done.add(name);
297
312
  }