pxt-core 8.2.11 → 8.2.12

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/built/cli.js CHANGED
@@ -3891,11 +3891,6 @@ async function testSnippetsAsync(snippets, re, pyStrictSyntaxCheck) {
3891
3891
  }
3892
3892
  return;
3893
3893
  }
3894
- if (++codeSnippetCount % 40 == 0) {
3895
- // clean up cache every once in a while to speed up / clear up mem
3896
- // TODO probably this should be handled in the service host as it does become a perf concern
3897
- cleanService();
3898
- }
3899
3894
  const isPy = snippet.ext === "py";
3900
3895
  const inFiles = Object.assign({ [pxt.MAIN_TS]: isPy ? "" : snippet.code, [pxt.MAIN_PY]: isPy ? snippet.code : "", [pxt.MAIN_BLOCKS]: "" }, (snippet.extraFiles || {}));
3901
3896
  const { pkg, opts } = await getCompileResources(inFiles, snippet.packages);
package/built/pxt.js CHANGED
@@ -121892,7 +121892,7 @@ var ts;
121892
121892
  // Assumptions:
121893
121893
  // - registers can hold a pointer (data or code)
121894
121894
  // - special registers include: sp
121895
- // - fixed registers are r0, r1, r2, r3, r5, r6
121895
+ // - fixed registers are r0, r1, r2, r3, r5, r6
121896
121896
  // - r0 is the current value (from expression evaluation)
121897
121897
  // - registers for runtime calls (r0, r1,r2,r3)
121898
121898
  // - r5 is for captured locals in lambda
@@ -121905,7 +121905,7 @@ var ts;
121905
121905
  class AssemblerSnippets {
121906
121906
  nop() { return "TBD(nop)"; }
121907
121907
  reg_gets_imm(reg, imm) { return "TBD(reg_gets_imm)"; }
121908
- // Registers are stored on the stack in numerical order
121908
+ // Registers are stored on the stack in numerical order
121909
121909
  proc_setup(numlocals, main) { return "TBD(proc_setup)"; }
121910
121910
  push_fixed(reg) { return "TBD(push_fixed)"; }
121911
121911
  push_local(reg) { return "TBD(push_local)"; }
@@ -122120,7 +122120,7 @@ ${baseLabel}_nochk:
122120
122120
  }
122121
122121
  }
122122
122122
  };
122123
- if (this.bin.options.breakpoints) {
122123
+ if (this.bin.breakpoints) {
122124
122124
  this.write(this.t.debugger_proc(bkptLabel));
122125
122125
  }
122126
122126
  this.baseStackSize = 1; // push {lr}
@@ -122163,7 +122163,7 @@ ${baseLabel}_nochk:
122163
122163
  this.write(`; ${s.expr.data}`);
122164
122164
  break;
122165
122165
  case pxtc.ir.SK.Breakpoint:
122166
- if (this.bin.options.breakpoints) {
122166
+ if (this.bin.breakpoints) {
122167
122167
  let lbl = `__brkp_${s.breakpointInfo.id}`;
122168
122168
  if (s.breakpointInfo.isDebuggerStmt) {
122169
122169
  this.write(this.t.debugger_stmt(lbl));
@@ -123562,7 +123562,7 @@ var ts;
123562
123562
  "bind",
123563
123563
  "leaveAccessor"
123564
123564
  ];
123565
- function jsEmit(bin) {
123565
+ function jsEmit(bin, cres) {
123566
123566
  let jssource = "(function (ectx) {\n'use strict';\n";
123567
123567
  for (let n of evalIfaceFields) {
123568
123568
  jssource += `const ${n} = ectx.${n};\n`;
@@ -123574,7 +123574,7 @@ var ts;
123574
123574
  jssource += "pxsim.setTitle(" + JSON.stringify(bin.getTitle()) + ");\n";
123575
123575
  let cfg = {};
123576
123576
  let cfgKey = {};
123577
- for (let ce of bin.res.configData || []) {
123577
+ for (let ce of cres.configData || []) {
123578
123578
  cfg[ce.key + ""] = ce.value;
123579
123579
  cfgKey[ce.name] = ce.key;
123580
123580
  }
@@ -123604,8 +123604,8 @@ var ts;
123604
123604
  bin.usedClassInfos.forEach(info => {
123605
123605
  jssource += vtableToJs(info);
123606
123606
  });
123607
- if (bin.res.breakpoints)
123608
- jssource += `\nconst breakpoints = setupDebugger(${bin.res.breakpoints.length}, [${bin.globals.filter(c => c.isUserVariable).map(c => `"${c.uniqueName()}"`).join(",")}])\n`;
123607
+ if (cres.breakpoints)
123608
+ jssource += `\nconst breakpoints = setupDebugger(${cres.breakpoints.length}, [${bin.globals.filter(c => c.isUserVariable).map(c => `"${c.uniqueName()}"`).join(",")}])\n`;
123609
123609
  jssource += `\nreturn ${bin.procs[0] ? bin.procs[0].label() : "null"}\n})\n`;
123610
123610
  const total = jssource.length;
123611
123611
  const perc = (n) => ((100 * n) / total).toFixed(2) + "%";
@@ -123739,7 +123739,7 @@ function ${id}(s) {
123739
123739
  let id = s.breakpointInfo.id;
123740
123740
  let lbl;
123741
123741
  write(`s.lastBrkId = ${id};`);
123742
- if (bin.options.breakpoints) {
123742
+ if (bin.breakpoints) {
123743
123743
  lbl = ++lblIdx;
123744
123744
  let brkCall = `return breakpoint(s, ${lbl}, ${id}, r0);`;
123745
123745
  if (s.breakpointInfo.isDebuggerStmt) {
@@ -123747,12 +123747,12 @@ function ${id}(s) {
123747
123747
  }
123748
123748
  else {
123749
123749
  write(`if ((breakpoints[0] && isBreakFrame(s)) || breakpoints[${id}]) ${brkCall}`);
123750
- if (bin.options.trace) {
123750
+ if (bin.trace) {
123751
123751
  write(`else return trace(${id}, s, ${lbl}, ${proc.label()}.info);`);
123752
123752
  }
123753
123753
  }
123754
123754
  }
123755
- else if (bin.options.trace) {
123755
+ else if (bin.trace) {
123756
123756
  lbl = ++lblIdx;
123757
123757
  write(`return trace(${id}, s, ${lbl}, ${proc.label()}.info);`);
123758
123758
  }
@@ -124694,7 +124694,7 @@ ${info.id}_IfaceVT:
124694
124694
  }
124695
124695
  }
124696
124696
  /* eslint-disable no-trailing-spaces */
124697
- function vmEmit(bin, opts) {
124697
+ function vmEmit(bin, opts, cres) {
124698
124698
  let vmsource = `; VM start
124699
124699
  _img_start:
124700
124700
  ${pxtc.hexfile.hexPrelude()}
@@ -124798,7 +124798,7 @@ _start_${name}:
124798
124798
  + "\n.word 0, 0, 0 ; dummy entry to make sure not empty");
124799
124799
  section("numberLiterals", SectionType.NumberLiterals, () => ctx.dblText.join("\n")
124800
124800
  + "\n.word 0, 0 ; dummy entry to make sure not empty");
124801
- const cfg = bin.res.configData || [];
124801
+ const cfg = cres.configData || [];
124802
124802
  section("configData", SectionType.ConfigData, () => cfg.map(d => ` .word ${d.key}, ${d.value} ; ${d.name}=${d.value}`).join("\n")
124803
124803
  + "\n .word 0, 0");
124804
124804
  let s = ctx.opcodes.map(s => s == null ? "" : s).join("\x00") + "\x00";
@@ -130982,8 +130982,9 @@ var ts;
130982
130982
  }
130983
130983
  let bin = new Binary();
130984
130984
  let proc;
130985
- bin.res = res;
130986
- bin.options = opts;
130985
+ bin.trace = opts.trace;
130986
+ bin.breakpoints = opts.breakpoints;
130987
+ bin.name = opts.name;
130987
130988
  bin.target = opts.target;
130988
130989
  function reset() {
130989
130990
  bin.reset();
@@ -131209,29 +131210,8 @@ var ts;
131209
131210
  info.captured = true;
131210
131211
  }
131211
131212
  }
131212
- function recordAction(f) {
131213
- const r = f(bin);
131214
- if (needsUsingInfo)
131215
- bin.recordAction(currUsingContext, f);
131216
- return r;
131217
- }
131218
131213
  function getIfaceMemberId(name, markUsed = false) {
131219
- return recordAction(bin => {
131220
- if (markUsed) {
131221
- if (!pxtc.U.lookup(bin.explicitlyUsedIfaceMembers, name)) {
131222
- pxtc.U.assert(!bin.finalPass);
131223
- bin.explicitlyUsedIfaceMembers[name] = true;
131224
- }
131225
- }
131226
- let v = pxtc.U.lookup(bin.ifaceMemberMap, name);
131227
- if (v != null)
131228
- return v;
131229
- pxtc.U.assert(!bin.finalPass);
131230
- // this gets renumbered before the final pass
131231
- v = bin.ifaceMemberMap[name] = -1;
131232
- bin.emitString(name);
131233
- return v;
131234
- });
131214
+ return recordGetInterfaceId(bin, name, markUsed, needsUsingInfo, currUsingContext);
131235
131215
  }
131236
131216
  function finalEmit() {
131237
131217
  if (opts.noEmit)
@@ -131255,13 +131235,16 @@ var ts;
131255
131235
  bin.writeFile("platformio.json", JSON.stringify(extinfo.platformio, null, 2));
131256
131236
  });
131257
131237
  if (opts.target.nativeType == pxtc.NATIVE_TYPE_VM)
131258
- pxtc.vmEmit(bin, opts);
131238
+ pxtc.vmEmit(bin, opts, res);
131259
131239
  else
131260
131240
  pxtc.processorEmit(bin, opts, res);
131261
131241
  }
131262
131242
  else {
131263
- pxtc.jsEmit(bin);
131243
+ pxtc.jsEmit(bin, res);
131264
131244
  }
131245
+ // Clear writeFile so that we don't leak the reference to res, which
131246
+ // includes the entire source of the program
131247
+ bin.writeFile = undefined;
131265
131248
  }
131266
131249
  function typeCheckVar(tp) {
131267
131250
  if (tp.flags & ts.TypeFlags.Void) {
@@ -131978,9 +131961,7 @@ ${lbl}: .short 0xffff
131978
131961
  markUsed(decl);
131979
131962
  }
131980
131963
  function emitAndMarkString(str) {
131981
- return recordAction(bin => {
131982
- return bin.emitString(str);
131983
- });
131964
+ return recordEmitAndMarkString(bin, str, needsUsingInfo, currUsingContext);
131984
131965
  }
131985
131966
  function recordUsage(decl) {
131986
131967
  if (!needsUsingInfo)
@@ -132827,7 +132808,7 @@ ${lbl}: .short 0xffff
132827
132808
  pinfo.proc = myProc;
132828
132809
  myProc.usingCtx = currUsingContext;
132829
132810
  proc = myProc;
132830
- recordAction(bin => bin.addProc(myProc));
132811
+ recordAddProc(bin, myProc, needsUsingInfo, currUsingContext);
132831
132812
  }
132832
132813
  proc.captured = locals;
132833
132814
  const initalizedFields = [];
@@ -134744,7 +134725,7 @@ ${lbl}: .short 0xffff
134744
134725
  this.numStmts = 0;
134745
134726
  }
134746
134727
  getTitle() {
134747
- const title = this.options.name || pxtc.U.lf("Untitled");
134728
+ const title = this.name || pxtc.U.lf("Untitled");
134748
134729
  if (title.length >= 90)
134749
134730
  return title.slice(0, 87) + "...";
134750
134731
  else
@@ -134832,6 +134813,36 @@ ${lbl}: .short 0xffff
134832
134813
  return !!(type.flags & (ts.TypeFlags.NumberLike | ts.TypeFlags.EnumLike | ts.TypeFlags.BooleanLike));
134833
134814
  }
134834
134815
  }
134816
+ function recordAction(bin, needsUsingInfo, currUsingContext, f) {
134817
+ const r = f(bin);
134818
+ if (needsUsingInfo)
134819
+ bin.recordAction(currUsingContext, f);
134820
+ return r;
134821
+ }
134822
+ function recordAddProc(bin, proc, needsUsingInfo, currUsingContext) {
134823
+ recordAction(bin, needsUsingInfo, currUsingContext, b => b.addProc(proc));
134824
+ }
134825
+ function recordGetInterfaceId(bin, name, markUsed, needsUsingInfo, currUsingContext) {
134826
+ return recordAction(bin, needsUsingInfo, currUsingContext, bin => {
134827
+ if (markUsed) {
134828
+ if (!pxtc.U.lookup(bin.explicitlyUsedIfaceMembers, name)) {
134829
+ pxtc.U.assert(!bin.finalPass);
134830
+ bin.explicitlyUsedIfaceMembers[name] = true;
134831
+ }
134832
+ }
134833
+ let v = pxtc.U.lookup(bin.ifaceMemberMap, name);
134834
+ if (v != null)
134835
+ return v;
134836
+ pxtc.U.assert(!bin.finalPass);
134837
+ // this gets renumbered before the final pass
134838
+ v = bin.ifaceMemberMap[name] = -1;
134839
+ bin.emitString(name);
134840
+ return v;
134841
+ });
134842
+ }
134843
+ function recordEmitAndMarkString(bin, str, needsUsingInfo, currUsingContext) {
134844
+ return recordAction(bin, needsUsingInfo, currUsingContext, b => b.emitString(str));
134845
+ }
134835
134846
  })(pxtc = ts.pxtc || (ts.pxtc = {}));
134836
134847
  })(ts || (ts = {}));
134837
134848
  /// <reference path="../../localtypings/pxtarget.d.ts"/>
@@ -136855,7 +136866,7 @@ var ts;
136855
136866
  for (let i = 0; i < hd.length; ++i)
136856
136867
  pxt.HF2.write16(resbuf, i * 2 + ctx.jmpStartAddr, hd[i]);
136857
136868
  if (uf2 && !bin.target.switches.rawELF) {
136858
- let bn = bin.options.name || "pxt";
136869
+ let bn = bin.name || "pxt";
136859
136870
  bn = bn.replace(/[^a-zA-Z0-9\-\.]+/g, "_");
136860
136871
  uf2.filename = "Projects/" + bn + ".elf";
136861
136872
  pxtc.UF2.writeBytes(uf2, 0, resbuf);
@@ -137102,7 +137113,7 @@ ${lbl}: ${snippets.obj_header("pxt::number_vt")}
137102
137113
  }
137103
137114
  }
137104
137115
  pxtc.computeHashMultiplier = computeHashMultiplier;
137105
- function vtableToAsm(info, opts, bin) {
137116
+ function vtableToAsm(info, opts, bin, res) {
137106
137117
  /*
137107
137118
  uint16_t numbytes;
137108
137119
  ValType objectType;
@@ -137190,7 +137201,7 @@ ${hexfile.hexPrelude()}
137190
137201
  .hex 873266330af9dbdb ; replaced in binary by program hash
137191
137202
  `;
137192
137203
  }
137193
- function serialize(bin, opts) {
137204
+ function serialize(bin, opts, res) {
137194
137205
  let asmsource = `
137195
137206
  .short ${bin.globalsWords} ; num. globals
137196
137207
  .short 0 ; patched with number of 64 bit words resulting from assembly
@@ -137225,7 +137236,7 @@ ${hexfile.hexPrelude()}
137225
137236
  asmsource += snippets.arithmetic();
137226
137237
  asmsource += "_helpers_end:\n\n";
137227
137238
  bin.usedClassInfos.forEach(info => {
137228
- asmsource += vtableToAsm(info, opts, bin);
137239
+ asmsource += vtableToAsm(info, opts, bin, res);
137229
137240
  });
137230
137241
  asmsource += `\n.balign 4\n.object _pxt_iface_member_names\n_pxt_iface_member_names:\n`;
137231
137242
  asmsource += ` .word ${bin.ifaceMembers.length}\n`;
@@ -137237,7 +137248,7 @@ ${hexfile.hexPrelude()}
137237
137248
  asmsource += ` .word 0\n`;
137238
137249
  asmsource += "_vtables_end:\n\n";
137239
137250
  asmsource += `\n.balign 4\n.object _pxt_config_data\n_pxt_config_data:\n`;
137240
- const cfg = bin.res.configData || [];
137251
+ const cfg = res.configData || [];
137241
137252
  // asmsource += ` .word ${cfg.length}, 0 ; num. entries`
137242
137253
  for (let d of cfg) {
137243
137254
  asmsource += ` .word ${d.key}, ${d.value} ; ${d.name}=${d.value}\n`;
@@ -137506,7 +137517,7 @@ __flash_checksums:
137506
137517
  return elts.map(s => `"${s}"`).join(",");
137507
137518
  }
137508
137519
  function processorEmit(bin, opts, cres) {
137509
- const src = serialize(bin, opts);
137520
+ const src = serialize(bin, opts, cres);
137510
137521
  const opts0 = pxtc.U.flatClone(opts);
137511
137522
  // normally, this would already have been done, but if the main variant
137512
137523
  // is disabled, another variant may be set up
@@ -161739,11 +161750,6 @@ async function testSnippetsAsync(snippets, re, pyStrictSyntaxCheck) {
161739
161750
  }
161740
161751
  return;
161741
161752
  }
161742
- if (++codeSnippetCount % 40 == 0) {
161743
- // clean up cache every once in a while to speed up / clear up mem
161744
- // TODO probably this should be handled in the service host as it does become a perf concern
161745
- cleanService();
161746
- }
161747
161753
  const isPy = snippet.ext === "py";
161748
161754
  const inFiles = Object.assign({ [pxt.MAIN_TS]: isPy ? "" : snippet.code, [pxt.MAIN_PY]: isPy ? snippet.code : "", [pxt.MAIN_BLOCKS]: "" }, (snippet.extraFiles || {}));
161749
161755
  const { pkg, opts } = await getCompileResources(inFiles, snippet.packages);
@@ -156,7 +156,7 @@ declare namespace ts.pxtc {
156
156
  declare namespace ts.pxtc {
157
157
  function isBuiltinSimOp(name: string): boolean;
158
158
  function shimToJs(shimName: string): string;
159
- function jsEmit(bin: Binary): void;
159
+ function jsEmit(bin: Binary, cres: CompileResult): void;
160
160
  }
161
161
  declare namespace ts.pxtc {
162
162
  const thumbCmpMap: pxt.Map<string>;
@@ -203,7 +203,7 @@ declare namespace ts.pxtc {
203
203
  }
204
204
  }
205
205
  declare namespace ts.pxtc {
206
- function vmEmit(bin: Binary, opts: CompileOptions): void;
206
+ function vmEmit(bin: Binary, opts: CompileOptions, cres: CompileResult): void;
207
207
  }
208
208
  declare namespace ts.pxtc.decompiler {
209
209
  export enum DecompileParamKeys {
@@ -709,8 +709,9 @@ declare namespace ts.pxtc {
709
709
  finalPass: boolean;
710
710
  target: CompileTarget;
711
711
  writeFile: (fn: string, cont: string) => void;
712
- res: CompileResult;
713
- options: CompileOptions;
712
+ trace: boolean;
713
+ breakpoints: boolean;
714
+ name: string;
714
715
  usedClassInfos: ClassInfo[];
715
716
  checksumBlock: number[];
716
717
  numStmts: number;
@@ -833,7 +834,7 @@ declare namespace ts.pxtc {
833
834
  mapping: Uint16Array;
834
835
  size: number;
835
836
  };
836
- function vtableToAsm(info: ClassInfo, opts: CompileOptions, bin: Binary): string;
837
+ function vtableToAsm(info: ClassInfo, opts: CompileOptions, bin: Binary, res: CompileResult): string;
837
838
  function processorInlineAssemble(target: CompileTarget, src: string): number[];
838
839
  function assemble(target: CompileTarget, bin: Binary, src: string): {
839
840
  src: string;
@@ -612,7 +612,7 @@ var ts;
612
612
  // Assumptions:
613
613
  // - registers can hold a pointer (data or code)
614
614
  // - special registers include: sp
615
- // - fixed registers are r0, r1, r2, r3, r5, r6
615
+ // - fixed registers are r0, r1, r2, r3, r5, r6
616
616
  // - r0 is the current value (from expression evaluation)
617
617
  // - registers for runtime calls (r0, r1,r2,r3)
618
618
  // - r5 is for captured locals in lambda
@@ -625,7 +625,7 @@ var ts;
625
625
  class AssemblerSnippets {
626
626
  nop() { return "TBD(nop)"; }
627
627
  reg_gets_imm(reg, imm) { return "TBD(reg_gets_imm)"; }
628
- // Registers are stored on the stack in numerical order
628
+ // Registers are stored on the stack in numerical order
629
629
  proc_setup(numlocals, main) { return "TBD(proc_setup)"; }
630
630
  push_fixed(reg) { return "TBD(push_fixed)"; }
631
631
  push_local(reg) { return "TBD(push_local)"; }
@@ -840,7 +840,7 @@ ${baseLabel}_nochk:
840
840
  }
841
841
  }
842
842
  };
843
- if (this.bin.options.breakpoints) {
843
+ if (this.bin.breakpoints) {
844
844
  this.write(this.t.debugger_proc(bkptLabel));
845
845
  }
846
846
  this.baseStackSize = 1; // push {lr}
@@ -883,7 +883,7 @@ ${baseLabel}_nochk:
883
883
  this.write(`; ${s.expr.data}`);
884
884
  break;
885
885
  case pxtc.ir.SK.Breakpoint:
886
- if (this.bin.options.breakpoints) {
886
+ if (this.bin.breakpoints) {
887
887
  let lbl = `__brkp_${s.breakpointInfo.id}`;
888
888
  if (s.breakpointInfo.isDebuggerStmt) {
889
889
  this.write(this.t.debugger_stmt(lbl));
@@ -2282,7 +2282,7 @@ var ts;
2282
2282
  "bind",
2283
2283
  "leaveAccessor"
2284
2284
  ];
2285
- function jsEmit(bin) {
2285
+ function jsEmit(bin, cres) {
2286
2286
  let jssource = "(function (ectx) {\n'use strict';\n";
2287
2287
  for (let n of evalIfaceFields) {
2288
2288
  jssource += `const ${n} = ectx.${n};\n`;
@@ -2294,7 +2294,7 @@ var ts;
2294
2294
  jssource += "pxsim.setTitle(" + JSON.stringify(bin.getTitle()) + ");\n";
2295
2295
  let cfg = {};
2296
2296
  let cfgKey = {};
2297
- for (let ce of bin.res.configData || []) {
2297
+ for (let ce of cres.configData || []) {
2298
2298
  cfg[ce.key + ""] = ce.value;
2299
2299
  cfgKey[ce.name] = ce.key;
2300
2300
  }
@@ -2324,8 +2324,8 @@ var ts;
2324
2324
  bin.usedClassInfos.forEach(info => {
2325
2325
  jssource += vtableToJs(info);
2326
2326
  });
2327
- if (bin.res.breakpoints)
2328
- jssource += `\nconst breakpoints = setupDebugger(${bin.res.breakpoints.length}, [${bin.globals.filter(c => c.isUserVariable).map(c => `"${c.uniqueName()}"`).join(",")}])\n`;
2327
+ if (cres.breakpoints)
2328
+ jssource += `\nconst breakpoints = setupDebugger(${cres.breakpoints.length}, [${bin.globals.filter(c => c.isUserVariable).map(c => `"${c.uniqueName()}"`).join(",")}])\n`;
2329
2329
  jssource += `\nreturn ${bin.procs[0] ? bin.procs[0].label() : "null"}\n})\n`;
2330
2330
  const total = jssource.length;
2331
2331
  const perc = (n) => ((100 * n) / total).toFixed(2) + "%";
@@ -2459,7 +2459,7 @@ function ${id}(s) {
2459
2459
  let id = s.breakpointInfo.id;
2460
2460
  let lbl;
2461
2461
  write(`s.lastBrkId = ${id};`);
2462
- if (bin.options.breakpoints) {
2462
+ if (bin.breakpoints) {
2463
2463
  lbl = ++lblIdx;
2464
2464
  let brkCall = `return breakpoint(s, ${lbl}, ${id}, r0);`;
2465
2465
  if (s.breakpointInfo.isDebuggerStmt) {
@@ -2467,12 +2467,12 @@ function ${id}(s) {
2467
2467
  }
2468
2468
  else {
2469
2469
  write(`if ((breakpoints[0] && isBreakFrame(s)) || breakpoints[${id}]) ${brkCall}`);
2470
- if (bin.options.trace) {
2470
+ if (bin.trace) {
2471
2471
  write(`else return trace(${id}, s, ${lbl}, ${proc.label()}.info);`);
2472
2472
  }
2473
2473
  }
2474
2474
  }
2475
- else if (bin.options.trace) {
2475
+ else if (bin.trace) {
2476
2476
  lbl = ++lblIdx;
2477
2477
  write(`return trace(${id}, s, ${lbl}, ${proc.label()}.info);`);
2478
2478
  }
@@ -3414,7 +3414,7 @@ ${info.id}_IfaceVT:
3414
3414
  }
3415
3415
  }
3416
3416
  /* eslint-disable no-trailing-spaces */
3417
- function vmEmit(bin, opts) {
3417
+ function vmEmit(bin, opts, cres) {
3418
3418
  let vmsource = `; VM start
3419
3419
  _img_start:
3420
3420
  ${pxtc.hexfile.hexPrelude()}
@@ -3518,7 +3518,7 @@ _start_${name}:
3518
3518
  + "\n.word 0, 0, 0 ; dummy entry to make sure not empty");
3519
3519
  section("numberLiterals", SectionType.NumberLiterals, () => ctx.dblText.join("\n")
3520
3520
  + "\n.word 0, 0 ; dummy entry to make sure not empty");
3521
- const cfg = bin.res.configData || [];
3521
+ const cfg = cres.configData || [];
3522
3522
  section("configData", SectionType.ConfigData, () => cfg.map(d => ` .word ${d.key}, ${d.value} ; ${d.name}=${d.value}`).join("\n")
3523
3523
  + "\n .word 0, 0");
3524
3524
  let s = ctx.opcodes.map(s => s == null ? "" : s).join("\x00") + "\x00";
@@ -9702,8 +9702,9 @@ var ts;
9702
9702
  }
9703
9703
  let bin = new Binary();
9704
9704
  let proc;
9705
- bin.res = res;
9706
- bin.options = opts;
9705
+ bin.trace = opts.trace;
9706
+ bin.breakpoints = opts.breakpoints;
9707
+ bin.name = opts.name;
9707
9708
  bin.target = opts.target;
9708
9709
  function reset() {
9709
9710
  bin.reset();
@@ -9929,29 +9930,8 @@ var ts;
9929
9930
  info.captured = true;
9930
9931
  }
9931
9932
  }
9932
- function recordAction(f) {
9933
- const r = f(bin);
9934
- if (needsUsingInfo)
9935
- bin.recordAction(currUsingContext, f);
9936
- return r;
9937
- }
9938
9933
  function getIfaceMemberId(name, markUsed = false) {
9939
- return recordAction(bin => {
9940
- if (markUsed) {
9941
- if (!pxtc.U.lookup(bin.explicitlyUsedIfaceMembers, name)) {
9942
- pxtc.U.assert(!bin.finalPass);
9943
- bin.explicitlyUsedIfaceMembers[name] = true;
9944
- }
9945
- }
9946
- let v = pxtc.U.lookup(bin.ifaceMemberMap, name);
9947
- if (v != null)
9948
- return v;
9949
- pxtc.U.assert(!bin.finalPass);
9950
- // this gets renumbered before the final pass
9951
- v = bin.ifaceMemberMap[name] = -1;
9952
- bin.emitString(name);
9953
- return v;
9954
- });
9934
+ return recordGetInterfaceId(bin, name, markUsed, needsUsingInfo, currUsingContext);
9955
9935
  }
9956
9936
  function finalEmit() {
9957
9937
  if (opts.noEmit)
@@ -9975,13 +9955,16 @@ var ts;
9975
9955
  bin.writeFile("platformio.json", JSON.stringify(extinfo.platformio, null, 2));
9976
9956
  });
9977
9957
  if (opts.target.nativeType == pxtc.NATIVE_TYPE_VM)
9978
- pxtc.vmEmit(bin, opts);
9958
+ pxtc.vmEmit(bin, opts, res);
9979
9959
  else
9980
9960
  pxtc.processorEmit(bin, opts, res);
9981
9961
  }
9982
9962
  else {
9983
- pxtc.jsEmit(bin);
9963
+ pxtc.jsEmit(bin, res);
9984
9964
  }
9965
+ // Clear writeFile so that we don't leak the reference to res, which
9966
+ // includes the entire source of the program
9967
+ bin.writeFile = undefined;
9985
9968
  }
9986
9969
  function typeCheckVar(tp) {
9987
9970
  if (tp.flags & ts.TypeFlags.Void) {
@@ -10698,9 +10681,7 @@ ${lbl}: .short 0xffff
10698
10681
  markUsed(decl);
10699
10682
  }
10700
10683
  function emitAndMarkString(str) {
10701
- return recordAction(bin => {
10702
- return bin.emitString(str);
10703
- });
10684
+ return recordEmitAndMarkString(bin, str, needsUsingInfo, currUsingContext);
10704
10685
  }
10705
10686
  function recordUsage(decl) {
10706
10687
  if (!needsUsingInfo)
@@ -11547,7 +11528,7 @@ ${lbl}: .short 0xffff
11547
11528
  pinfo.proc = myProc;
11548
11529
  myProc.usingCtx = currUsingContext;
11549
11530
  proc = myProc;
11550
- recordAction(bin => bin.addProc(myProc));
11531
+ recordAddProc(bin, myProc, needsUsingInfo, currUsingContext);
11551
11532
  }
11552
11533
  proc.captured = locals;
11553
11534
  const initalizedFields = [];
@@ -13464,7 +13445,7 @@ ${lbl}: .short 0xffff
13464
13445
  this.numStmts = 0;
13465
13446
  }
13466
13447
  getTitle() {
13467
- const title = this.options.name || pxtc.U.lf("Untitled");
13448
+ const title = this.name || pxtc.U.lf("Untitled");
13468
13449
  if (title.length >= 90)
13469
13450
  return title.slice(0, 87) + "...";
13470
13451
  else
@@ -13552,6 +13533,36 @@ ${lbl}: .short 0xffff
13552
13533
  return !!(type.flags & (ts.TypeFlags.NumberLike | ts.TypeFlags.EnumLike | ts.TypeFlags.BooleanLike));
13553
13534
  }
13554
13535
  }
13536
+ function recordAction(bin, needsUsingInfo, currUsingContext, f) {
13537
+ const r = f(bin);
13538
+ if (needsUsingInfo)
13539
+ bin.recordAction(currUsingContext, f);
13540
+ return r;
13541
+ }
13542
+ function recordAddProc(bin, proc, needsUsingInfo, currUsingContext) {
13543
+ recordAction(bin, needsUsingInfo, currUsingContext, b => b.addProc(proc));
13544
+ }
13545
+ function recordGetInterfaceId(bin, name, markUsed, needsUsingInfo, currUsingContext) {
13546
+ return recordAction(bin, needsUsingInfo, currUsingContext, bin => {
13547
+ if (markUsed) {
13548
+ if (!pxtc.U.lookup(bin.explicitlyUsedIfaceMembers, name)) {
13549
+ pxtc.U.assert(!bin.finalPass);
13550
+ bin.explicitlyUsedIfaceMembers[name] = true;
13551
+ }
13552
+ }
13553
+ let v = pxtc.U.lookup(bin.ifaceMemberMap, name);
13554
+ if (v != null)
13555
+ return v;
13556
+ pxtc.U.assert(!bin.finalPass);
13557
+ // this gets renumbered before the final pass
13558
+ v = bin.ifaceMemberMap[name] = -1;
13559
+ bin.emitString(name);
13560
+ return v;
13561
+ });
13562
+ }
13563
+ function recordEmitAndMarkString(bin, str, needsUsingInfo, currUsingContext) {
13564
+ return recordAction(bin, needsUsingInfo, currUsingContext, b => b.emitString(str));
13565
+ }
13555
13566
  })(pxtc = ts.pxtc || (ts.pxtc = {}));
13556
13567
  })(ts || (ts = {}));
13557
13568
  /// <reference path="../../localtypings/pxtarget.d.ts"/>
@@ -15575,7 +15586,7 @@ var ts;
15575
15586
  for (let i = 0; i < hd.length; ++i)
15576
15587
  pxt.HF2.write16(resbuf, i * 2 + ctx.jmpStartAddr, hd[i]);
15577
15588
  if (uf2 && !bin.target.switches.rawELF) {
15578
- let bn = bin.options.name || "pxt";
15589
+ let bn = bin.name || "pxt";
15579
15590
  bn = bn.replace(/[^a-zA-Z0-9\-\.]+/g, "_");
15580
15591
  uf2.filename = "Projects/" + bn + ".elf";
15581
15592
  pxtc.UF2.writeBytes(uf2, 0, resbuf);
@@ -15822,7 +15833,7 @@ ${lbl}: ${snippets.obj_header("pxt::number_vt")}
15822
15833
  }
15823
15834
  }
15824
15835
  pxtc.computeHashMultiplier = computeHashMultiplier;
15825
- function vtableToAsm(info, opts, bin) {
15836
+ function vtableToAsm(info, opts, bin, res) {
15826
15837
  /*
15827
15838
  uint16_t numbytes;
15828
15839
  ValType objectType;
@@ -15910,7 +15921,7 @@ ${hexfile.hexPrelude()}
15910
15921
  .hex 873266330af9dbdb ; replaced in binary by program hash
15911
15922
  `;
15912
15923
  }
15913
- function serialize(bin, opts) {
15924
+ function serialize(bin, opts, res) {
15914
15925
  let asmsource = `
15915
15926
  .short ${bin.globalsWords} ; num. globals
15916
15927
  .short 0 ; patched with number of 64 bit words resulting from assembly
@@ -15945,7 +15956,7 @@ ${hexfile.hexPrelude()}
15945
15956
  asmsource += snippets.arithmetic();
15946
15957
  asmsource += "_helpers_end:\n\n";
15947
15958
  bin.usedClassInfos.forEach(info => {
15948
- asmsource += vtableToAsm(info, opts, bin);
15959
+ asmsource += vtableToAsm(info, opts, bin, res);
15949
15960
  });
15950
15961
  asmsource += `\n.balign 4\n.object _pxt_iface_member_names\n_pxt_iface_member_names:\n`;
15951
15962
  asmsource += ` .word ${bin.ifaceMembers.length}\n`;
@@ -15957,7 +15968,7 @@ ${hexfile.hexPrelude()}
15957
15968
  asmsource += ` .word 0\n`;
15958
15969
  asmsource += "_vtables_end:\n\n";
15959
15970
  asmsource += `\n.balign 4\n.object _pxt_config_data\n_pxt_config_data:\n`;
15960
- const cfg = bin.res.configData || [];
15971
+ const cfg = res.configData || [];
15961
15972
  // asmsource += ` .word ${cfg.length}, 0 ; num. entries`
15962
15973
  for (let d of cfg) {
15963
15974
  asmsource += ` .word ${d.key}, ${d.value} ; ${d.name}=${d.value}\n`;
@@ -16226,7 +16237,7 @@ __flash_checksums:
16226
16237
  return elts.map(s => `"${s}"`).join(",");
16227
16238
  }
16228
16239
  function processorEmit(bin, opts, cres) {
16229
- const src = serialize(bin, opts);
16240
+ const src = serialize(bin, opts, cres);
16230
16241
  const opts0 = pxtc.U.flatClone(opts);
16231
16242
  // normally, this would already have been done, but if the main variant
16232
16243
  // is disabled, another variant may be set up