pxt-core 12.3.20 → 12.3.22

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/pxtlib.js CHANGED
@@ -4236,6 +4236,7 @@ var pxt;
4236
4236
  pxt.TUTORIAL_CODE_STOP = "_onCodeStop.ts";
4237
4237
  pxt.TUTORIAL_INFO_FILE = "tutorial-info-cache.json";
4238
4238
  pxt.TUTORIAL_CUSTOM_TS = "tutorial.custom.ts";
4239
+ pxt.PACKAGED_EXTENSIONS = "_packaged-extensions.json";
4239
4240
  pxt.BREAKPOINT_TABLET = 991; // TODO (shakao) revisit when tutorial stuff is more settled
4240
4241
  pxt.PALETTES_FILE = "_palettes.json";
4241
4242
  pxt.HISTORY_FILE = "_history";
@@ -4282,6 +4283,30 @@ var pxt;
4282
4283
  };
4283
4284
  // Like MATH_FUNCTIONS, but used only for rounding operations
4284
4285
  blocks.ROUNDING_FUNCTIONS = ["round", "ceil", "floor", "trunc"];
4286
+ function parameterDefaultLocalizationKey(qName, actualName) {
4287
+ return qName ? `${qName}|param|${actualName}|defl` : undefined;
4288
+ }
4289
+ blocks.parameterDefaultLocalizationKey = parameterDefaultLocalizationKey;
4290
+ function parameterDefaultToLocalizationString(defaultValue, type) {
4291
+ if (!defaultValue)
4292
+ return undefined;
4293
+ if (type === "string" && defaultValue.charAt(0) !== "\"")
4294
+ return defaultValue;
4295
+ if (defaultValue.charAt(0) !== "\"")
4296
+ return undefined;
4297
+ try {
4298
+ const value = JSON.parse(defaultValue);
4299
+ return typeof value === "string" ? value : undefined;
4300
+ }
4301
+ catch (e) {
4302
+ return undefined;
4303
+ }
4304
+ }
4305
+ blocks.parameterDefaultToLocalizationString = parameterDefaultToLocalizationString;
4306
+ function localizationStringToParameterDefault(value) {
4307
+ return JSON.stringify(value);
4308
+ }
4309
+ blocks.localizationStringToParameterDefault = localizationStringToParameterDefault;
4285
4310
  // Information for blocks that compile to function calls but are defined by vanilla Blockly
4286
4311
  // and not dynamically by BlocklyLoader
4287
4312
  blocks.builtinFunctionInfo = {
@@ -8063,6 +8088,13 @@ int main() {
8063
8088
  });
8064
8089
  }
8065
8090
  hexloader.recordGetAsync = recordGetAsync;
8091
+ function stringifyHexInfoForCache(hexInfo) {
8092
+ if (!(hexInfo === null || hexInfo === void 0 ? void 0 : hexInfo.hex))
8093
+ return undefined;
8094
+ const cachedMeta = Object.assign(Object.assign({}, hexInfo), { hex: compressHex(hexInfo.hex) });
8095
+ return JSON.stringify(cachedMeta);
8096
+ }
8097
+ hexloader.stringifyHexInfoForCache = stringifyHexInfoForCache;
8066
8098
  function getHexInfoAsync(host, extInfo, cloudModule) {
8067
8099
  if (!extInfo.sha)
8068
8100
  return Promise.resolve(null);
@@ -8091,10 +8123,7 @@ int main() {
8091
8123
  else {
8092
8124
  return downloadHexInfoAsync(extInfo)
8093
8125
  .then(meta => {
8094
- let origHex = meta.hex;
8095
- meta.hex = compressHex(meta.hex);
8096
- let store = JSON.stringify(meta);
8097
- meta.hex = origHex;
8126
+ let store = stringifyHexInfoForCache(meta);
8098
8127
  return storeWithLimitAsync(host, "hex-keys", key, store)
8099
8128
  .then(() => meta);
8100
8129
  }).catch(e => {
@@ -10686,6 +10715,18 @@ var pxt;
10686
10715
  }
10687
10716
  github.shouldUseProxyForRepo = shouldUseProxyForRepo;
10688
10717
  const isPrivateRepoCache = {};
10718
+ function copyCachedPackage(cachedPackage) {
10719
+ return {
10720
+ files: Object.assign({}, cachedPackage.files)
10721
+ };
10722
+ }
10723
+ function cachedPackageFromFallback(fallbackPackageFiles) {
10724
+ if (!fallbackPackageFiles)
10725
+ return undefined;
10726
+ return {
10727
+ files: Object.assign({}, fallbackPackageFiles)
10728
+ };
10729
+ }
10689
10730
  function ghRequestAsync(options) {
10690
10731
  var _a;
10691
10732
  options.method = (_a = options.method) !== null && _a !== void 0 ? _a : "GET";
@@ -10797,7 +10838,7 @@ var pxt;
10797
10838
  }
10798
10839
  return resolved;
10799
10840
  }
10800
- async loadPackageAsync(repopath, tag) {
10841
+ async loadPackageAsync(repopath, tag, fallbackPackageFiles) {
10801
10842
  if (!tag) {
10802
10843
  pxt.debug(`load pkg: default to master branch`);
10803
10844
  tag = "master";
@@ -10805,45 +10846,46 @@ var pxt;
10805
10846
  // try using github proxy first
10806
10847
  if (hasProxy()) {
10807
10848
  try {
10808
- return await this.proxyWithCdnLoadPackageAsync(repopath, tag).then(v => pxt.U.clone(v));
10849
+ return await this.proxyWithCdnLoadPackageAsync(repopath, tag).then(copyCachedPackage);
10809
10850
  }
10810
10851
  catch (e) {
10811
10852
  ghProxyHandleException(e);
10812
10853
  }
10813
10854
  }
10814
10855
  // try using github apis
10815
- return await this.githubLoadPackageAsync(repopath, tag);
10856
+ return await this.githubLoadPackageAsync(repopath, tag, fallbackPackageFiles);
10816
10857
  }
10817
- githubLoadPackageAsync(repopath, tag) {
10818
- return tagToShaAsync(repopath, tag)
10819
- .then(sha => {
10858
+ async githubLoadPackageAsync(repopath, tag, fallbackPackageFiles) {
10859
+ try {
10860
+ const sha = await tagToShaAsync(repopath, tag);
10820
10861
  // cache lookup
10821
10862
  const key = `${repopath}/${sha}`;
10822
10863
  let res = this.packages[key];
10823
10864
  if (res) {
10824
10865
  pxt.debug(`github cache ${repopath}/${tag}/text`);
10825
- return Promise.resolve(pxt.U.clone(res));
10866
+ return copyCachedPackage(res);
10826
10867
  }
10827
10868
  // load and cache
10828
10869
  pxt.log(`Downloading ${repopath}/${tag} -> ${sha}`);
10829
- return downloadTextAsync(repopath, sha, pxt.CONFIG_NAME)
10830
- .then(pkg => {
10831
- const current = {
10832
- files: {}
10833
- };
10834
- current.files[pxt.CONFIG_NAME] = pkg;
10835
- const cfg = JSON.parse(pkg);
10836
- return pxt.U.promiseMapAll(pxt.allPkgFiles(cfg).slice(1), fn => downloadTextAsync(repopath, sha, fn)
10837
- .then(text => {
10838
- current.files[fn] = text;
10839
- }))
10840
- .then(() => {
10841
- // cache!
10842
- this.packages[key] = current;
10843
- return pxt.U.clone(current);
10844
- });
10870
+ const pkg = await downloadTextAsync(repopath, sha, pxt.CONFIG_NAME);
10871
+ const current = {
10872
+ files: {}
10873
+ };
10874
+ current.files[pxt.CONFIG_NAME] = pkg;
10875
+ const cfg = JSON.parse(pkg);
10876
+ await pxt.U.promiseMapAll(pxt.allPkgFiles(cfg).slice(1), async (fn) => {
10877
+ current.files[fn] = await downloadTextAsync(repopath, sha, fn);
10845
10878
  });
10846
- });
10879
+ // cache!
10880
+ this.packages[key] = current;
10881
+ return copyCachedPackage(current);
10882
+ }
10883
+ catch (e) {
10884
+ const fallbackPackage = cachedPackageFromFallback(fallbackPackageFiles);
10885
+ if (fallbackPackage)
10886
+ return fallbackPackage;
10887
+ throw e;
10888
+ }
10847
10889
  }
10848
10890
  async loadTutorialMarkdown(repopath, tag) {
10849
10891
  repopath = normalizeTutorialPath(repopath);
@@ -11199,7 +11241,7 @@ var pxt;
11199
11241
  return await github.db.loadConfigAsync(repopath, tag);
11200
11242
  }
11201
11243
  github.pkgConfigAsync = pkgConfigAsync;
11202
- async function downloadPackageAsync(repoWithTag, config) {
11244
+ async function downloadPackageAsync(repoWithTag, config, fallbackPackageFiles) {
11203
11245
  const p = parseRepoId(repoWithTag);
11204
11246
  if (!p) {
11205
11247
  pxt.log('Unknown GitHub syntax');
@@ -11212,9 +11254,17 @@ var pxt;
11212
11254
  }
11213
11255
  // always try to upgrade unbound versions
11214
11256
  if (!p.tag) {
11215
- p.tag = await github.db.latestVersionAsync(p.slug, config);
11257
+ try {
11258
+ p.tag = await github.db.latestVersionAsync(p.slug, config);
11259
+ }
11260
+ catch (e) {
11261
+ const fallbackPackage = cachedPackageFromFallback(fallbackPackageFiles);
11262
+ if (fallbackPackage)
11263
+ return fallbackPackage;
11264
+ throw e;
11265
+ }
11216
11266
  }
11217
- const cached = await github.db.loadPackageAsync(p.fullName, p.tag);
11267
+ const cached = await github.db.loadPackageAsync(p.fullName, p.tag, fallbackPackageFiles);
11218
11268
  const dv = upgradedDisablesVariants(config, repoWithTag);
11219
11269
  if (dv) {
11220
11270
  const cfg = pxt.Package.parseAndValidConfig(cached.files[pxt.CONFIG_NAME]);
@@ -11239,7 +11289,11 @@ var pxt;
11239
11289
  return { version, config };
11240
11290
  }
11241
11291
  github.downloadLatestPackageAsync = downloadLatestPackageAsync;
11242
- async function cacheProjectDependenciesAsync(cfg) {
11292
+ async function cacheProjectDependenciesAsync(cfg, fallbackPackageFilesById) {
11293
+ await cacheProjectDependenciesCoreAsync(cfg, {}, fallbackPackageFilesById);
11294
+ }
11295
+ github.cacheProjectDependenciesAsync = cacheProjectDependenciesAsync;
11296
+ async function cacheProjectDependenciesCoreAsync(cfg, checked, fallbackPackageFilesById) {
11243
11297
  var _a;
11244
11298
  const ghExtensions = (_a = Object.keys(cfg.dependencies)) === null || _a === void 0 ? void 0 : _a.filter(dep => isGithubId(cfg.dependencies[dep]));
11245
11299
  if (ghExtensions.length) {
@@ -11247,14 +11301,19 @@ var pxt;
11247
11301
  // Make sure external packages load before installing header.
11248
11302
  await Promise.all(ghExtensions.map(async (ext) => {
11249
11303
  const extSrc = cfg.dependencies[ext];
11250
- const ghPkg = await downloadPackageAsync(extSrc, pkgConfig);
11304
+ if (checked[extSrc])
11305
+ return;
11306
+ checked[extSrc] = true;
11307
+ const ghPkg = await downloadPackageAsync(extSrc, pkgConfig, fallbackPackageFilesById === null || fallbackPackageFilesById === void 0 ? void 0 : fallbackPackageFilesById[extSrc]);
11251
11308
  if (!ghPkg) {
11252
11309
  throw new Error(lf("Cannot load extension {0} from {1}", ext, extSrc));
11253
11310
  }
11311
+ const ghPkgCfg = pxt.Package.parseAndValidConfig(ghPkg.files[pxt.CONFIG_NAME]);
11312
+ if (ghPkgCfg)
11313
+ await cacheProjectDependenciesCoreAsync(ghPkgCfg, checked, fallbackPackageFilesById);
11254
11314
  }));
11255
11315
  }
11256
11316
  }
11257
- github.cacheProjectDependenciesAsync = cacheProjectDependenciesAsync;
11258
11317
  let GitRepoStatus;
11259
11318
  (function (GitRepoStatus) {
11260
11319
  GitRepoStatus[GitRepoStatus["Unknown"] = 0] = "Unknown";
@@ -17304,7 +17363,7 @@ var pxt;
17304
17363
  this.config.binaryonly ||
17305
17364
  !opts.target.isNative;
17306
17365
  if (!noFileEmbed) {
17307
- const files = await this.filesToBePublishedAsync(true);
17366
+ const files = await this.filesToBePublishedAsync(true, !pxt.appTarget.compile.useUF2);
17308
17367
  const headerString = JSON.stringify({
17309
17368
  name: this.config.name,
17310
17369
  comment: this.config.description,
@@ -17376,25 +17435,61 @@ var pxt;
17376
17435
  cfg.files = cfg.files.filter(fn => fn !== pxt.HISTORY_FILE);
17377
17436
  return cfg;
17378
17437
  }
17379
- filesToBePublishedAsync(allowPrivate = false) {
17438
+ async filesToBePublishedAsync(allowPrivate = false, packExternalExtensions = false) {
17380
17439
  const files = {};
17381
- return this.loadAsync()
17382
- .then(() => {
17383
- if (!allowPrivate && !this.config.public)
17384
- pxt.U.userError('Only packages with "public":true can be published');
17385
- const cfg = this.prepareConfigToBePublished();
17386
- files[pxt.CONFIG_NAME] = pxt.Package.stringifyConfig(cfg);
17387
- for (let f of this.getFiles()) {
17388
- // already stored
17389
- if (f === pxt.CONFIG_NAME || f === pxt.HISTORY_FILE)
17440
+ await this.loadAsync();
17441
+ if (!allowPrivate && !this.config.public)
17442
+ pxt.U.userError('Only packages with "public":true can be published');
17443
+ const cfg = this.prepareConfigToBePublished();
17444
+ files[pxt.CONFIG_NAME] = pxt.Package.stringifyConfig(cfg);
17445
+ for (let f of this.getFiles()) {
17446
+ // already stored
17447
+ if (f === pxt.CONFIG_NAME || f === pxt.HISTORY_FILE)
17448
+ continue;
17449
+ let str = this.readFile(f);
17450
+ if (str == null)
17451
+ pxt.U.userError("referenced file missing: " + f);
17452
+ files[f] = str;
17453
+ }
17454
+ if (packExternalExtensions) {
17455
+ const packagedExtensions = this.packagedExternalExtensions();
17456
+ if (Object.keys(packagedExtensions).length)
17457
+ files[pxt.PACKAGED_EXTENSIONS] = JSON.stringify(packagedExtensions);
17458
+ }
17459
+ return pxt.U.sortObjectFields(files);
17460
+ }
17461
+ packagedExternalExtensions() {
17462
+ const packaged = {};
17463
+ const seen = {};
17464
+ const packDeps = (pkg) => {
17465
+ for (const dep of pkg.resolvedDependencies()) {
17466
+ if (!dep)
17467
+ continue;
17468
+ const seenKey = `${dep.id}:${dep.version()}`;
17469
+ if (seen[seenKey])
17390
17470
  continue;
17391
- let str = this.readFile(f);
17392
- if (str == null)
17393
- pxt.U.userError("referenced file missing: " + f);
17394
- files[f] = str;
17471
+ seen[seenKey] = true;
17472
+ if (dep.verProtocol() === "github" || dep.verProtocol() === "pub") {
17473
+ const depFiles = {};
17474
+ for (const fn of dep.getFiles()) {
17475
+ if (fn === pxt.CONFIG_NAME || fn === pxt.HISTORY_FILE)
17476
+ continue;
17477
+ const content = dep.readFile(fn);
17478
+ if (content != null)
17479
+ depFiles[fn] = content;
17480
+ }
17481
+ depFiles[pxt.CONFIG_NAME] = pxt.Package.stringifyConfig(dep.config);
17482
+ packaged[dep._verspec] = depFiles;
17483
+ if (dep.version() !== dep._verspec)
17484
+ packaged[dep.version()] = depFiles;
17485
+ if (dep.verProtocol() === "pub")
17486
+ packaged[dep.verArgument()] = depFiles;
17487
+ }
17488
+ packDeps(dep);
17395
17489
  }
17396
- return pxt.U.sortObjectFields(files);
17397
- });
17490
+ };
17491
+ packDeps(this);
17492
+ return packaged;
17398
17493
  }
17399
17494
  saveToJsonAsync() {
17400
17495
  return this.filesToBePublishedAsync(true)
@@ -18339,18 +18434,25 @@ var ts;
18339
18434
  const langLower = lang.toLowerCase();
18340
18435
  const attrJsLocsKey = langLower + "|jsdoc";
18341
18436
  const attrBlockLocsKey = langLower + "|block";
18437
+ const attrAriaLabelLocsKey = langLower + "|ariaLabel";
18342
18438
  const loc = await mainPkg.localizationStringsAsync(lang);
18343
18439
  if (pxtc.apiLocalizationStrings)
18344
18440
  pxtc.Util.jsonMergeFrom(loc, pxtc.apiLocalizationStrings);
18345
18441
  const toLocalize = pxtc.Util.values(apis.byQName).filter(fn => fn.attributes._translatedLanguageCode !== lang);
18346
18442
  await pxtc.Util.promiseMapAll(toLocalize, async (fn) => {
18347
- var _a, _b, _c;
18443
+ var _a, _b, _c, _d;
18348
18444
  const altLocSrc = fn.attributes.useLoc || fn.attributes.blockAliasFor;
18349
18445
  const altLocSrcFn = altLocSrc && apis.byQName[altLocSrc];
18350
18446
  if (fn.attributes._untranslatedJsDoc)
18351
18447
  fn.attributes.jsDoc = fn.attributes._untranslatedJsDoc;
18352
18448
  if (fn.attributes._untranslatedBlock)
18353
- fn.attributes.jsDoc = fn.attributes._untranslatedBlock;
18449
+ fn.attributes.block = fn.attributes._untranslatedBlock;
18450
+ if (fn.attributes._untranslatedAriaLabel)
18451
+ fn.attributes.ariaLabel = fn.attributes._untranslatedAriaLabel;
18452
+ if (fn.attributes._untranslatedParamDefl) {
18453
+ fn.attributes.paramDefl = pxtc.U.clone(fn.attributes._untranslatedParamDefl);
18454
+ syncParameterDefaults(fn);
18455
+ }
18354
18456
  const lookupLoc = (locSuff, attrKey) => {
18355
18457
  var _a, _b;
18356
18458
  return loc[fn.qName + locSuff] || ((_a = fn.attributes.locs) === null || _a === void 0 ? void 0 : _a[attrKey])
@@ -18372,6 +18474,7 @@ var ts;
18372
18474
  });
18373
18475
  const nsDoc = loc['{id:category}' + pxtc.Util.capitalize(fn.qName)];
18374
18476
  let locBlock = loc[`${fn.qName}|block`] || ((_b = fn.attributes.locs) === null || _b === void 0 ? void 0 : _b[attrBlockLocsKey]);
18477
+ const locAriaLabel = loc[`${fn.qName}|ariaLabel`] || ((_c = fn.attributes.locs) === null || _c === void 0 ? void 0 : _c[attrAriaLabelLocsKey]);
18375
18478
  if (fn.attributes.block) {
18376
18479
  const comp = pxt.blocks.compileInfo(fn);
18377
18480
  if (comp.handlerArgs) {
@@ -18386,20 +18489,35 @@ var ts;
18386
18489
  }
18387
18490
  const paramsWithLabels = comp.thisParameter ? [comp.thisParameter, ...comp.parameters] : comp.parameters;
18388
18491
  for (const param of paramsWithLabels) {
18389
- if (!param.labelLocalizationKey)
18390
- continue;
18391
- const locSuff = param.labelLocalizationKey.slice(fn.qName.length);
18392
- const paramLabel = lookupLoc(locSuff, langLower + locSuff);
18393
- if (paramLabel) {
18394
- setBlockTranslationCacheKey(param.labelLocalizationKey, paramLabel);
18492
+ if (param.labelLocalizationKey) {
18493
+ const locSuff = param.labelLocalizationKey.slice(fn.qName.length);
18494
+ const paramLabel = lookupLoc(locSuff, langLower + locSuff);
18495
+ if (paramLabel) {
18496
+ setBlockTranslationCacheKey(param.labelLocalizationKey, paramLabel);
18497
+ }
18498
+ else {
18499
+ clearBlockTranslationCacheKey(param.labelLocalizationKey);
18500
+ }
18395
18501
  }
18396
- else {
18397
- clearBlockTranslationCacheKey(param.labelLocalizationKey);
18502
+ const defaultString = pxt.blocks.parameterDefaultToLocalizationString(param.defaultValue, param.type);
18503
+ const defaultLocalizationKey = pxt.blocks.parameterDefaultLocalizationKey(fn.qName, param.actualName);
18504
+ if (defaultLocalizationKey && defaultString !== undefined) {
18505
+ const locSuff = defaultLocalizationKey.slice(fn.qName.length);
18506
+ const paramDefault = lookupLoc(locSuff, langLower + locSuff);
18507
+ if (paramDefault !== undefined) {
18508
+ if (!fn.attributes._untranslatedParamDefl) {
18509
+ fn.attributes._untranslatedParamDefl = pxtc.U.clone(fn.attributes.paramDefl || {});
18510
+ }
18511
+ if (!fn.attributes.paramDefl)
18512
+ fn.attributes.paramDefl = {};
18513
+ fn.attributes.paramDefl[param.actualName] = pxt.blocks.localizationStringToParameterDefault(paramDefault);
18514
+ syncParameterDefaults(fn);
18515
+ }
18398
18516
  }
18399
18517
  }
18400
18518
  }
18401
18519
  if (!locBlock && altLocSrcFn) {
18402
- const otherTranslation = loc[`${altLocSrcFn.qName}|block`] || ((_c = altLocSrcFn.attributes.locs) === null || _c === void 0 ? void 0 : _c[attrBlockLocsKey]);
18520
+ const otherTranslation = loc[`${altLocSrcFn.qName}|block`] || ((_d = altLocSrcFn.attributes.locs) === null || _d === void 0 ? void 0 : _d[attrBlockLocsKey]);
18403
18521
  const isSameBlockDef = fn.attributes.block === (altLocSrcFn.attributes._untranslatedBlock || altLocSrcFn.attributes.block);
18404
18522
  if (isSameBlockDef && !!otherTranslation) {
18405
18523
  locBlock = otherTranslation;
@@ -18456,11 +18574,24 @@ var ts;
18456
18574
  else {
18457
18575
  updateBlockDef(fn.attributes);
18458
18576
  }
18577
+ if (locAriaLabel) {
18578
+ if (!fn.attributes._untranslatedAriaLabel) {
18579
+ fn.attributes._untranslatedAriaLabel = fn.attributes.ariaLabel;
18580
+ }
18581
+ fn.attributes.ariaLabel = locAriaLabel;
18582
+ }
18459
18583
  fn.attributes._translatedLanguageCode = lang;
18460
18584
  });
18461
18585
  return cleanLocalizations(apis);
18462
18586
  }
18463
18587
  pxtc.localizeApisAsync = localizeApisAsync;
18588
+ function syncParameterDefaults(fn) {
18589
+ if (!fn.parameters)
18590
+ return;
18591
+ for (const param of fn.parameters) {
18592
+ param.default = fn.attributes.paramDefl && fn.attributes.paramDefl[param.name];
18593
+ }
18594
+ }
18464
18595
  function cleanLocalizations(apis) {
18465
18596
  pxtc.Util.values(apis.byQName)
18466
18597
  .filter(fb => fb.attributes.block && /^{[^:]+:[^}]+}/.test(fb.attributes.block))
@@ -18584,6 +18715,11 @@ var ts;
18584
18715
  res.locs = {};
18585
18716
  res.locs[n.slice("jsdoc.loc.".length).toLowerCase() + "|jsdoc"] = v;
18586
18717
  }
18718
+ else if (pxtc.U.startsWith(n, "ariaLabel.loc.")) {
18719
+ if (!res.locs)
18720
+ res.locs = {};
18721
+ res.locs[n.slice("ariaLabel.loc.".length).toLowerCase() + "|ariaLabel"] = v;
18722
+ }
18587
18723
  else if (pxtc.U.contains(n, ".loc.")) {
18588
18724
  if (!res.locs)
18589
18725
  res.locs = {};