pxt-core 8.2.2 → 8.2.5

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/pxt.js CHANGED
@@ -106399,14 +106399,32 @@ var pxt;
106399
106399
  docs.prepTemplate = prepTemplate;
106400
106400
  function setupRenderer(renderer) {
106401
106401
  renderer.image = function (href, title, text) {
106402
- const endpointName = "makecode-lucas-testing-makecodetempmediaservice-usea";
106402
+ var _a, _b;
106403
+ const endpointName = "makecodeprodmediaeastus-usea";
106403
106404
  if (href.startsWith("youtube:")) {
106404
- let out = '<div class="tutorial-video-embed"><iframe src="https://www.youtube.com/embed/' + href.split(":").pop()
106405
- + '" title="' + title + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
106405
+ let out = '<div class="tutorial-video-embed"><iframe class="yt-embed" src="https://www.youtube.com/embed/' + href.split(":").pop()
106406
+ + '" title="' + text + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
106406
106407
  return out;
106407
106408
  }
106408
106409
  else if (href.startsWith("azuremedia:")) {
106409
- let out = `<div class="tutorial-video-embed"><video class="ams-embed" controls src="https://${endpointName}.streaming.media.azure.net/` + href.split(":").pop() + '/manifest(format=mpd-time-cmaf)" /></div>';
106410
+ let videoID = href.split(":")[1];
106411
+ const flagsSplit = videoID.split("?");
106412
+ let startTime;
106413
+ let endTime;
106414
+ if (flagsSplit[1]) {
106415
+ videoID = flagsSplit[0];
106416
+ const passedParameters = flagsSplit[1];
106417
+ startTime = (_a = /start(?:time)?=(\d+)/i.exec(passedParameters)) === null || _a === void 0 ? void 0 : _a[1];
106418
+ endTime = (_b = /end(?:time)?=(\d+)/i.exec(passedParameters)) === null || _b === void 0 ? void 0 : _b[1];
106419
+ }
106420
+ const url = new URL(`https://${endpointName}.streaming.media.azure.net/${videoID}/manifest(format=mpd-time-csf).mpd`);
106421
+ if (startTime) {
106422
+ url.hash = `t=${startTime}`;
106423
+ }
106424
+ if (endTime) {
106425
+ url.searchParams.append("endTime", endTime);
106426
+ }
106427
+ let out = `<div class="tutorial-video-embed"><video class="ams-embed" controls src="${url.toString()}" /></div>`;
106410
106428
  return out;
106411
106429
  }
106412
106430
  else {
@@ -108186,14 +108204,17 @@ var pxt;
108186
108204
  return false;
108187
108205
  }
108188
108206
  function isRepoBanned(repo, config) {
108207
+ var _a, _b;
108189
108208
  if (isOrgBanned(repo, config))
108190
108209
  return true;
108191
108210
  if (!config)
108192
108211
  return false; // don't know
108193
- if (!repo || !repo.fullName)
108212
+ if (!repo)
108194
108213
  return true;
108214
+ const repoFull = (_a = repo.fullName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
108215
+ const repoSlug = (_b = repo.slug) === null || _b === void 0 ? void 0 : _b.toLowerCase();
108195
108216
  if (config.bannedRepos
108196
- && config.bannedRepos.some(fn => fn.toLowerCase() == repo.fullName.toLowerCase()))
108217
+ && config.bannedRepos.some(fn => fn && (fn.toLowerCase() == repoFull || fn.toLowerCase() == repoSlug)))
108197
108218
  return true;
108198
108219
  return false;
108199
108220
  }
@@ -108207,13 +108228,15 @@ var pxt;
108207
108228
  return false;
108208
108229
  }
108209
108230
  function isRepoApproved(repo, config) {
108210
- var _a;
108231
+ var _a, _b;
108211
108232
  if (isOrgApproved(repo, config))
108212
108233
  return true;
108213
- if (!repo || !config)
108234
+ const repoFull = (_a = repo === null || repo === void 0 ? void 0 : repo.fullName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
108235
+ const repoSlug = (_b = repo === null || repo === void 0 ? void 0 : repo.slug) === null || _b === void 0 ? void 0 : _b.toLowerCase();
108236
+ if (!(config === null || config === void 0 ? void 0 : config.approvedRepoLib) || !(repoFull || repoSlug))
108214
108237
  return false;
108215
- if (repo.fullName
108216
- && ((_a = config.approvedRepoLib) === null || _a === void 0 ? void 0 : _a[repo.fullName.toLowerCase()]))
108238
+ if (config.approvedRepoLib[repoFull]
108239
+ || config.approvedRepoLib[repoSlug])
108217
108240
  return true;
108218
108241
  return false;
108219
108242
  }
@@ -111956,7 +111979,7 @@ var pxt;
111956
111979
  // and pulls from master
111957
111980
  const modtag = (modid === null || modid === void 0 ? void 0 : modid.tag) || ((_a = mod.config) === null || _a === void 0 ? void 0 : _a.version);
111958
111981
  const vertag = verid.tag;
111959
- // if there is no tag on the current dependency,
111982
+ // if there is no tag on the current dependency,
111960
111983
  // assume same as existing module version if any
111961
111984
  if (modtag && !vertag) {
111962
111985
  pxt.debug(`unversioned ${ver}, using ${modtag}`);
@@ -112415,6 +112438,8 @@ var pxt;
112415
112438
  opts.otherMultiVariants.push(etarget);
112416
112439
  }
112417
112440
  else {
112441
+ etarget.target.isNative = opts.target.isNative;
112442
+ opts.target = etarget.target;
112418
112443
  ext = einfo;
112419
112444
  opts.otherMultiVariants = [];
112420
112445
  }
@@ -113370,7 +113395,12 @@ var ts;
113370
113395
  const left = param.substr(0, dotIdx);
113371
113396
  let right = param.substr(dotIdx + 1);
113372
113397
  right = pxtc.U.snakify(right).toUpperCase();
113373
- return `${left}.${right}`;
113398
+ if (left) {
113399
+ return `${left}.${right}`;
113400
+ }
113401
+ else {
113402
+ return right;
113403
+ }
113374
113404
  }
113375
113405
  return param;
113376
113406
  }
@@ -114591,6 +114621,97 @@ var pxt;
114591
114621
  return outParts.join(" ");
114592
114622
  }
114593
114623
  }
114624
+ function soundToInstructionBuffer(sound, fxSteps, fxRange) {
114625
+ const { startFrequency, endFrequency, startVolume, endVolume, interpolation, duration } = sound;
114626
+ const steps = [];
114627
+ // Optimize the simple case
114628
+ if (sound.interpolation === "linear" && sound.effect === "none") {
114629
+ steps.push({
114630
+ frequency: startFrequency,
114631
+ volume: (startVolume / assets.MAX_VOLUME) * 1024,
114632
+ });
114633
+ steps.push({
114634
+ frequency: endFrequency,
114635
+ volume: (endVolume / assets.MAX_VOLUME) * 1024,
114636
+ });
114637
+ }
114638
+ else {
114639
+ fxSteps = Math.min(fxSteps, Math.floor(duration / 5));
114640
+ const getVolumeAt = (t) => ((startVolume + t * (endVolume - startVolume) / duration) / assets.MAX_VOLUME) * 1024;
114641
+ let getFrequencyAt;
114642
+ switch (interpolation) {
114643
+ case "linear":
114644
+ getFrequencyAt = t => startFrequency + t * (endFrequency - startFrequency) / duration;
114645
+ break;
114646
+ case "curve":
114647
+ getFrequencyAt = t => startFrequency + (endFrequency - startFrequency) * Math.sin(t / duration * (Math.PI / 2));
114648
+ break;
114649
+ case "logarithmic":
114650
+ getFrequencyAt = t => startFrequency + Math.log10(1 + 9 * (t / duration)) * (endFrequency - startFrequency);
114651
+ break;
114652
+ }
114653
+ const timeSlice = duration / fxSteps;
114654
+ for (let i = 0; i < fxSteps; i++) {
114655
+ const newStep = {
114656
+ frequency: Math.max(getFrequencyAt(i * timeSlice), 1),
114657
+ volume: getVolumeAt(i * timeSlice)
114658
+ };
114659
+ if (sound.effect === "tremolo") {
114660
+ if (i % 2 === 0) {
114661
+ newStep.volume = Math.max(newStep.volume - fxRange * 500, 0);
114662
+ }
114663
+ else {
114664
+ newStep.volume = Math.min(newStep.volume + fxRange * 500, 1023);
114665
+ }
114666
+ }
114667
+ else if (sound.effect === "vibrato") {
114668
+ if (i % 2 === 0) {
114669
+ newStep.frequency = Math.max(newStep.frequency - fxRange * 100, 1);
114670
+ }
114671
+ else {
114672
+ newStep.frequency = newStep.frequency + fxRange * 100;
114673
+ }
114674
+ }
114675
+ else if (sound.effect === "warble") {
114676
+ if (i % 2 === 0) {
114677
+ newStep.frequency = Math.max(newStep.frequency - fxRange * 1000, 1);
114678
+ }
114679
+ else {
114680
+ newStep.frequency = newStep.frequency + fxRange * 1000;
114681
+ }
114682
+ }
114683
+ steps.push(newStep);
114684
+ }
114685
+ }
114686
+ const out = new Uint8Array(12 * (steps.length - 1));
114687
+ const stepDuration = Math.floor(duration / (steps.length - 1));
114688
+ for (let i = 0; i < steps.length - 1; i++) {
114689
+ const offset = i * 12;
114690
+ out[offset] = waveToValue(sound.wave);
114691
+ set16BitNumber(out, offset + 2, steps[i].frequency);
114692
+ set16BitNumber(out, offset + 4, stepDuration);
114693
+ set16BitNumber(out, offset + 6, steps[i].volume);
114694
+ set16BitNumber(out, offset + 8, steps[i + 1].volume);
114695
+ set16BitNumber(out, offset + 10, steps[i + 1].frequency);
114696
+ }
114697
+ return out;
114698
+ }
114699
+ assets.soundToInstructionBuffer = soundToInstructionBuffer;
114700
+ function waveToValue(wave) {
114701
+ switch (wave) {
114702
+ case "square": return 15;
114703
+ case "sine": return 3;
114704
+ case "triangle": return 1;
114705
+ case "noise": return 18;
114706
+ case "sawtooth": return 2;
114707
+ }
114708
+ }
114709
+ function set16BitNumber(buf, offset, value) {
114710
+ const temp = new Uint8Array(2);
114711
+ new Uint16Array(temp.buffer)[0] = value | 0;
114712
+ buf[offset] = temp[0];
114713
+ buf[offset + 1] = temp[1];
114714
+ }
114594
114715
  })(assets = pxt.assets || (pxt.assets = {}));
114595
114716
  })(pxt || (pxt = {}));
114596
114717
  // See https://github.com/microsoft/TouchDevelop-backend/blob/master/docs/streams.md
@@ -119193,6 +119314,18 @@ var ts;
119193
119314
  }
119194
119315
  }
119195
119316
  assembler.Line = Line;
119317
+ const MAX_OBJ_USERS = 5;
119318
+ class AsmObject {
119319
+ constructor(id, description) {
119320
+ this.id = id;
119321
+ this.description = description;
119322
+ this.sizeAdj = 0;
119323
+ this.users = [];
119324
+ }
119325
+ get size() {
119326
+ return (this.endLocation - this.startLocation) - this.sizeAdj;
119327
+ }
119328
+ }
119196
119329
  // File is the center of the action: parsing a file into a sequence of Lines
119197
119330
  // and also emitting the binary (buf)
119198
119331
  class File {
@@ -119217,6 +119350,11 @@ var ts;
119217
119350
  this.throwOnError = false;
119218
119351
  this.disablePeepHole = false;
119219
119352
  this.stackAtLabel = {};
119353
+ this.codeSizeStats = false;
119354
+ this.labelToObject = {};
119355
+ this.idToObject = {};
119356
+ this.objSuspendStart = 0;
119357
+ this.labelsToObjectDone = false;
119220
119358
  this.currLine = new Line(this, "<start>");
119221
119359
  this.currLine.lineNo = 0;
119222
119360
  this.ei = ei;
@@ -119236,6 +119374,15 @@ var ts;
119236
119374
  pc() {
119237
119375
  return this.location() + this.baseOffset;
119238
119376
  }
119377
+ useLabel(name) {
119378
+ if (!this.currObject || name[0] == '.' || this.objSuspendStart)
119379
+ return;
119380
+ const obj = pxtc.U.lookup(this.labelToObject, name);
119381
+ if (!obj || obj == this.currObject)
119382
+ return;
119383
+ if (obj.users.length < MAX_OBJ_USERS && obj.users.indexOf(this.currObject) < 0)
119384
+ obj.users.push(this.currObject);
119385
+ }
119239
119386
  // parsing of an "integer", well actually much more than
119240
119387
  // just that
119241
119388
  parseOneInt(s) {
@@ -119365,6 +119512,7 @@ var ts;
119365
119512
  return name;
119366
119513
  }
119367
119514
  lookupLabel(name, direct = false) {
119515
+ this.useLabel(name);
119368
119516
  let v = null;
119369
119517
  let scoped = this.scopedName(name);
119370
119518
  if (this.labels.hasOwnProperty(scoped)) {
@@ -119523,6 +119671,37 @@ var ts;
119523
119671
  };
119524
119672
  let num0;
119525
119673
  switch (words[0]) {
119674
+ case ".object":
119675
+ if (!this.codeSizeStats) {
119676
+ // do nothing
119677
+ }
119678
+ else if (words[1] == "PUSH") {
119679
+ this.objSuspendStart = this.location();
119680
+ }
119681
+ else if (words[1] == "POP") {
119682
+ if (this.objSuspendStart)
119683
+ this.currObject.sizeAdj += this.location() - this.objSuspendStart;
119684
+ this.objSuspendStart = 0;
119685
+ }
119686
+ else {
119687
+ if (this.currObject)
119688
+ this.currObject.endLocation = this.location();
119689
+ this.currObject = pxtc.U.lookup(this.idToObject, words[1]);
119690
+ if (!this.currObject) {
119691
+ const str = l.text.replace(/^[^"]*/, "");
119692
+ let parsed = words[1];
119693
+ if (words.length > 2) {
119694
+ parsed = parseString(str.trim());
119695
+ if (parsed == null)
119696
+ this.directiveError(lf("expecting string in .object"));
119697
+ }
119698
+ this.currObject = new AsmObject(words[1], parsed);
119699
+ this.idToObject[words[1]] = this.currObject;
119700
+ }
119701
+ this.currObject.sizeAdj = 0;
119702
+ this.currObject.startLocation = this.location();
119703
+ }
119704
+ break;
119526
119705
  case ".ascii":
119527
119706
  case ".asciz":
119528
119707
  case ".string":
@@ -119717,6 +119896,8 @@ var ts;
119717
119896
  }
119718
119897
  }
119719
119898
  handleOneInstruction(ln, instr) {
119899
+ if (this.codeSizeStats && ln.ldlitLabel)
119900
+ this.useLabel(ln.ldlitLabel);
119720
119901
  let op = instr.emit(ln);
119721
119902
  if (!op.error) {
119722
119903
  this.stack += op.stack;
@@ -119825,6 +120006,8 @@ var ts;
119825
120006
  if (l.words.length == 0)
119826
120007
  return;
119827
120008
  if (l.type == "label") {
120009
+ if (this.currObject && !this.labelsToObjectDone && l.words[0][0] != '.')
120010
+ this.labelToObject[l.words[0]] = this.currObject;
119828
120011
  let lblname = this.scopedName(l.words[0]);
119829
120012
  this.prevLabel = lblname;
119830
120013
  if (this.finalEmit) {
@@ -119865,6 +120048,8 @@ var ts;
119865
120048
  pxtc.oops();
119866
120049
  }
119867
120050
  });
120051
+ this.labelsToObjectDone = true;
120052
+ this.currObject = null;
119868
120053
  }
119869
120054
  getSourceMap() {
119870
120055
  const sourceMap = {};
@@ -119897,6 +120082,22 @@ var ts;
119897
120082
  }
119898
120083
  return sourceMap;
119899
120084
  }
120085
+ getCodeSizeStats() {
120086
+ if (!this.codeSizeStats)
120087
+ return "";
120088
+ const objs = pxtc.U.values(this.idToObject);
120089
+ objs.sort((a, b) => b.size - a.size);
120090
+ let r = ";\n; Code size:\n;\n";
120091
+ for (const obj of objs) {
120092
+ r += `; ${(" " + obj.size).slice(-6)} ${obj.description} [${obj.id}]\n`;
120093
+ if (obj.users.length >= MAX_OBJ_USERS)
120094
+ r += `; by many, including ${obj.users[0].description}\n`;
120095
+ else
120096
+ for (const x of obj.users)
120097
+ r += `; by ${x.description} [${x.id}]\n`;
120098
+ }
120099
+ return r;
120100
+ }
119900
120101
  getSource(clean, numStmts = 1, flashSize = 0) {
119901
120102
  let lenPrev = 0;
119902
120103
  let size = (lbl) => {
@@ -119912,8 +120113,11 @@ var ts;
119912
120113
  let lenLiterals = size("_literals_end");
119913
120114
  let lenAllCode = lenPrev;
119914
120115
  let totalSize = (lenTotal + this.baseOffset) & 0xffffff;
119915
- if (flashSize && totalSize > flashSize)
119916
- pxtc.U.userError(lf("program too big by {0} bytes!", totalSize - flashSize));
120116
+ if (flashSize && totalSize > flashSize) {
120117
+ const e = new Error(lf("program too big by {0} bytes!", totalSize - flashSize));
120118
+ e.ksErrorCode = 9283;
120119
+ throw e;
120120
+ }
119917
120121
  flashSize = flashSize || 128 * 1024;
119918
120122
  let totalInfo = lf("; total bytes: {0} ({1}% of {2}k flash with {3} free)", totalSize, (100 * totalSize / flashSize).toFixed(1), (flashSize / 1024).toFixed(1), flashSize - totalSize);
119919
120123
  let res =
@@ -119921,7 +120125,7 @@ var ts;
119921
120125
  lf("; generated code sizes (bytes): {0} (incl. {1} user, {2} helpers, {3} vtables, {4} lits); src size {5}\n", lenAllCode, lenCode, lenHelpers, lenVtables, lenLiterals, lenTotal - lenAllCode) +
119922
120126
  lf("; assembly: {0} lines; density: {1} bytes/stmt; ({2} stmts)\n", this.lines.length, Math.round(100 * lenCode / numStmts) / 100, numStmts) +
119923
120127
  totalInfo + "\n" +
119924
- this.stats + "\n\n";
120128
+ this.stats + this.getCodeSizeStats() + "\n\n";
119925
120129
  let skipOne = false;
119926
120130
  this.lines.forEach((ln, i) => {
119927
120131
  if (ln.words[0] == "_stored_program") {
@@ -121722,6 +121926,7 @@ var ts;
121722
121926
  const info = utf8AsmStringLiteral(strLit);
121723
121927
  return `
121724
121928
  .balign 4
121929
+ .object ${lbl}
121725
121930
  ${lbl}: ${this.obj_header(info.vt)}
121726
121931
  ${info.asm}
121727
121932
  `;
@@ -121732,6 +121937,7 @@ var ts;
121732
121937
  const align = /f{16}/i.test(data) ? 8 : 4;
121733
121938
  return `
121734
121939
  .balign ${align}
121940
+ .object ${lbl}
121735
121941
  ${lbl}: ${this.obj_header("pxt::buffer_vt")}
121736
121942
  ${hexLiteralAsm(data)}
121737
121943
  `;
@@ -121841,6 +122047,7 @@ ${hexLiteralAsm(data)}
121841
122047
  ;
121842
122048
  `);
121843
122049
  let baseLabel = this.proc.label();
122050
+ this.write(`.object ${baseLabel} ${JSON.stringify(this.proc.getFullName())}`);
121844
122051
  let preLabel = baseLabel + "_pre";
121845
122052
  let bkptLabel = baseLabel + "_bkpt";
121846
122053
  let locLabel = baseLabel + "_locals";
@@ -122205,9 +122412,13 @@ ${baseLabel}_nochk:
122205
122412
  this.writeFailBranch();
122206
122413
  });
122207
122414
  }
122415
+ helperObject(desc) {
122416
+ return `.object _pxt_helper_${desc.replace(/[^\w]+/g, "_")} "helper: ${desc}"`;
122417
+ }
122208
122418
  emitBindHelper() {
122209
122419
  const maxArgs = 12;
122210
122420
  this.write(`
122421
+ ${this.helperObject("bind")}
122211
122422
  .section code
122212
122423
  _pxt_bind_helper:
122213
122424
  push {r0, r2}
@@ -122682,6 +122893,7 @@ ${baseLabel}_nochk:
122682
122893
  emitFieldMethods() {
122683
122894
  for (let op of ["get", "set"]) {
122684
122895
  this.write(`
122896
+ ${this.helperObject(op)}
122685
122897
  .section code
122686
122898
  _pxt_map_${op}:
122687
122899
  `);
@@ -122723,6 +122935,7 @@ ${baseLabel}_nochk:
122723
122935
  }
122724
122936
  emitArrayMethod(op, isBuffer) {
122725
122937
  this.write(`
122938
+ ${this.helperObject(op + " " + (isBuffer ? "buffer" : "array"))}
122726
122939
  .section code
122727
122940
  _pxt_${isBuffer ? "buffer" : "array"}_${op}:
122728
122941
  `);
@@ -122807,6 +123020,7 @@ ${baseLabel}_nochk:
122807
123020
  emitLambdaTrampoline() {
122808
123021
  let r3 = pxtc.target.stackAlign ? "r3," : "";
122809
123022
  this.write(`
123023
+ ${this.helperObject("trampoline")}
122810
123024
  .section code
122811
123025
  _pxt_lambda_trampoline:
122812
123026
  push {${r3} r4, r5, r6, r7, lr}
@@ -122846,6 +123060,7 @@ ${baseLabel}_nochk:
122846
123060
  mov r11, r7
122847
123061
  pop {${r3} r4, r5, r6, r7, pc}`);
122848
123062
  this.write(`
123063
+ ${this.helperObject("exn")}
122849
123064
  .section code
122850
123065
  ; r0 - try frame
122851
123066
  ; r1 - handler PC
@@ -122874,6 +123089,7 @@ ${baseLabel}_nochk:
122874
123089
  bx r1
122875
123090
  `);
122876
123091
  this.write(`
123092
+ ${this.helperObject("stringconv")}
122877
123093
  .section code
122878
123094
  _pxt_stringConv:
122879
123095
  `);
@@ -124188,6 +124404,7 @@ _numops_fromInt:
124188
124404
  // this make sure to set the Z flag correctly
124189
124405
  r += `
124190
124406
  .section code
124407
+ .object _pxt_helper_cmp_${op}
124191
124408
  _cmp_${op}:
124192
124409
  lsls r2, r0, #31
124193
124410
  beq .boxed
@@ -128773,7 +128990,8 @@ var ts;
128773
128990
  lbl = "_ldlit_" + ++seq;
128774
128991
  values[v] = lbl;
128775
128992
  }
128776
- line.update(`ldr ${reg}, ${lbl}`);
128993
+ line.ldlitLabel = line.words[3];
128994
+ line.update(`ldr ${reg}, ${lbl} ; ${line.ldlitLabel}`);
128777
128995
  }
128778
128996
  if (line === nextGoodSpot) {
128779
128997
  nextGoodSpot = null;
@@ -128781,6 +128999,7 @@ var ts;
128781
128999
  let jmplbl = "_jmpwords_" + ++seq;
128782
129000
  if (needsJumpOver)
128783
129001
  txtLines.push("bb " + jmplbl);
129002
+ txtLines.push(`.object PUSH`);
128784
129003
  txtLines.push(".balign 4");
128785
129004
  for (let v of Object.keys(values)) {
128786
129005
  let lbl = values[v];
@@ -128788,6 +129007,7 @@ var ts;
128788
129007
  }
128789
129008
  if (needsJumpOver)
128790
129009
  txtLines.push(jmplbl + ":");
129010
+ txtLines.push(`.object POP`);
128791
129011
  for (let t of txtLines) {
128792
129012
  f.buildLine(t, outlines);
128793
129013
  let ll = outlines[outlines.length - 1];
@@ -130082,7 +130302,7 @@ var ts;
130082
130302
  function inspect(n) {
130083
130303
  console.log(stringKind(n));
130084
130304
  }
130085
- // next free error 9283
130305
+ // next free error 9284
130086
130306
  function userError(code, msg, secondary = false) {
130087
130307
  let e = new Error(msg);
130088
130308
  e.ksEmitterUserError = true;
@@ -136252,7 +136472,8 @@ var ts;
136252
136472
  asmLabels[lbl] = true;
136253
136473
  return "";
136254
136474
  });
136255
- let code = ".section code\n" +
136475
+ let code = ".object inlineasm\n" +
136476
+ ".section code\n" +
136256
136477
  "@stackmark func\n" +
136257
136478
  "@scope user" + asmIdx++ + "\n" +
136258
136479
  src + "\n" +
@@ -136785,6 +137006,7 @@ var ts;
136785
137006
  for (let data of Object.keys(bin.doubles)) {
136786
137007
  let lbl = bin.doubles[data];
136787
137008
  bin.otherLiterals.push(`
137009
+ .object ${lbl}
136788
137010
  .balign 4
136789
137011
  ${lbl}: ${snippets.obj_header("pxt::number_vt")}
136790
137012
  .hex ${data}
@@ -136877,6 +137099,7 @@ ${lbl}: ${snippets.obj_header("pxt::number_vt")}
136877
137099
  // ifaceInfo.mult = 0
136878
137100
  let ptrSz = pxtc.target.shortPointers ? ".short" : ".word";
136879
137101
  let s = `
137102
+ .object ${info.id}_VT
136880
137103
  .balign 4
136881
137104
  ${info.id}_VT:
136882
137105
  .short ${info.allfields.length * 4 + 4} ; size in bytes
@@ -136974,14 +137197,18 @@ ${hexfile.hexPrelude()}
136974
137197
  asmsource += hexfile.asmTotalSource; // user-supplied asm
136975
137198
  asmsource += "_code_end:\n\n";
136976
137199
  pxtc.U.iterMap(bin.codeHelpers, (code, lbl) => {
136977
- asmsource += ` .section code\n${lbl}:\n${code}\n`;
137200
+ asmsource +=
137201
+ ` .section code\n` +
137202
+ ` .object _code_helper_${lbl}\n` +
137203
+ `${lbl}:\n` +
137204
+ `${code}\n`;
136978
137205
  });
136979
137206
  asmsource += snippets.arithmetic();
136980
137207
  asmsource += "_helpers_end:\n\n";
136981
137208
  bin.usedClassInfos.forEach(info => {
136982
137209
  asmsource += vtableToAsm(info, opts, bin);
136983
137210
  });
136984
- asmsource += `\n.balign 4\n_pxt_iface_member_names:\n`;
137211
+ asmsource += `\n.balign 4\n.object _pxt_iface_member_names\n_pxt_iface_member_names:\n`;
136985
137212
  asmsource += ` .word ${bin.ifaceMembers.length}\n`;
136986
137213
  let idx = 0;
136987
137214
  for (let d of bin.ifaceMembers) {
@@ -136990,7 +137217,7 @@ ${hexfile.hexPrelude()}
136990
137217
  }
136991
137218
  asmsource += ` .word 0\n`;
136992
137219
  asmsource += "_vtables_end:\n\n";
136993
- asmsource += `\n.balign 4\n_pxt_config_data:\n`;
137220
+ asmsource += `\n.balign 4\n.object _pxt_config_data\n_pxt_config_data:\n`;
136994
137221
  const cfg = bin.res.configData || [];
136995
137222
  // asmsource += ` .word ${cfg.length}, 0 ; num. entries`
136996
137223
  for (let d of cfg) {
@@ -136999,7 +137226,7 @@ ${hexfile.hexPrelude()}
136999
137226
  asmsource += ` .word 0\n\n`;
137000
137227
  emitStrings(snippets, bin);
137001
137228
  asmsource += bin.otherLiterals.join("");
137002
- asmsource += `\n.balign 4\n.section code\n_pxt_perf_counters:\n`;
137229
+ asmsource += `\n.balign 4\n.section code\n.object _perf_counters\n_pxt_perf_counters:\n`;
137003
137230
  asmsource += ` .word ${perfCounters.length}\n`;
137004
137231
  let strs = "";
137005
137232
  for (let i = 0; i < perfCounters.length; ++i) {
@@ -137032,6 +137259,8 @@ ${hexfile.hexPrelude()}
137032
137259
  b.ei.testAssembler(); // just in case
137033
137260
  if (target.switches.noPeepHole)
137034
137261
  b.disablePeepHole = true;
137262
+ if (target.switches.size)
137263
+ b.codeSizeStats = true;
137035
137264
  b.lookupExternalLabel = hexfile.lookupFunctionAddr;
137036
137265
  b.normalizeExternalLabel = s => {
137037
137266
  let inf = hexfile.lookupFunc(s);
@@ -137092,6 +137321,7 @@ ${hexfile.hexPrelude()}
137092
137321
  }
137093
137322
  return `
137094
137323
  .balign 16
137324
+ .object _stored_program
137095
137325
  _stored_program: .hex ${res}
137096
137326
  `;
137097
137327
  }
@@ -139639,7 +139869,7 @@ var ts;
139639
139869
  }
139640
139870
  const type = checker === null || checker === void 0 ? void 0 : checker.getTypeAtLocation(param);
139641
139871
  const typeSymbol = service.getPxtSymbolFromTsSymbol(type === null || type === void 0 ? void 0 : type.symbol, apis, checker);
139642
- if ((typeSymbol === null || typeSymbol === void 0 ? void 0 : typeSymbol.attributes.fixedInstances) && python) {
139872
+ if (((typeSymbol === null || typeSymbol === void 0 ? void 0 : typeSymbol.attributes.fixedInstances) || (typeSymbol === null || typeSymbol === void 0 ? void 0 : typeSymbol.attributes.emitAsConstant)) && python) {
139643
139873
  return pxt.Util.snakify(paramDefl);
139644
139874
  }
139645
139875
  if (python) {
@@ -153272,7 +153502,7 @@ var pxsim;
153272
153502
  }
153273
153503
  }
153274
153504
  createFrame(url) {
153275
- var _a;
153505
+ var _a, _b;
153276
153506
  const wrapper = document.createElement("div");
153277
153507
  wrapper.className = `simframe ui embed`;
153278
153508
  const frame = document.createElement('iframe');
@@ -153283,7 +153513,7 @@ var pxsim;
153283
153513
  frame.setAttribute('sandbox', 'allow-same-origin allow-scripts');
153284
153514
  frame.className = 'no-select';
153285
153515
  let furl = url || this.getSimUrl().toString();
153286
- if (this._runOptions.hideSimButtons) {
153516
+ if ((_a = this._runOptions) === null || _a === void 0 ? void 0 : _a.hideSimButtons) {
153287
153517
  const urlObject = new URL(furl);
153288
153518
  urlObject.searchParams.append("hideSimButtons", "1");
153289
153519
  furl = urlObject.toString();
@@ -153293,7 +153523,7 @@ var pxsim;
153293
153523
  frame.frameBorder = "0";
153294
153524
  frame.dataset['runid'] = this.runId;
153295
153525
  frame.dataset['origin'] = new URL(furl).origin || "*";
153296
- if ((_a = this._runOptions) === null || _a === void 0 ? void 0 : _a.autofocus)
153526
+ if ((_b = this._runOptions) === null || _b === void 0 ? void 0 : _b.autofocus)
153297
153527
  frame.setAttribute("autofocus", "true");
153298
153528
  wrapper.appendChild(frame);
153299
153529
  const i = document.createElement("i");
@@ -154227,92 +154457,10 @@ var pxsim;
154227
154457
  .then(() => {
154228
154458
  if (prevStop != instrStopId)
154229
154459
  return Promise.resolve();
154230
- return playInstructionsAsync(b);
154460
+ return playInstructionsAsync(b.data);
154231
154461
  });
154232
154462
  }
154233
154463
  AudioContextManager.queuePlayInstructions = queuePlayInstructions;
154234
- function playInstructionsAsync(b) {
154235
- const prevStop = instrStopId;
154236
- let ctx = context();
154237
- let idx = 0;
154238
- let ch = new Channel();
154239
- let currWave = -1;
154240
- let currFreq = -1;
154241
- let timeOff = 0;
154242
- if (channels.length > 5)
154243
- channels[0].remove();
154244
- channels.push(ch);
154245
- /** Square waves are perceved as much louder than other sounds, so scale it down a bit to make it less jarring **/
154246
- const scaleVol = (n, isSqWave) => (n / 1024) / 4 * (isSqWave ? .5 : 1);
154247
- const finish = () => {
154248
- ch.disconnectNodes();
154249
- timeOff = 0;
154250
- currWave = -1;
154251
- currFreq = -1;
154252
- };
154253
- const loopAsync = () => {
154254
- if (idx >= b.data.length || !b.data[idx])
154255
- return pxsim.U.delay(timeOff).then(finish);
154256
- const soundWaveIdx = b.data[idx];
154257
- const freq = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 2);
154258
- const duration = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 4);
154259
- const startVol = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 6);
154260
- const endVol = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 8);
154261
- const endFreq = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 10);
154262
- const isSquareWave = 11 <= soundWaveIdx && soundWaveIdx <= 15;
154263
- const isFilteredNoise = soundWaveIdx == 4 || (16 <= soundWaveIdx && soundWaveIdx <= 18);
154264
- const scaledStart = scaleVol(startVol, isSquareWave);
154265
- const scaledEnd = scaleVol(endVol, isSquareWave);
154266
- if (!ctx || prevStop != instrStopId)
154267
- return pxsim.U.delay(duration);
154268
- if (currWave != soundWaveIdx || currFreq != freq || freq != endFreq) {
154269
- if (ch.generator) {
154270
- return pxsim.U.delay(timeOff)
154271
- .then(() => {
154272
- finish();
154273
- return loopAsync();
154274
- });
154275
- }
154276
- ch.generator = getGenerator(soundWaveIdx, freq);
154277
- if (!ch.generator)
154278
- return pxsim.U.delay(duration);
154279
- currWave = soundWaveIdx;
154280
- currFreq = freq;
154281
- ch.gain = ctx.createGain();
154282
- ch.gain.gain.value = 0;
154283
- ch.gain.gain.setTargetAtTime(scaledStart, _context.currentTime, 0.015);
154284
- if (endFreq != freq) {
154285
- if (ch.generator.frequency != undefined) {
154286
- // If generator is an OscillatorNode
154287
- const param = ch.generator.frequency;
154288
- param.linearRampToValueAtTime(endFreq, ctx.currentTime + ((timeOff + duration) / 1000));
154289
- }
154290
- else if (ch.generator.playbackRate != undefined) {
154291
- // If generator is an AudioBufferSourceNode
154292
- const param = ch.generator.playbackRate;
154293
- const bufferSamplesPerWave = isFilteredNoise ? 4 : 1024;
154294
- param.linearRampToValueAtTime(endFreq / (context().sampleRate / bufferSamplesPerWave), ctx.currentTime + ((timeOff + duration) / 1000));
154295
- }
154296
- }
154297
- ch.generator.connect(ch.gain);
154298
- ch.gain.connect(destination);
154299
- ch.generator.start();
154300
- }
154301
- idx += 12;
154302
- ch.gain.gain.setValueAtTime(scaledStart, ctx.currentTime + (timeOff / 1000));
154303
- timeOff += duration;
154304
- // To prevent clipping, we ramp to this value slightly earlier than intended. This is so that we
154305
- // can go for a smooth ramp to 0 in ch.mute() without this operation interrupting it. If we had
154306
- // more accurate timing this would not be necessary, but we'd probably have to do something like
154307
- // running a metronome in a webworker to get the level of precision we need
154308
- const endTime = scaledEnd !== 0 && duration > 50 ? ((timeOff - 50) / 1000) : ((timeOff - 10) / 1000);
154309
- ch.gain.gain.linearRampToValueAtTime(scaledEnd, ctx.currentTime + endTime);
154310
- return loopAsync();
154311
- };
154312
- return loopAsync()
154313
- .then(() => ch.remove());
154314
- }
154315
- AudioContextManager.playInstructionsAsync = playInstructionsAsync;
154316
154464
  function tone(frequency, gain) {
154317
154465
  if (frequency < 0)
154318
154466
  return;
@@ -154451,6 +154599,126 @@ var pxsim;
154451
154599
  function frequencyFromMidiNoteNumber(note) {
154452
154600
  return 440 * Math.pow(2, (note - 69) / 12);
154453
154601
  }
154602
+ function playInstructionsAsync(instructions, isCancelled, onPull) {
154603
+ return new Promise(async (resolve) => {
154604
+ let resolved = false;
154605
+ let ctx = context();
154606
+ let channel = new Channel();
154607
+ if (channels.length > 5)
154608
+ channels[0].remove();
154609
+ channels.push(channel);
154610
+ channel.gain = ctx.createGain();
154611
+ channel.gain.gain.value = 1;
154612
+ channel.gain.connect(destination);
154613
+ const oscillators = {};
154614
+ const gains = {};
154615
+ let startTime = ctx.currentTime;
154616
+ let currentTime = startTime;
154617
+ let currentWave = 0;
154618
+ let totalDuration = 0;
154619
+ /** Square waves are perceved as much louder than other sounds, so scale it down a bit to make it less jarring **/
154620
+ const scaleVol = (n, isSqWave) => (n / 1024) / 4 * (isSqWave ? .5 : 1);
154621
+ const disconnectNodes = () => {
154622
+ if (resolved)
154623
+ return;
154624
+ resolved = true;
154625
+ channel.disconnectNodes();
154626
+ for (const wave of Object.keys(oscillators)) {
154627
+ oscillators[wave].stop();
154628
+ oscillators[wave].disconnect();
154629
+ gains[wave].disconnect();
154630
+ }
154631
+ resolve();
154632
+ };
154633
+ for (let i = 0; i < instructions.length; i += 12) {
154634
+ const wave = instructions[i];
154635
+ const startFrequency = readUint16(instructions, i + 2);
154636
+ const duration = readUint16(instructions, i + 4) / 1000;
154637
+ const startVolume = readUint16(instructions, i + 6);
154638
+ const endVolume = readUint16(instructions, i + 8);
154639
+ const endFrequency = readUint16(instructions, i + 10);
154640
+ totalDuration += duration;
154641
+ const isSquareWave = 11 <= wave && wave <= 15;
154642
+ if (!oscillators[wave]) {
154643
+ oscillators[wave] = getGenerator(wave, startFrequency);
154644
+ gains[wave] = ctx.createGain();
154645
+ gains[wave].gain.value = 0;
154646
+ gains[wave].connect(channel.gain);
154647
+ oscillators[wave].connect(gains[wave]);
154648
+ oscillators[wave].start();
154649
+ }
154650
+ if (currentWave && wave !== currentWave) {
154651
+ gains[currentWave].gain.setTargetAtTime(0, currentTime, 0.015);
154652
+ }
154653
+ const osc = oscillators[wave];
154654
+ const gain = gains[wave];
154655
+ if (osc instanceof OscillatorNode) {
154656
+ osc.frequency.setValueAtTime(startFrequency, currentTime);
154657
+ osc.frequency.linearRampToValueAtTime(endFrequency, currentTime + duration);
154658
+ }
154659
+ else {
154660
+ const isFilteredNoise = wave == 4 || (16 <= wave && wave <= 18);
154661
+ if (isFilteredNoise)
154662
+ osc.playbackRate.linearRampToValueAtTime(endFrequency / (ctx.sampleRate / 4), currentTime + duration);
154663
+ else if (wave != 5)
154664
+ osc.playbackRate.linearRampToValueAtTime(endFrequency / (ctx.sampleRate / 1024), currentTime + duration);
154665
+ }
154666
+ gain.gain.setValueAtTime(scaleVol(startVolume, isSquareWave), currentTime);
154667
+ gain.gain.linearRampToValueAtTime(scaleVol(endVolume, isSquareWave), currentTime + duration);
154668
+ currentWave = wave;
154669
+ currentTime += duration;
154670
+ }
154671
+ channel.gain.gain.setTargetAtTime(0, currentTime, 0.015);
154672
+ if (isCancelled || onPull) {
154673
+ const handleAnimationFrame = () => {
154674
+ const time = ctx.currentTime;
154675
+ if (time > startTime + totalDuration) {
154676
+ return;
154677
+ }
154678
+ if (isCancelled && isCancelled()) {
154679
+ disconnectNodes();
154680
+ return;
154681
+ }
154682
+ const { frequency, volume } = findFrequencyAndVolumeAtTime((time - startTime) * 1000, instructions);
154683
+ onPull(frequency, volume / 1024);
154684
+ requestAnimationFrame(handleAnimationFrame);
154685
+ };
154686
+ requestAnimationFrame(handleAnimationFrame);
154687
+ }
154688
+ await pxsim.U.delay(totalDuration * 1000);
154689
+ disconnectNodes();
154690
+ });
154691
+ }
154692
+ AudioContextManager.playInstructionsAsync = playInstructionsAsync;
154693
+ function readUint16(buf, offset) {
154694
+ const temp = new Uint8Array(2);
154695
+ temp[0] = buf[offset];
154696
+ temp[1] = buf[offset + 1];
154697
+ return new Uint16Array(temp.buffer)[0];
154698
+ }
154699
+ function findFrequencyAndVolumeAtTime(millis, instructions) {
154700
+ let currentTime = 0;
154701
+ for (let i = 0; i < instructions.length; i += 12) {
154702
+ const startFrequency = readUint16(instructions, i + 2);
154703
+ const duration = readUint16(instructions, i + 4);
154704
+ const startVolume = readUint16(instructions, i + 6);
154705
+ const endVolume = readUint16(instructions, i + 8);
154706
+ const endFrequency = readUint16(instructions, i + 10);
154707
+ if (currentTime + duration < millis) {
154708
+ currentTime += duration;
154709
+ continue;
154710
+ }
154711
+ const offset = (millis - currentTime) / duration;
154712
+ return {
154713
+ frequency: startFrequency + (endFrequency - startFrequency) * offset,
154714
+ volume: startVolume + (endVolume - startVolume) * offset,
154715
+ };
154716
+ }
154717
+ return {
154718
+ frequency: -1,
154719
+ volume: -1
154720
+ };
154721
+ }
154454
154722
  function sendMidiMessage(buf) {
154455
154723
  const data = buf.data;
154456
154724
  if (!data.length) // garbage.