pxt-core 7.3.3 → 7.3.7
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 +17 -0
- package/built/pxt.js +153 -17
- package/built/pxtcompiler.js +75 -7
- package/built/pxtlib.d.ts +4 -0
- package/built/pxtlib.js +61 -10
- package/built/target.js +1 -1
- package/built/web/main.js +1 -1
- package/built/web/pxtapp.js +1 -1
- package/built/web/pxtasseteditor.js +1 -1
- package/built/web/pxtcompiler.js +1 -1
- package/built/web/pxtembed.js +1 -1
- package/built/web/pxtlib.js +1 -1
- package/built/web/pxtworker.js +1 -1
- package/built/web/rtlsemantic.css +2 -2
- package/built/web/semantic.css +2 -2
- package/built/web/skillmap/css/main.90d453fd.chunk.css +1 -0
- package/built/web/skillmap/js/main.e8ffa077.chunk.js +1 -0
- package/common-docs/extensions/approval.md +1 -1
- package/docfiles/tracking.html +2 -2
- package/localtypings/pxtarget.d.ts +1 -0
- package/package.json +1 -1
- package/theme/common.less +26 -0
- package/theme/themes/pxt/modules/modal.overrides +2 -1
- package/webapp/public/skillmap.html +2 -2
- package/built/web/skillmap/css/main.0db0a463.chunk.css +0 -1
- package/built/web/skillmap/js/main.1bb404cf.chunk.js +0 -1
package/built/cli.js
CHANGED
|
@@ -403,6 +403,8 @@ function ciAsync() {
|
|
|
403
403
|
pxt.log(`pull request: ${pullRequest}`);
|
|
404
404
|
pxt.log(`upload api strings: ${uploadApiStrings}`);
|
|
405
405
|
pxt.log(`upload docs: ${uploadDocs}`);
|
|
406
|
+
lintJSONInDirectory(path.resolve("."));
|
|
407
|
+
lintJSONInDirectory(path.resolve("docs"));
|
|
406
408
|
function npmPublishAsync() {
|
|
407
409
|
if (!npmPublish)
|
|
408
410
|
return Promise.resolve();
|
|
@@ -459,6 +461,21 @@ function ciAsync() {
|
|
|
459
461
|
});
|
|
460
462
|
}
|
|
461
463
|
}
|
|
464
|
+
function lintJSONInDirectory(dir) {
|
|
465
|
+
for (const file of fs.readdirSync(dir)) {
|
|
466
|
+
const fullPath = path.join(dir, file);
|
|
467
|
+
if (file.endsWith(".json")) {
|
|
468
|
+
const contents = fs.readFileSync(fullPath, "utf8");
|
|
469
|
+
try {
|
|
470
|
+
JSON.parse(contents);
|
|
471
|
+
}
|
|
472
|
+
catch (e) {
|
|
473
|
+
console.log("Could not parse " + fullPath);
|
|
474
|
+
process.exit(1);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
462
479
|
function bumpPxtCoreDepAsync() {
|
|
463
480
|
let pkg = readJson("package.json");
|
|
464
481
|
if (pkg["name"] == "pxt-core")
|
package/built/pxt.js
CHANGED
|
@@ -97876,6 +97876,10 @@ var pxt;
|
|
|
97876
97876
|
let _client;
|
|
97877
97877
|
function client() { return _client; }
|
|
97878
97878
|
auth.client = client;
|
|
97879
|
+
const PREFERENCES_DEBOUNCE_MS = 5 * 1000;
|
|
97880
|
+
const PREFERENCES_DEBOUNCE_MAX_MS = 30 * 1000;
|
|
97881
|
+
let debouncePreferencesChangedTimeout = 0;
|
|
97882
|
+
let debouncePreferencesChangedStarted = 0;
|
|
97879
97883
|
class AuthClient {
|
|
97880
97884
|
constructor() {
|
|
97881
97885
|
this.initialUserPreferences_ = undefined;
|
|
@@ -98081,15 +98085,28 @@ var pxt;
|
|
|
98081
98085
|
if (!await this.loggedInAsync()) {
|
|
98082
98086
|
return;
|
|
98083
98087
|
}
|
|
98084
|
-
// If the user is logged in, save to cloud
|
|
98085
|
-
|
|
98086
|
-
|
|
98087
|
-
|
|
98088
|
-
|
|
98089
|
-
|
|
98088
|
+
// If the user is logged in, save to cloud, but debounce the api call as this can be called frequently from skillmaps
|
|
98089
|
+
clearTimeout(debouncePreferencesChangedTimeout);
|
|
98090
|
+
const savePrefs = async () => {
|
|
98091
|
+
debouncePreferencesChangedStarted = 0;
|
|
98092
|
+
const result = await this.apiAsync('/api/user/preferences', ops, 'PATCH');
|
|
98093
|
+
if (result.success) {
|
|
98094
|
+
pxt.debug("Updating local user preferences w/ cloud data after result of POST");
|
|
98095
|
+
// Set user profile from returned value so we stay in-sync
|
|
98096
|
+
this.setUserPreferencesAsync(result.resp);
|
|
98097
|
+
}
|
|
98098
|
+
else {
|
|
98099
|
+
pxt.reportError("identity", "update preferences failed", result);
|
|
98100
|
+
}
|
|
98101
|
+
};
|
|
98102
|
+
if (!debouncePreferencesChangedStarted) {
|
|
98103
|
+
debouncePreferencesChangedStarted = pxt.U.now();
|
|
98104
|
+
}
|
|
98105
|
+
if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
|
|
98106
|
+
await savePrefs();
|
|
98090
98107
|
}
|
|
98091
98108
|
else {
|
|
98092
|
-
|
|
98109
|
+
debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
|
|
98093
98110
|
}
|
|
98094
98111
|
}
|
|
98095
98112
|
/*protected*/ hasUserId() {
|
|
@@ -101052,6 +101069,8 @@ var pxt;
|
|
|
101052
101069
|
}
|
|
101053
101070
|
if (!comp.switches)
|
|
101054
101071
|
comp.switches = {};
|
|
101072
|
+
if (comp.nativeType == pxtc.NATIVE_TYPE_VM)
|
|
101073
|
+
comp.sourceMap = true;
|
|
101055
101074
|
pxt.U.jsonCopyFrom(comp.switches, savedSwitches);
|
|
101056
101075
|
// JS ref counting currently not supported
|
|
101057
101076
|
comp.jsRefCounting = false;
|
|
@@ -103399,6 +103418,7 @@ var pxt;
|
|
|
103399
103418
|
commands.electronDeployAsync = undefined; // A pointer to the Electron deploy function, so that targets can access it in their extension.ts
|
|
103400
103419
|
commands.webUsbPairDialogAsync = undefined;
|
|
103401
103420
|
commands.onTutorialCompleted = undefined;
|
|
103421
|
+
commands.workspaceLoadedAsync = undefined;
|
|
103402
103422
|
})(commands = pxt.commands || (pxt.commands = {}));
|
|
103403
103423
|
})(pxt || (pxt = {}));
|
|
103404
103424
|
/// <reference path="../localtypings/pxtarget.d.ts"/>
|
|
@@ -104645,7 +104665,7 @@ int main() {
|
|
|
104645
104665
|
.then(ret => new Promise((resolve, reject) => {
|
|
104646
104666
|
let retry = 0;
|
|
104647
104667
|
const delay = 8000; // ms
|
|
104648
|
-
const maxWait =
|
|
104668
|
+
const maxWait = 300000; // ms
|
|
104649
104669
|
const startTry = pxt.U.now();
|
|
104650
104670
|
const tryGet = () => {
|
|
104651
104671
|
retry++;
|
|
@@ -112845,6 +112865,7 @@ var ts;
|
|
|
112845
112865
|
pxtc.BINARY_ELF = "binary.elf";
|
|
112846
112866
|
pxtc.BINARY_PXT64 = "binary.pxt64";
|
|
112847
112867
|
pxtc.BINARY_ESP = "binary.bin";
|
|
112868
|
+
pxtc.BINARY_SRCMAP = "binary.srcmap";
|
|
112848
112869
|
pxtc.NATIVE_TYPE_THUMB = "thumb";
|
|
112849
112870
|
pxtc.NATIVE_TYPE_VM = "vm";
|
|
112850
112871
|
function BuildSourceMapHelpers(sourceMap, tsFile, pyFile) {
|
|
@@ -118709,7 +118730,6 @@ var pxt;
|
|
|
118709
118730
|
youtube.watchUrl = watchUrl;
|
|
118710
118731
|
})(youtube = pxt.youtube || (pxt.youtube = {}));
|
|
118711
118732
|
})(pxt || (pxt = {}));
|
|
118712
|
-
/* eslint-disable no-cond-assign */
|
|
118713
118733
|
// TODO: add a macro facility to make 8-bit assembly easier?
|
|
118714
118734
|
var ts;
|
|
118715
118735
|
(function (ts) {
|
|
@@ -118967,7 +118987,7 @@ var ts;
|
|
|
118967
118987
|
// recursive-descent parsing of multiplication
|
|
118968
118988
|
if (s.indexOf("*") >= 0) {
|
|
118969
118989
|
let m = null;
|
|
118970
|
-
while (m = /^([^\*]*)\*(.*)$/.exec(s)) {
|
|
118990
|
+
while (null != (m = /^([^\*]*)\*(.*)$/.exec(s))) {
|
|
118971
118991
|
let tmp = this.parseOneInt(m[1]);
|
|
118972
118992
|
if (tmp == null)
|
|
118973
118993
|
return null;
|
|
@@ -119582,6 +119602,37 @@ var ts;
|
|
|
119582
119602
|
}
|
|
119583
119603
|
});
|
|
119584
119604
|
}
|
|
119605
|
+
getSourceMap() {
|
|
119606
|
+
const sourceMap = {};
|
|
119607
|
+
let locFile = "";
|
|
119608
|
+
let locLn = 0;
|
|
119609
|
+
let locPos = 0;
|
|
119610
|
+
let locEnd = 0;
|
|
119611
|
+
this.lines.forEach((ln, i) => {
|
|
119612
|
+
const m = /^; ([\w\/\.-]+)\(([\d]+),\d+\):/.exec(ln.text);
|
|
119613
|
+
if (m) {
|
|
119614
|
+
flush();
|
|
119615
|
+
locFile = m[1];
|
|
119616
|
+
locLn = parseInt(m[2]);
|
|
119617
|
+
}
|
|
119618
|
+
if (ln.type == "instruction") {
|
|
119619
|
+
if (!locPos)
|
|
119620
|
+
locPos = ln.location;
|
|
119621
|
+
locEnd = ln.location;
|
|
119622
|
+
}
|
|
119623
|
+
});
|
|
119624
|
+
flush();
|
|
119625
|
+
function flush() {
|
|
119626
|
+
if (locFile && locPos) {
|
|
119627
|
+
if (!sourceMap[locFile])
|
|
119628
|
+
sourceMap[locFile] = [];
|
|
119629
|
+
sourceMap[locFile].push(locLn, locPos, locEnd - locPos);
|
|
119630
|
+
}
|
|
119631
|
+
locPos = 0;
|
|
119632
|
+
locEnd = 0;
|
|
119633
|
+
}
|
|
119634
|
+
return sourceMap;
|
|
119635
|
+
}
|
|
119585
119636
|
getSource(clean, numStmts = 1, flashSize = 0) {
|
|
119586
119637
|
let lenPrev = 0;
|
|
119587
119638
|
let size = (lbl) => {
|
|
@@ -124092,6 +124143,53 @@ ${info.id}_IfaceVT:
|
|
|
124092
124143
|
else
|
|
124093
124144
|
return `0xffffffff, 0xffffffff ; -> ${vt}`;
|
|
124094
124145
|
}
|
|
124146
|
+
function encodeSourceMap(srcmap) {
|
|
124147
|
+
// magic: 0x4d435253 0x2d4e1588 0x719986aa ('SRCM' ... )
|
|
124148
|
+
const res = [0x53, 0x52, 0x43, 0x4d, 0x88, 0x15, 0x4e, 0x2d, 0xaa, 0x86, 0x99, 0x71, 0x00, 0x00, 0x00, 0x00];
|
|
124149
|
+
for (const fn of Object.keys(srcmap)) {
|
|
124150
|
+
for (const c of pxtc.U.stringToUint8Array(fn))
|
|
124151
|
+
res.push(c);
|
|
124152
|
+
res.push(0);
|
|
124153
|
+
const arr = srcmap[fn];
|
|
124154
|
+
let prevLn = 0;
|
|
124155
|
+
let prevOff = 0;
|
|
124156
|
+
for (let i = 0; i < arr.length; i += 3) {
|
|
124157
|
+
encodeNumber(arr[i] - prevLn);
|
|
124158
|
+
encodeNumber((arr[i + 1] - prevOff) >> 1);
|
|
124159
|
+
encodeNumber(arr[i + 2] >> 1);
|
|
124160
|
+
prevLn = arr[i];
|
|
124161
|
+
prevOff = arr[i + 1];
|
|
124162
|
+
}
|
|
124163
|
+
res.push(0xff); // end-marker
|
|
124164
|
+
}
|
|
124165
|
+
res.push(0);
|
|
124166
|
+
if (res.length & 1)
|
|
124167
|
+
res.push(0);
|
|
124168
|
+
const res2 = [];
|
|
124169
|
+
for (let i = 0; i < res.length; i += 2)
|
|
124170
|
+
res2.push(res[i] | (res[i + 1] << 8));
|
|
124171
|
+
return res2;
|
|
124172
|
+
function encodeNumber(k) {
|
|
124173
|
+
if (0 <= k && k < 0xf0)
|
|
124174
|
+
res.push(k);
|
|
124175
|
+
else {
|
|
124176
|
+
let mark = 0xf0;
|
|
124177
|
+
if (k < 0) {
|
|
124178
|
+
k = -k;
|
|
124179
|
+
mark |= 0x08;
|
|
124180
|
+
}
|
|
124181
|
+
const idx = res.length;
|
|
124182
|
+
res.push(null); // placeholder
|
|
124183
|
+
let len = 0;
|
|
124184
|
+
while (k != 0) {
|
|
124185
|
+
res.push(k & 0xff);
|
|
124186
|
+
k >>>= 8;
|
|
124187
|
+
len++;
|
|
124188
|
+
}
|
|
124189
|
+
res[idx] = mark | len;
|
|
124190
|
+
}
|
|
124191
|
+
}
|
|
124192
|
+
}
|
|
124095
124193
|
/* eslint-disable no-trailing-spaces */
|
|
124096
124194
|
function vmEmit(bin, opts) {
|
|
124097
124195
|
let vmsource = `; VM start
|
|
@@ -124129,7 +124227,7 @@ _start_${name}:
|
|
|
124129
124227
|
vmsource += `\n.balign 8\n_end_${name}:\n`;
|
|
124130
124228
|
address++;
|
|
124131
124229
|
}
|
|
124132
|
-
const now = new Date();
|
|
124230
|
+
const now = new Date(0); // new Date()
|
|
124133
124231
|
let encodedName = pxtc.U.toUTF8(opts.name, true);
|
|
124134
124232
|
if (encodedName.length > 100)
|
|
124135
124233
|
encodedName = encodedName.slice(0, 100);
|
|
@@ -124215,8 +124313,25 @@ _start_${name}:
|
|
|
124215
124313
|
vmsource += "\n; The end.\n";
|
|
124216
124314
|
bin.writeFile(pxtc.BINARY_ASM, vmsource);
|
|
124217
124315
|
let res = pxtc.assemble(opts.target, bin, vmsource);
|
|
124316
|
+
const srcmap = res.thumbFile.getSourceMap();
|
|
124317
|
+
const encodedSrcMap = encodeSourceMap(srcmap);
|
|
124218
124318
|
if (res.src)
|
|
124219
|
-
bin.writeFile(pxtc.BINARY_ASM, res.src);
|
|
124319
|
+
bin.writeFile(pxtc.BINARY_ASM, `; srcmap size: ${encodedSrcMap.length << 1} bytes\n` + res.src);
|
|
124320
|
+
{
|
|
124321
|
+
let binstring = "";
|
|
124322
|
+
for (let v of res.buf)
|
|
124323
|
+
binstring += String.fromCharCode(v & 0xff, v >> 8);
|
|
124324
|
+
const hash = pxtc.U.sha256(binstring);
|
|
124325
|
+
for (let i = 0; i < 4; ++i) {
|
|
124326
|
+
res.buf[16 + i] = parseInt(hash.slice(i * 4, i * 4 + 4), 16);
|
|
124327
|
+
}
|
|
124328
|
+
srcmap["__meta"] = {
|
|
124329
|
+
name: opts.name,
|
|
124330
|
+
programHash: res.buf[16] | (res.buf[16 + 1] << 16),
|
|
124331
|
+
// TODO would be nice to include version number of editor...
|
|
124332
|
+
};
|
|
124333
|
+
}
|
|
124334
|
+
bin.writeFile(pxtc.BINARY_SRCMAP, JSON.stringify(srcmap));
|
|
124220
124335
|
if (pxt.options.debug) {
|
|
124221
124336
|
let pc = res.thumbFile.peepCounts;
|
|
124222
124337
|
let keys = Object.keys(pc);
|
|
@@ -124227,12 +124342,16 @@ _start_${name}:
|
|
|
124227
124342
|
}
|
|
124228
124343
|
if (res.buf) {
|
|
124229
124344
|
let binstring = "";
|
|
124230
|
-
|
|
124345
|
+
const buf = res.buf;
|
|
124346
|
+
while (buf.length & 0xf)
|
|
124347
|
+
buf.push(0);
|
|
124348
|
+
pxtc.U.pushRange(buf, encodedSrcMap);
|
|
124349
|
+
for (let v of buf)
|
|
124231
124350
|
binstring += String.fromCharCode(v & 0xff, v >> 8);
|
|
124232
124351
|
binstring = ts.pxtc.encodeBase64(binstring);
|
|
124233
124352
|
if (embedVTs()) {
|
|
124234
124353
|
bin.writeFile(pxtc.BINARY_PXT64, binstring);
|
|
124235
|
-
const patched = pxtc.hexfile.patchHex(bin,
|
|
124354
|
+
const patched = pxtc.hexfile.patchHex(bin, buf, false, !!pxtc.target.useUF2)[0];
|
|
124236
124355
|
bin.writeFile(pxt.outputName(pxtc.target), ts.pxtc.encodeBase64(patched));
|
|
124237
124356
|
}
|
|
124238
124357
|
else {
|
|
@@ -124263,7 +124382,7 @@ _start_${name}:
|
|
|
124263
124382
|
emitAll();
|
|
124264
124383
|
return resText;
|
|
124265
124384
|
function emitAll() {
|
|
124266
|
-
writeRaw(`;\n;
|
|
124385
|
+
writeRaw(`;\n; ${proc.getFullName()}\n;`);
|
|
124267
124386
|
write(".section code");
|
|
124268
124387
|
if (bin.procs[0] == proc) {
|
|
124269
124388
|
writeRaw(`; main`);
|
|
@@ -129005,7 +129124,7 @@ var ts;
|
|
|
129005
129124
|
let name = pxtc.getDeclName(this.action);
|
|
129006
129125
|
if (this.action) {
|
|
129007
129126
|
let info = ts.pxtc.nodeLocationInfo(this.action);
|
|
129008
|
-
name
|
|
129127
|
+
name = info.fileName.replace("pxt_modules/", "") + "(" + (info.line + 1) + "," + (info.column + 1) + "): " + name;
|
|
129009
129128
|
}
|
|
129010
129129
|
return name;
|
|
129011
129130
|
}
|
|
@@ -132948,7 +133067,7 @@ ${lbl}: .short 0xffff
|
|
|
132948
133067
|
}
|
|
132949
133068
|
function emitBrk(node) {
|
|
132950
133069
|
bin.numStmts++;
|
|
132951
|
-
const needsComment = pxtc.assembler.debug || pxtc.target.switches.size;
|
|
133070
|
+
const needsComment = pxtc.assembler.debug || pxtc.target.switches.size || pxtc.target.sourceMap;
|
|
132952
133071
|
let needsBreak = !!opts.breakpoints;
|
|
132953
133072
|
if (!needsComment && !needsBreak)
|
|
132954
133073
|
return;
|
|
@@ -156153,6 +156272,8 @@ function ciAsync() {
|
|
|
156153
156272
|
pxt.log(`pull request: ${pullRequest}`);
|
|
156154
156273
|
pxt.log(`upload api strings: ${uploadApiStrings}`);
|
|
156155
156274
|
pxt.log(`upload docs: ${uploadDocs}`);
|
|
156275
|
+
lintJSONInDirectory(path.resolve("."));
|
|
156276
|
+
lintJSONInDirectory(path.resolve("docs"));
|
|
156156
156277
|
function npmPublishAsync() {
|
|
156157
156278
|
if (!npmPublish)
|
|
156158
156279
|
return Promise.resolve();
|
|
@@ -156209,6 +156330,21 @@ function ciAsync() {
|
|
|
156209
156330
|
});
|
|
156210
156331
|
}
|
|
156211
156332
|
}
|
|
156333
|
+
function lintJSONInDirectory(dir) {
|
|
156334
|
+
for (const file of fs.readdirSync(dir)) {
|
|
156335
|
+
const fullPath = path.join(dir, file);
|
|
156336
|
+
if (file.endsWith(".json")) {
|
|
156337
|
+
const contents = fs.readFileSync(fullPath, "utf8");
|
|
156338
|
+
try {
|
|
156339
|
+
JSON.parse(contents);
|
|
156340
|
+
}
|
|
156341
|
+
catch (e) {
|
|
156342
|
+
console.log("Could not parse " + fullPath);
|
|
156343
|
+
process.exit(1);
|
|
156344
|
+
}
|
|
156345
|
+
}
|
|
156346
|
+
}
|
|
156347
|
+
}
|
|
156212
156348
|
function bumpPxtCoreDepAsync() {
|
|
156213
156349
|
let pkg = readJson("package.json");
|
|
156214
156350
|
if (pkg["name"] == "pxt-core")
|
package/built/pxtcompiler.js
CHANGED
|
@@ -3350,6 +3350,53 @@ ${info.id}_IfaceVT:
|
|
|
3350
3350
|
else
|
|
3351
3351
|
return `0xffffffff, 0xffffffff ; -> ${vt}`;
|
|
3352
3352
|
}
|
|
3353
|
+
function encodeSourceMap(srcmap) {
|
|
3354
|
+
// magic: 0x4d435253 0x2d4e1588 0x719986aa ('SRCM' ... )
|
|
3355
|
+
const res = [0x53, 0x52, 0x43, 0x4d, 0x88, 0x15, 0x4e, 0x2d, 0xaa, 0x86, 0x99, 0x71, 0x00, 0x00, 0x00, 0x00];
|
|
3356
|
+
for (const fn of Object.keys(srcmap)) {
|
|
3357
|
+
for (const c of pxtc.U.stringToUint8Array(fn))
|
|
3358
|
+
res.push(c);
|
|
3359
|
+
res.push(0);
|
|
3360
|
+
const arr = srcmap[fn];
|
|
3361
|
+
let prevLn = 0;
|
|
3362
|
+
let prevOff = 0;
|
|
3363
|
+
for (let i = 0; i < arr.length; i += 3) {
|
|
3364
|
+
encodeNumber(arr[i] - prevLn);
|
|
3365
|
+
encodeNumber((arr[i + 1] - prevOff) >> 1);
|
|
3366
|
+
encodeNumber(arr[i + 2] >> 1);
|
|
3367
|
+
prevLn = arr[i];
|
|
3368
|
+
prevOff = arr[i + 1];
|
|
3369
|
+
}
|
|
3370
|
+
res.push(0xff); // end-marker
|
|
3371
|
+
}
|
|
3372
|
+
res.push(0);
|
|
3373
|
+
if (res.length & 1)
|
|
3374
|
+
res.push(0);
|
|
3375
|
+
const res2 = [];
|
|
3376
|
+
for (let i = 0; i < res.length; i += 2)
|
|
3377
|
+
res2.push(res[i] | (res[i + 1] << 8));
|
|
3378
|
+
return res2;
|
|
3379
|
+
function encodeNumber(k) {
|
|
3380
|
+
if (0 <= k && k < 0xf0)
|
|
3381
|
+
res.push(k);
|
|
3382
|
+
else {
|
|
3383
|
+
let mark = 0xf0;
|
|
3384
|
+
if (k < 0) {
|
|
3385
|
+
k = -k;
|
|
3386
|
+
mark |= 0x08;
|
|
3387
|
+
}
|
|
3388
|
+
const idx = res.length;
|
|
3389
|
+
res.push(null); // placeholder
|
|
3390
|
+
let len = 0;
|
|
3391
|
+
while (k != 0) {
|
|
3392
|
+
res.push(k & 0xff);
|
|
3393
|
+
k >>>= 8;
|
|
3394
|
+
len++;
|
|
3395
|
+
}
|
|
3396
|
+
res[idx] = mark | len;
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3353
3400
|
/* eslint-disable no-trailing-spaces */
|
|
3354
3401
|
function vmEmit(bin, opts) {
|
|
3355
3402
|
let vmsource = `; VM start
|
|
@@ -3387,7 +3434,7 @@ _start_${name}:
|
|
|
3387
3434
|
vmsource += `\n.balign 8\n_end_${name}:\n`;
|
|
3388
3435
|
address++;
|
|
3389
3436
|
}
|
|
3390
|
-
const now = new Date();
|
|
3437
|
+
const now = new Date(0); // new Date()
|
|
3391
3438
|
let encodedName = pxtc.U.toUTF8(opts.name, true);
|
|
3392
3439
|
if (encodedName.length > 100)
|
|
3393
3440
|
encodedName = encodedName.slice(0, 100);
|
|
@@ -3473,8 +3520,25 @@ _start_${name}:
|
|
|
3473
3520
|
vmsource += "\n; The end.\n";
|
|
3474
3521
|
bin.writeFile(pxtc.BINARY_ASM, vmsource);
|
|
3475
3522
|
let res = pxtc.assemble(opts.target, bin, vmsource);
|
|
3523
|
+
const srcmap = res.thumbFile.getSourceMap();
|
|
3524
|
+
const encodedSrcMap = encodeSourceMap(srcmap);
|
|
3476
3525
|
if (res.src)
|
|
3477
|
-
bin.writeFile(pxtc.BINARY_ASM, res.src);
|
|
3526
|
+
bin.writeFile(pxtc.BINARY_ASM, `; srcmap size: ${encodedSrcMap.length << 1} bytes\n` + res.src);
|
|
3527
|
+
{
|
|
3528
|
+
let binstring = "";
|
|
3529
|
+
for (let v of res.buf)
|
|
3530
|
+
binstring += String.fromCharCode(v & 0xff, v >> 8);
|
|
3531
|
+
const hash = pxtc.U.sha256(binstring);
|
|
3532
|
+
for (let i = 0; i < 4; ++i) {
|
|
3533
|
+
res.buf[16 + i] = parseInt(hash.slice(i * 4, i * 4 + 4), 16);
|
|
3534
|
+
}
|
|
3535
|
+
srcmap["__meta"] = {
|
|
3536
|
+
name: opts.name,
|
|
3537
|
+
programHash: res.buf[16] | (res.buf[16 + 1] << 16),
|
|
3538
|
+
// TODO would be nice to include version number of editor...
|
|
3539
|
+
};
|
|
3540
|
+
}
|
|
3541
|
+
bin.writeFile(pxtc.BINARY_SRCMAP, JSON.stringify(srcmap));
|
|
3478
3542
|
if (pxt.options.debug) {
|
|
3479
3543
|
let pc = res.thumbFile.peepCounts;
|
|
3480
3544
|
let keys = Object.keys(pc);
|
|
@@ -3485,12 +3549,16 @@ _start_${name}:
|
|
|
3485
3549
|
}
|
|
3486
3550
|
if (res.buf) {
|
|
3487
3551
|
let binstring = "";
|
|
3488
|
-
|
|
3552
|
+
const buf = res.buf;
|
|
3553
|
+
while (buf.length & 0xf)
|
|
3554
|
+
buf.push(0);
|
|
3555
|
+
pxtc.U.pushRange(buf, encodedSrcMap);
|
|
3556
|
+
for (let v of buf)
|
|
3489
3557
|
binstring += String.fromCharCode(v & 0xff, v >> 8);
|
|
3490
3558
|
binstring = ts.pxtc.encodeBase64(binstring);
|
|
3491
3559
|
if (embedVTs()) {
|
|
3492
3560
|
bin.writeFile(pxtc.BINARY_PXT64, binstring);
|
|
3493
|
-
const patched = pxtc.hexfile.patchHex(bin,
|
|
3561
|
+
const patched = pxtc.hexfile.patchHex(bin, buf, false, !!pxtc.target.useUF2)[0];
|
|
3494
3562
|
bin.writeFile(pxt.outputName(pxtc.target), ts.pxtc.encodeBase64(patched));
|
|
3495
3563
|
}
|
|
3496
3564
|
else {
|
|
@@ -3521,7 +3589,7 @@ _start_${name}:
|
|
|
3521
3589
|
emitAll();
|
|
3522
3590
|
return resText;
|
|
3523
3591
|
function emitAll() {
|
|
3524
|
-
writeRaw(`;\n;
|
|
3592
|
+
writeRaw(`;\n; ${proc.getFullName()}\n;`);
|
|
3525
3593
|
write(".section code");
|
|
3526
3594
|
if (bin.procs[0] == proc) {
|
|
3527
3595
|
writeRaw(`; main`);
|
|
@@ -8263,7 +8331,7 @@ var ts;
|
|
|
8263
8331
|
let name = pxtc.getDeclName(this.action);
|
|
8264
8332
|
if (this.action) {
|
|
8265
8333
|
let info = ts.pxtc.nodeLocationInfo(this.action);
|
|
8266
|
-
name
|
|
8334
|
+
name = info.fileName.replace("pxt_modules/", "") + "(" + (info.line + 1) + "," + (info.column + 1) + "): " + name;
|
|
8267
8335
|
}
|
|
8268
8336
|
return name;
|
|
8269
8337
|
}
|
|
@@ -12206,7 +12274,7 @@ ${lbl}: .short 0xffff
|
|
|
12206
12274
|
}
|
|
12207
12275
|
function emitBrk(node) {
|
|
12208
12276
|
bin.numStmts++;
|
|
12209
|
-
const needsComment = pxtc.assembler.debug || pxtc.target.switches.size;
|
|
12277
|
+
const needsComment = pxtc.assembler.debug || pxtc.target.switches.size || pxtc.target.sourceMap;
|
|
12210
12278
|
let needsBreak = !!opts.breakpoints;
|
|
12211
12279
|
if (!needsComment && !needsBreak)
|
|
12212
12280
|
return;
|
package/built/pxtlib.d.ts
CHANGED
|
@@ -47,6 +47,7 @@ declare namespace pxt.auth {
|
|
|
47
47
|
encoded?: string;
|
|
48
48
|
dataUrl?: string;
|
|
49
49
|
};
|
|
50
|
+
pictureUrl?: string;
|
|
50
51
|
};
|
|
51
52
|
};
|
|
52
53
|
type UserSkillmapState = {
|
|
@@ -876,6 +877,7 @@ declare namespace pxt.commands {
|
|
|
876
877
|
let electronDeployAsync: (r: ts.pxtc.CompileResult) => Promise<void>;
|
|
877
878
|
let webUsbPairDialogAsync: (pairAsync: () => Promise<boolean>, confirmAsync: (options: any) => Promise<number>) => Promise<number>;
|
|
878
879
|
let onTutorialCompleted: () => void;
|
|
880
|
+
let workspaceLoadedAsync: () => Promise<void>;
|
|
879
881
|
}
|
|
880
882
|
declare namespace pxt {
|
|
881
883
|
function lzmaDecompressAsync(buf: Uint8Array): Promise<string>;
|
|
@@ -1925,6 +1927,7 @@ declare namespace ts.pxtc {
|
|
|
1925
1927
|
const BINARY_ELF = "binary.elf";
|
|
1926
1928
|
const BINARY_PXT64 = "binary.pxt64";
|
|
1927
1929
|
const BINARY_ESP = "binary.bin";
|
|
1930
|
+
const BINARY_SRCMAP = "binary.srcmap";
|
|
1928
1931
|
const NATIVE_TYPE_THUMB = "thumb";
|
|
1929
1932
|
const NATIVE_TYPE_VM = "vm";
|
|
1930
1933
|
interface BlocksInfo {
|
|
@@ -3377,6 +3380,7 @@ declare namespace ts.pxtc.assembler {
|
|
|
3377
3380
|
buildLine(tx: string, lst: Line[]): void;
|
|
3378
3381
|
private prepLines;
|
|
3379
3382
|
private iterLines;
|
|
3383
|
+
getSourceMap(): pxt.Map<number[]>;
|
|
3380
3384
|
getSource(clean: boolean, numStmts?: number, flashSize?: number): string;
|
|
3381
3385
|
private peepHole;
|
|
3382
3386
|
private clearLabels;
|
package/built/pxtlib.js
CHANGED
|
@@ -190,6 +190,10 @@ var pxt;
|
|
|
190
190
|
let _client;
|
|
191
191
|
function client() { return _client; }
|
|
192
192
|
auth.client = client;
|
|
193
|
+
const PREFERENCES_DEBOUNCE_MS = 5 * 1000;
|
|
194
|
+
const PREFERENCES_DEBOUNCE_MAX_MS = 30 * 1000;
|
|
195
|
+
let debouncePreferencesChangedTimeout = 0;
|
|
196
|
+
let debouncePreferencesChangedStarted = 0;
|
|
193
197
|
class AuthClient {
|
|
194
198
|
constructor() {
|
|
195
199
|
this.initialUserPreferences_ = undefined;
|
|
@@ -395,15 +399,28 @@ var pxt;
|
|
|
395
399
|
if (!await this.loggedInAsync()) {
|
|
396
400
|
return;
|
|
397
401
|
}
|
|
398
|
-
// If the user is logged in, save to cloud
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
402
|
+
// If the user is logged in, save to cloud, but debounce the api call as this can be called frequently from skillmaps
|
|
403
|
+
clearTimeout(debouncePreferencesChangedTimeout);
|
|
404
|
+
const savePrefs = async () => {
|
|
405
|
+
debouncePreferencesChangedStarted = 0;
|
|
406
|
+
const result = await this.apiAsync('/api/user/preferences', ops, 'PATCH');
|
|
407
|
+
if (result.success) {
|
|
408
|
+
pxt.debug("Updating local user preferences w/ cloud data after result of POST");
|
|
409
|
+
// Set user profile from returned value so we stay in-sync
|
|
410
|
+
this.setUserPreferencesAsync(result.resp);
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
pxt.reportError("identity", "update preferences failed", result);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
if (!debouncePreferencesChangedStarted) {
|
|
417
|
+
debouncePreferencesChangedStarted = pxt.U.now();
|
|
418
|
+
}
|
|
419
|
+
if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
|
|
420
|
+
await savePrefs();
|
|
404
421
|
}
|
|
405
422
|
else {
|
|
406
|
-
|
|
423
|
+
debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
|
|
407
424
|
}
|
|
408
425
|
}
|
|
409
426
|
/*protected*/ hasUserId() {
|
|
@@ -3366,6 +3383,8 @@ var pxt;
|
|
|
3366
3383
|
}
|
|
3367
3384
|
if (!comp.switches)
|
|
3368
3385
|
comp.switches = {};
|
|
3386
|
+
if (comp.nativeType == pxtc.NATIVE_TYPE_VM)
|
|
3387
|
+
comp.sourceMap = true;
|
|
3369
3388
|
pxt.U.jsonCopyFrom(comp.switches, savedSwitches);
|
|
3370
3389
|
// JS ref counting currently not supported
|
|
3371
3390
|
comp.jsRefCounting = false;
|
|
@@ -5713,6 +5732,7 @@ var pxt;
|
|
|
5713
5732
|
commands.electronDeployAsync = undefined; // A pointer to the Electron deploy function, so that targets can access it in their extension.ts
|
|
5714
5733
|
commands.webUsbPairDialogAsync = undefined;
|
|
5715
5734
|
commands.onTutorialCompleted = undefined;
|
|
5735
|
+
commands.workspaceLoadedAsync = undefined;
|
|
5716
5736
|
})(commands = pxt.commands || (pxt.commands = {}));
|
|
5717
5737
|
})(pxt || (pxt = {}));
|
|
5718
5738
|
/// <reference path="../localtypings/pxtarget.d.ts"/>
|
|
@@ -6959,7 +6979,7 @@ int main() {
|
|
|
6959
6979
|
.then(ret => new Promise((resolve, reject) => {
|
|
6960
6980
|
let retry = 0;
|
|
6961
6981
|
const delay = 8000; // ms
|
|
6962
|
-
const maxWait =
|
|
6982
|
+
const maxWait = 300000; // ms
|
|
6963
6983
|
const startTry = pxt.U.now();
|
|
6964
6984
|
const tryGet = () => {
|
|
6965
6985
|
retry++;
|
|
@@ -15159,6 +15179,7 @@ var ts;
|
|
|
15159
15179
|
pxtc.BINARY_ELF = "binary.elf";
|
|
15160
15180
|
pxtc.BINARY_PXT64 = "binary.pxt64";
|
|
15161
15181
|
pxtc.BINARY_ESP = "binary.bin";
|
|
15182
|
+
pxtc.BINARY_SRCMAP = "binary.srcmap";
|
|
15162
15183
|
pxtc.NATIVE_TYPE_THUMB = "thumb";
|
|
15163
15184
|
pxtc.NATIVE_TYPE_VM = "vm";
|
|
15164
15185
|
function BuildSourceMapHelpers(sourceMap, tsFile, pyFile) {
|
|
@@ -21023,7 +21044,6 @@ var pxt;
|
|
|
21023
21044
|
youtube.watchUrl = watchUrl;
|
|
21024
21045
|
})(youtube = pxt.youtube || (pxt.youtube = {}));
|
|
21025
21046
|
})(pxt || (pxt = {}));
|
|
21026
|
-
/* eslint-disable no-cond-assign */
|
|
21027
21047
|
// TODO: add a macro facility to make 8-bit assembly easier?
|
|
21028
21048
|
var ts;
|
|
21029
21049
|
(function (ts) {
|
|
@@ -21281,7 +21301,7 @@ var ts;
|
|
|
21281
21301
|
// recursive-descent parsing of multiplication
|
|
21282
21302
|
if (s.indexOf("*") >= 0) {
|
|
21283
21303
|
let m = null;
|
|
21284
|
-
while (m = /^([^\*]*)\*(.*)$/.exec(s)) {
|
|
21304
|
+
while (null != (m = /^([^\*]*)\*(.*)$/.exec(s))) {
|
|
21285
21305
|
let tmp = this.parseOneInt(m[1]);
|
|
21286
21306
|
if (tmp == null)
|
|
21287
21307
|
return null;
|
|
@@ -21896,6 +21916,37 @@ var ts;
|
|
|
21896
21916
|
}
|
|
21897
21917
|
});
|
|
21898
21918
|
}
|
|
21919
|
+
getSourceMap() {
|
|
21920
|
+
const sourceMap = {};
|
|
21921
|
+
let locFile = "";
|
|
21922
|
+
let locLn = 0;
|
|
21923
|
+
let locPos = 0;
|
|
21924
|
+
let locEnd = 0;
|
|
21925
|
+
this.lines.forEach((ln, i) => {
|
|
21926
|
+
const m = /^; ([\w\/\.-]+)\(([\d]+),\d+\):/.exec(ln.text);
|
|
21927
|
+
if (m) {
|
|
21928
|
+
flush();
|
|
21929
|
+
locFile = m[1];
|
|
21930
|
+
locLn = parseInt(m[2]);
|
|
21931
|
+
}
|
|
21932
|
+
if (ln.type == "instruction") {
|
|
21933
|
+
if (!locPos)
|
|
21934
|
+
locPos = ln.location;
|
|
21935
|
+
locEnd = ln.location;
|
|
21936
|
+
}
|
|
21937
|
+
});
|
|
21938
|
+
flush();
|
|
21939
|
+
function flush() {
|
|
21940
|
+
if (locFile && locPos) {
|
|
21941
|
+
if (!sourceMap[locFile])
|
|
21942
|
+
sourceMap[locFile] = [];
|
|
21943
|
+
sourceMap[locFile].push(locLn, locPos, locEnd - locPos);
|
|
21944
|
+
}
|
|
21945
|
+
locPos = 0;
|
|
21946
|
+
locEnd = 0;
|
|
21947
|
+
}
|
|
21948
|
+
return sourceMap;
|
|
21949
|
+
}
|
|
21899
21950
|
getSource(clean, numStmts = 1, flashSize = 0) {
|
|
21900
21951
|
let lenPrev = 0;
|
|
21901
21952
|
let size = (lbl) => {
|