pxt-core 12.3.20 → 12.3.21

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,8 @@ 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";
4240
+ pxt.PACKAGED_EXT_INFO = "_packaged-ext-info.json";
4239
4241
  pxt.BREAKPOINT_TABLET = 991; // TODO (shakao) revisit when tutorial stuff is more settled
4240
4242
  pxt.PALETTES_FILE = "_palettes.json";
4241
4243
  pxt.HISTORY_FILE = "_history";
@@ -4282,6 +4284,30 @@ var pxt;
4282
4284
  };
4283
4285
  // Like MATH_FUNCTIONS, but used only for rounding operations
4284
4286
  blocks.ROUNDING_FUNCTIONS = ["round", "ceil", "floor", "trunc"];
4287
+ function parameterDefaultLocalizationKey(qName, actualName) {
4288
+ return qName ? `${qName}|param|${actualName}|defl` : undefined;
4289
+ }
4290
+ blocks.parameterDefaultLocalizationKey = parameterDefaultLocalizationKey;
4291
+ function parameterDefaultToLocalizationString(defaultValue, type) {
4292
+ if (!defaultValue)
4293
+ return undefined;
4294
+ if (type === "string" && defaultValue.charAt(0) !== "\"")
4295
+ return defaultValue;
4296
+ if (defaultValue.charAt(0) !== "\"")
4297
+ return undefined;
4298
+ try {
4299
+ const value = JSON.parse(defaultValue);
4300
+ return typeof value === "string" ? value : undefined;
4301
+ }
4302
+ catch (e) {
4303
+ return undefined;
4304
+ }
4305
+ }
4306
+ blocks.parameterDefaultToLocalizationString = parameterDefaultToLocalizationString;
4307
+ function localizationStringToParameterDefault(value) {
4308
+ return JSON.stringify(value);
4309
+ }
4310
+ blocks.localizationStringToParameterDefault = localizationStringToParameterDefault;
4285
4311
  // Information for blocks that compile to function calls but are defined by vanilla Blockly
4286
4312
  // and not dynamically by BlocklyLoader
4287
4313
  blocks.builtinFunctionInfo = {
@@ -8063,6 +8089,19 @@ int main() {
8063
8089
  });
8064
8090
  }
8065
8091
  hexloader.recordGetAsync = recordGetAsync;
8092
+ function stringifyHexInfoForCache(hexInfo) {
8093
+ if (!(hexInfo === null || hexInfo === void 0 ? void 0 : hexInfo.hex))
8094
+ return undefined;
8095
+ const cachedMeta = Object.assign(Object.assign({}, hexInfo), { hex: compressHex(hexInfo.hex) });
8096
+ return JSON.stringify(cachedMeta);
8097
+ }
8098
+ hexloader.stringifyHexInfoForCache = stringifyHexInfoForCache;
8099
+ function storeHexInfoCacheEntryAsync(host, sha, cachedHexInfo) {
8100
+ if (!sha || !cachedHexInfo)
8101
+ return Promise.resolve();
8102
+ return storeWithLimitAsync(host, "hex-keys", "hex-" + sha, cachedHexInfo);
8103
+ }
8104
+ hexloader.storeHexInfoCacheEntryAsync = storeHexInfoCacheEntryAsync;
8066
8105
  function getHexInfoAsync(host, extInfo, cloudModule) {
8067
8106
  if (!extInfo.sha)
8068
8107
  return Promise.resolve(null);
@@ -8091,10 +8130,7 @@ int main() {
8091
8130
  else {
8092
8131
  return downloadHexInfoAsync(extInfo)
8093
8132
  .then(meta => {
8094
- let origHex = meta.hex;
8095
- meta.hex = compressHex(meta.hex);
8096
- let store = JSON.stringify(meta);
8097
- meta.hex = origHex;
8133
+ let store = stringifyHexInfoForCache(meta);
8098
8134
  return storeWithLimitAsync(host, "hex-keys", key, store)
8099
8135
  .then(() => meta);
8100
8136
  }).catch(e => {
@@ -10686,6 +10722,18 @@ var pxt;
10686
10722
  }
10687
10723
  github.shouldUseProxyForRepo = shouldUseProxyForRepo;
10688
10724
  const isPrivateRepoCache = {};
10725
+ function copyCachedPackage(cachedPackage) {
10726
+ return {
10727
+ files: Object.assign({}, cachedPackage.files)
10728
+ };
10729
+ }
10730
+ function cachedPackageFromFallback(fallbackPackageFiles) {
10731
+ if (!fallbackPackageFiles)
10732
+ return undefined;
10733
+ return {
10734
+ files: Object.assign({}, fallbackPackageFiles)
10735
+ };
10736
+ }
10689
10737
  function ghRequestAsync(options) {
10690
10738
  var _a;
10691
10739
  options.method = (_a = options.method) !== null && _a !== void 0 ? _a : "GET";
@@ -10797,7 +10845,7 @@ var pxt;
10797
10845
  }
10798
10846
  return resolved;
10799
10847
  }
10800
- async loadPackageAsync(repopath, tag) {
10848
+ async loadPackageAsync(repopath, tag, fallbackPackageFiles) {
10801
10849
  if (!tag) {
10802
10850
  pxt.debug(`load pkg: default to master branch`);
10803
10851
  tag = "master";
@@ -10805,45 +10853,46 @@ var pxt;
10805
10853
  // try using github proxy first
10806
10854
  if (hasProxy()) {
10807
10855
  try {
10808
- return await this.proxyWithCdnLoadPackageAsync(repopath, tag).then(v => pxt.U.clone(v));
10856
+ return await this.proxyWithCdnLoadPackageAsync(repopath, tag).then(copyCachedPackage);
10809
10857
  }
10810
10858
  catch (e) {
10811
10859
  ghProxyHandleException(e);
10812
10860
  }
10813
10861
  }
10814
10862
  // try using github apis
10815
- return await this.githubLoadPackageAsync(repopath, tag);
10863
+ return await this.githubLoadPackageAsync(repopath, tag, fallbackPackageFiles);
10816
10864
  }
10817
- githubLoadPackageAsync(repopath, tag) {
10818
- return tagToShaAsync(repopath, tag)
10819
- .then(sha => {
10865
+ async githubLoadPackageAsync(repopath, tag, fallbackPackageFiles) {
10866
+ try {
10867
+ const sha = await tagToShaAsync(repopath, tag);
10820
10868
  // cache lookup
10821
10869
  const key = `${repopath}/${sha}`;
10822
10870
  let res = this.packages[key];
10823
10871
  if (res) {
10824
10872
  pxt.debug(`github cache ${repopath}/${tag}/text`);
10825
- return Promise.resolve(pxt.U.clone(res));
10873
+ return copyCachedPackage(res);
10826
10874
  }
10827
10875
  // load and cache
10828
10876
  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
- });
10877
+ const pkg = await downloadTextAsync(repopath, sha, pxt.CONFIG_NAME);
10878
+ const current = {
10879
+ files: {}
10880
+ };
10881
+ current.files[pxt.CONFIG_NAME] = pkg;
10882
+ const cfg = JSON.parse(pkg);
10883
+ await pxt.U.promiseMapAll(pxt.allPkgFiles(cfg).slice(1), async (fn) => {
10884
+ current.files[fn] = await downloadTextAsync(repopath, sha, fn);
10845
10885
  });
10846
- });
10886
+ // cache!
10887
+ this.packages[key] = current;
10888
+ return copyCachedPackage(current);
10889
+ }
10890
+ catch (e) {
10891
+ const fallbackPackage = cachedPackageFromFallback(fallbackPackageFiles);
10892
+ if (fallbackPackage)
10893
+ return fallbackPackage;
10894
+ throw e;
10895
+ }
10847
10896
  }
10848
10897
  async loadTutorialMarkdown(repopath, tag) {
10849
10898
  repopath = normalizeTutorialPath(repopath);
@@ -11199,7 +11248,7 @@ var pxt;
11199
11248
  return await github.db.loadConfigAsync(repopath, tag);
11200
11249
  }
11201
11250
  github.pkgConfigAsync = pkgConfigAsync;
11202
- async function downloadPackageAsync(repoWithTag, config) {
11251
+ async function downloadPackageAsync(repoWithTag, config, fallbackPackageFiles) {
11203
11252
  const p = parseRepoId(repoWithTag);
11204
11253
  if (!p) {
11205
11254
  pxt.log('Unknown GitHub syntax');
@@ -11212,9 +11261,17 @@ var pxt;
11212
11261
  }
11213
11262
  // always try to upgrade unbound versions
11214
11263
  if (!p.tag) {
11215
- p.tag = await github.db.latestVersionAsync(p.slug, config);
11264
+ try {
11265
+ p.tag = await github.db.latestVersionAsync(p.slug, config);
11266
+ }
11267
+ catch (e) {
11268
+ const fallbackPackage = cachedPackageFromFallback(fallbackPackageFiles);
11269
+ if (fallbackPackage)
11270
+ return fallbackPackage;
11271
+ throw e;
11272
+ }
11216
11273
  }
11217
- const cached = await github.db.loadPackageAsync(p.fullName, p.tag);
11274
+ const cached = await github.db.loadPackageAsync(p.fullName, p.tag, fallbackPackageFiles);
11218
11275
  const dv = upgradedDisablesVariants(config, repoWithTag);
11219
11276
  if (dv) {
11220
11277
  const cfg = pxt.Package.parseAndValidConfig(cached.files[pxt.CONFIG_NAME]);
@@ -11239,7 +11296,11 @@ var pxt;
11239
11296
  return { version, config };
11240
11297
  }
11241
11298
  github.downloadLatestPackageAsync = downloadLatestPackageAsync;
11242
- async function cacheProjectDependenciesAsync(cfg) {
11299
+ async function cacheProjectDependenciesAsync(cfg, fallbackPackageFilesById) {
11300
+ await cacheProjectDependenciesCoreAsync(cfg, {}, fallbackPackageFilesById);
11301
+ }
11302
+ github.cacheProjectDependenciesAsync = cacheProjectDependenciesAsync;
11303
+ async function cacheProjectDependenciesCoreAsync(cfg, checked, fallbackPackageFilesById) {
11243
11304
  var _a;
11244
11305
  const ghExtensions = (_a = Object.keys(cfg.dependencies)) === null || _a === void 0 ? void 0 : _a.filter(dep => isGithubId(cfg.dependencies[dep]));
11245
11306
  if (ghExtensions.length) {
@@ -11247,14 +11308,19 @@ var pxt;
11247
11308
  // Make sure external packages load before installing header.
11248
11309
  await Promise.all(ghExtensions.map(async (ext) => {
11249
11310
  const extSrc = cfg.dependencies[ext];
11250
- const ghPkg = await downloadPackageAsync(extSrc, pkgConfig);
11311
+ if (checked[extSrc])
11312
+ return;
11313
+ checked[extSrc] = true;
11314
+ const ghPkg = await downloadPackageAsync(extSrc, pkgConfig, fallbackPackageFilesById === null || fallbackPackageFilesById === void 0 ? void 0 : fallbackPackageFilesById[extSrc]);
11251
11315
  if (!ghPkg) {
11252
11316
  throw new Error(lf("Cannot load extension {0} from {1}", ext, extSrc));
11253
11317
  }
11318
+ const ghPkgCfg = pxt.Package.parseAndValidConfig(ghPkg.files[pxt.CONFIG_NAME]);
11319
+ if (ghPkgCfg)
11320
+ await cacheProjectDependenciesCoreAsync(ghPkgCfg, checked, fallbackPackageFilesById);
11254
11321
  }));
11255
11322
  }
11256
11323
  }
11257
- github.cacheProjectDependenciesAsync = cacheProjectDependenciesAsync;
11258
11324
  let GitRepoStatus;
11259
11325
  (function (GitRepoStatus) {
11260
11326
  GitRepoStatus[GitRepoStatus["Unknown"] = 0] = "Unknown";
@@ -17304,7 +17370,10 @@ var pxt;
17304
17370
  this.config.binaryonly ||
17305
17371
  !opts.target.isNative;
17306
17372
  if (!noFileEmbed) {
17307
- const files = await this.filesToBePublishedAsync(true);
17373
+ const files = await this.filesToBePublishedAsync(true, !pxt.appTarget.compile.useUF2);
17374
+ const packagedExtInfo = this.packagedExtensionHexInfo(opts);
17375
+ if (Object.keys(packagedExtInfo).length)
17376
+ files[pxt.PACKAGED_EXT_INFO] = JSON.stringify(packagedExtInfo);
17308
17377
  const headerString = JSON.stringify({
17309
17378
  name: this.config.name,
17310
17379
  comment: this.config.description,
@@ -17376,25 +17445,75 @@ var pxt;
17376
17445
  cfg.files = cfg.files.filter(fn => fn !== pxt.HISTORY_FILE);
17377
17446
  return cfg;
17378
17447
  }
17379
- filesToBePublishedAsync(allowPrivate = false) {
17448
+ async filesToBePublishedAsync(allowPrivate = false, packExternalExtensions = false) {
17380
17449
  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)
17450
+ await this.loadAsync();
17451
+ if (!allowPrivate && !this.config.public)
17452
+ pxt.U.userError('Only packages with "public":true can be published');
17453
+ const cfg = this.prepareConfigToBePublished();
17454
+ files[pxt.CONFIG_NAME] = pxt.Package.stringifyConfig(cfg);
17455
+ for (let f of this.getFiles()) {
17456
+ // already stored
17457
+ if (f === pxt.CONFIG_NAME || f === pxt.HISTORY_FILE)
17458
+ continue;
17459
+ let str = this.readFile(f);
17460
+ if (str == null)
17461
+ pxt.U.userError("referenced file missing: " + f);
17462
+ files[f] = str;
17463
+ }
17464
+ if (packExternalExtensions) {
17465
+ const packagedExtensions = this.packagedExternalExtensions();
17466
+ if (Object.keys(packagedExtensions).length)
17467
+ files[pxt.PACKAGED_EXTENSIONS] = JSON.stringify(packagedExtensions);
17468
+ }
17469
+ return pxt.U.sortObjectFields(files);
17470
+ }
17471
+ packagedExternalExtensions() {
17472
+ const packaged = {};
17473
+ const seen = {};
17474
+ const packDeps = (pkg) => {
17475
+ for (const dep of pkg.resolvedDependencies()) {
17476
+ if (!dep)
17477
+ continue;
17478
+ const seenKey = `${dep.id}:${dep.version()}`;
17479
+ if (seen[seenKey])
17390
17480
  continue;
17391
- let str = this.readFile(f);
17392
- if (str == null)
17393
- pxt.U.userError("referenced file missing: " + f);
17394
- files[f] = str;
17481
+ seen[seenKey] = true;
17482
+ if (dep.verProtocol() === "github" || dep.verProtocol() === "pub") {
17483
+ const depFiles = {};
17484
+ for (const fn of dep.getFiles()) {
17485
+ if (fn === pxt.CONFIG_NAME || fn === pxt.HISTORY_FILE)
17486
+ continue;
17487
+ const content = dep.readFile(fn);
17488
+ if (content != null)
17489
+ depFiles[fn] = content;
17490
+ }
17491
+ depFiles[pxt.CONFIG_NAME] = pxt.Package.stringifyConfig(dep.config);
17492
+ packaged[dep._verspec] = depFiles;
17493
+ if (dep.version() !== dep._verspec)
17494
+ packaged[dep.version()] = depFiles;
17495
+ if (dep.verProtocol() === "pub")
17496
+ packaged[dep.verArgument()] = depFiles;
17497
+ }
17498
+ packDeps(dep);
17395
17499
  }
17396
- return pxt.U.sortObjectFields(files);
17397
- });
17500
+ };
17501
+ packDeps(this);
17502
+ return packaged;
17503
+ }
17504
+ packagedExtensionHexInfo(opts) {
17505
+ var _a;
17506
+ const packaged = {};
17507
+ const targets = [opts, ...(opts.otherMultiVariants || [])];
17508
+ for (const target of targets) {
17509
+ const extInfo = target.extinfo;
17510
+ if (!(extInfo === null || extInfo === void 0 ? void 0 : extInfo.sha) || !((_a = extInfo.hexinfo) === null || _a === void 0 ? void 0 : _a.hex))
17511
+ continue;
17512
+ const serialized = pxt.hexloader.stringifyHexInfoForCache(extInfo.hexinfo);
17513
+ if (serialized)
17514
+ packaged[extInfo.sha] = serialized;
17515
+ }
17516
+ return packaged;
17398
17517
  }
17399
17518
  saveToJsonAsync() {
17400
17519
  return this.filesToBePublishedAsync(true)
@@ -18351,6 +18470,10 @@ var ts;
18351
18470
  fn.attributes.jsDoc = fn.attributes._untranslatedJsDoc;
18352
18471
  if (fn.attributes._untranslatedBlock)
18353
18472
  fn.attributes.jsDoc = fn.attributes._untranslatedBlock;
18473
+ if (fn.attributes._untranslatedParamDefl) {
18474
+ fn.attributes.paramDefl = pxtc.U.clone(fn.attributes._untranslatedParamDefl);
18475
+ syncParameterDefaults(fn);
18476
+ }
18354
18477
  const lookupLoc = (locSuff, attrKey) => {
18355
18478
  var _a, _b;
18356
18479
  return loc[fn.qName + locSuff] || ((_a = fn.attributes.locs) === null || _a === void 0 ? void 0 : _a[attrKey])
@@ -18386,15 +18509,30 @@ var ts;
18386
18509
  }
18387
18510
  const paramsWithLabels = comp.thisParameter ? [comp.thisParameter, ...comp.parameters] : comp.parameters;
18388
18511
  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);
18512
+ if (param.labelLocalizationKey) {
18513
+ const locSuff = param.labelLocalizationKey.slice(fn.qName.length);
18514
+ const paramLabel = lookupLoc(locSuff, langLower + locSuff);
18515
+ if (paramLabel) {
18516
+ setBlockTranslationCacheKey(param.labelLocalizationKey, paramLabel);
18517
+ }
18518
+ else {
18519
+ clearBlockTranslationCacheKey(param.labelLocalizationKey);
18520
+ }
18395
18521
  }
18396
- else {
18397
- clearBlockTranslationCacheKey(param.labelLocalizationKey);
18522
+ const defaultString = pxt.blocks.parameterDefaultToLocalizationString(param.defaultValue, param.type);
18523
+ const defaultLocalizationKey = pxt.blocks.parameterDefaultLocalizationKey(fn.qName, param.actualName);
18524
+ if (defaultLocalizationKey && defaultString !== undefined) {
18525
+ const locSuff = defaultLocalizationKey.slice(fn.qName.length);
18526
+ const paramDefault = lookupLoc(locSuff, langLower + locSuff);
18527
+ if (paramDefault !== undefined) {
18528
+ if (!fn.attributes._untranslatedParamDefl) {
18529
+ fn.attributes._untranslatedParamDefl = pxtc.U.clone(fn.attributes.paramDefl || {});
18530
+ }
18531
+ if (!fn.attributes.paramDefl)
18532
+ fn.attributes.paramDefl = {};
18533
+ fn.attributes.paramDefl[param.actualName] = pxt.blocks.localizationStringToParameterDefault(paramDefault);
18534
+ syncParameterDefaults(fn);
18535
+ }
18398
18536
  }
18399
18537
  }
18400
18538
  }
@@ -18461,6 +18599,13 @@ var ts;
18461
18599
  return cleanLocalizations(apis);
18462
18600
  }
18463
18601
  pxtc.localizeApisAsync = localizeApisAsync;
18602
+ function syncParameterDefaults(fn) {
18603
+ if (!fn.parameters)
18604
+ return;
18605
+ for (const param of fn.parameters) {
18606
+ param.default = fn.attributes.paramDefl && fn.attributes.paramDefl[param.name];
18607
+ }
18608
+ }
18464
18609
  function cleanLocalizations(apis) {
18465
18610
  pxtc.Util.values(apis.byQName)
18466
18611
  .filter(fb => fb.attributes.block && /^{[^:]+:[^}]+}/.test(fb.attributes.block))