@markw65/monkeyc-optimizer 1.0.43 → 1.0.45

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.
@@ -3585,6 +3585,17 @@ function manifestAnnotations(manifest) {
3585
3585
  .children("iq:annotation")
3586
3586
  .text();
3587
3587
  }
3588
+ function manifestLanguages(manifest) {
3589
+ if (manifest.body instanceof Error) {
3590
+ throw manifest.body;
3591
+ }
3592
+ return manifest.body
3593
+ .children()
3594
+ .filter((c) => c.name === "iq:application" || c.name === "iq:barrel")
3595
+ .children("iq:languages")
3596
+ .children("iq:language")
3597
+ .text();
3598
+ }
3588
3599
  async function checkManifest(manifest, products) {
3589
3600
  if (manifest.body instanceof Error) {
3590
3601
  throw manifest.body;
@@ -3973,10 +3984,6 @@ async function resolve_literals(qualifier, default_source, deviceInfo, cache) {
3973
3984
  const lang = qualifier["lang"];
3974
3985
  if (lang) {
3975
3986
  await Promise.all(Object.keys(lang).map((key) => {
3976
- if (!(0,external_api_cjs_namespaceObject.hasProperty)(deviceInfo.languages, key)) {
3977
- delete lang[key];
3978
- return null;
3979
- }
3980
3987
  return resolve_one_file_list(lang, key);
3981
3988
  }));
3982
3989
  if (Object.keys(lang).length === 0)
@@ -4479,6 +4486,7 @@ async function get_jungle_and_barrels(jungleFiles, defaultProducts, options, cac
4479
4486
  jungles,
4480
4487
  resources,
4481
4488
  buildDependencies,
4489
+ devices,
4482
4490
  };
4483
4491
  }
4484
4492
  catch (e) {
@@ -4509,17 +4517,22 @@ const external_child_process_namespaceObject = require("child_process");
4509
4517
 
4510
4518
 
4511
4519
  async function launchSimulator(force = true) {
4512
- if (!force && (await checkIfSimulatorRunning()))
4513
- return;
4514
- const sdk = await (0,external_sdk_util_cjs_namespaceObject.getSdkPath)();
4515
- const child = (0,external_child_process_namespaceObject.execFile)(external_path_.resolve(sdk, "bin", external_sdk_util_cjs_namespaceObject.isWin ? "simulator" : "connectiq"));
4516
- child.unref();
4517
- for (let i = 0;; i++) {
4518
- if (await checkIfSimulatorRunning())
4519
- return;
4520
- if (i === 5)
4520
+ try {
4521
+ if (!force && (await checkIfSimulatorRunning()))
4521
4522
  return;
4522
- await new Promise((r) => setTimeout(r, 200));
4523
+ const sdk = await (0,external_sdk_util_cjs_namespaceObject.getSdkPath)();
4524
+ const child = (0,external_child_process_namespaceObject.execFile)(external_path_.resolve(sdk, "bin", external_sdk_util_cjs_namespaceObject.isWin ? "simulator" : "connectiq"));
4525
+ child.unref();
4526
+ for (let i = 0;; i++) {
4527
+ if (await checkIfSimulatorRunning())
4528
+ return;
4529
+ if (i === 5)
4530
+ return;
4531
+ await new Promise((r) => setTimeout(r, 200));
4532
+ }
4533
+ }
4534
+ catch (e) {
4535
+ console.log(e);
4523
4536
  }
4524
4537
  }
4525
4538
  function checkIfSimulatorRunning() {
@@ -4534,7 +4547,7 @@ function checkIfSimulatorRunningOn(port) {
4534
4547
  socket.on("end", () => resolve(listening));
4535
4548
  socket.connect(port, "localhost");
4536
4549
  socket.end();
4537
- });
4550
+ }).catch(() => false);
4538
4551
  }
4539
4552
  function simulateProgram(prg, device, test = false, logger) {
4540
4553
  const args = [prg, device];
@@ -4789,13 +4802,73 @@ function getNodeValue(node) {
4789
4802
  return [node, "Long"];
4790
4803
  }
4791
4804
  if (type === "string") {
4792
- return [node, "String"];
4805
+ return node.raw.startsWith("'")
4806
+ ? [node, "Char"]
4807
+ : [node, "String"];
4793
4808
  }
4794
4809
  if (type === "boolean") {
4795
4810
  return [node, "Boolean"];
4796
4811
  }
4797
4812
  throw new Error(`Literal has unknown type '${type}'`);
4798
4813
  }
4814
+ function wrap(node, loc) {
4815
+ if (loc) {
4816
+ node.loc = loc;
4817
+ node.start = loc.start.offset;
4818
+ node.end = loc.end.offset;
4819
+ }
4820
+ return node;
4821
+ }
4822
+ function locRange(start, end) {
4823
+ return {
4824
+ source: start.source || end.source,
4825
+ start: start.start,
4826
+ end: end.end,
4827
+ };
4828
+ }
4829
+ function adjustLoc(loc, start = 1, end = -1) {
4830
+ return {
4831
+ source: loc.source,
4832
+ start: {
4833
+ offset: loc.start.offset + start,
4834
+ line: loc.start.line,
4835
+ column: loc.start.column + start,
4836
+ },
4837
+ end: {
4838
+ offset: loc.end.offset + end,
4839
+ line: loc.end.line,
4840
+ column: loc.end.column + end,
4841
+ },
4842
+ };
4843
+ }
4844
+ function makeIdentifier(name, loc) {
4845
+ return wrap({ type: "Identifier", name }, loc);
4846
+ }
4847
+ function makeMemberExpression(object, property) {
4848
+ return wrap({
4849
+ type: "MemberExpression",
4850
+ object,
4851
+ property,
4852
+ computed: false,
4853
+ }, object.loc && locRange(object.loc, property.loc));
4854
+ }
4855
+ function makeScopedName(dotted, l) {
4856
+ const loc = l && adjustLoc(l, 0, l.start.offset - l.end.offset);
4857
+ const result = dotted.split(/\s*\.\s*/).reduce(({ cur, offset }, next) => {
4858
+ const id = makeIdentifier(next, loc && adjustLoc(loc, offset, offset + next.length));
4859
+ if (!cur) {
4860
+ cur = id;
4861
+ }
4862
+ else {
4863
+ cur = makeMemberExpression(cur, id);
4864
+ }
4865
+ offset += next.length + 1;
4866
+ return { cur, offset };
4867
+ }, { cur: null, offset: 0 }).cur;
4868
+ if (!result)
4869
+ throw new Error("Failed to make a ScopedName");
4870
+ return result;
4871
+ }
4799
4872
 
4800
4873
  ;// CONCATENATED MODULE: ./src/function-info.ts
4801
4874
 
@@ -4848,6 +4921,8 @@ function recordCalledFuncs(func, callees) {
4848
4921
  }
4849
4922
  function functionMayModify(state, func, decl) {
4850
4923
  const info = func.info;
4924
+ if (info === false)
4925
+ return false;
4851
4926
  if (!info || info.modifiedUnknown)
4852
4927
  return true;
4853
4928
  if (info.resolvedDecls) {
@@ -4860,7 +4935,7 @@ function functionMayModify(state, func, decl) {
4860
4935
  const visited = new Set();
4861
4936
  const resolved = new Set();
4862
4937
  const resolveDecls = (f) => {
4863
- if (visited.has(f))
4938
+ if (f.info === false || visited.has(f))
4864
4939
  return true;
4865
4940
  if (!f.info)
4866
4941
  return false;
@@ -4922,6 +4997,16 @@ function findCalleesForNew(lookupDefs) {
4922
4997
  .flatMap(initializer)
4923
4998
  .filter((decl) => decl ? decl.type === "FunctionDeclaration" : false));
4924
4999
  }
5000
+ function findCalleesByNode(state, callee) {
5001
+ const name = callee.type === "Identifier"
5002
+ ? callee.name
5003
+ : callee.type === "MemberExpression" && !callee.computed
5004
+ ? callee.property.name
5005
+ : null;
5006
+ if (!name)
5007
+ return null;
5008
+ return ((hasProperty(state.allFunctions, name) && state.allFunctions[name]) || null);
5009
+ }
4925
5010
 
4926
5011
  ;// CONCATENATED MODULE: ./src/optimizer-types.ts
4927
5012
  var StateNodeAttributes;
@@ -5885,13 +5970,17 @@ function pragmaChecker(state, ast, diagnostics) {
5885
5970
  if (quote == '"') {
5886
5971
  return haystack.includes(needle);
5887
5972
  }
5888
- const re = new RegExp(needle.replace(/@([\d\w]+)/g, "(pre_)?$1(_\\d+)?"));
5973
+ const re = new RegExp(needle.replace(/@([-\d.\w]+|"[^"]*")/g, (_match, pat) => `(?:${pat}|pre_${pat.replace(/\W/g, "_")}(?:_\\d+)?)`));
5889
5974
  return re.test(haystack);
5890
5975
  };
5891
5976
  next();
5892
5977
  traverseAst(ast, (node) => {
5893
- if (index >= comments.length)
5978
+ if (index >= comments.length ||
5979
+ node.type === "Line" ||
5980
+ node.type === "Block" ||
5981
+ node.type === "MultiLine") {
5894
5982
  return false;
5983
+ }
5895
5984
  if (node.start && node.start >= (comment.end || Infinity)) {
5896
5985
  const { kind, quote, needle } = matchers.shift();
5897
5986
  if (kind === "match") {
@@ -6037,7 +6126,7 @@ function buildReducedGraph(state, func, notice) {
6037
6126
  try {
6038
6127
  const localState = new LocalState(func.node);
6039
6128
  const ret = localState.curBlock;
6040
- state.stack = func.stack;
6129
+ state.stack = [...func.stack];
6041
6130
  const stmtStack = [func.node];
6042
6131
  let tryActive = 0;
6043
6132
  state.pre = (node) => {
@@ -6052,6 +6141,8 @@ function buildReducedGraph(state, func, notice) {
6052
6141
  stmtStack.push(node);
6053
6142
  }
6054
6143
  switch (node.type) {
6144
+ case "FunctionDeclaration":
6145
+ return ["body"];
6055
6146
  case "AttributeList":
6056
6147
  return [];
6057
6148
  case "SwitchStatement": {
@@ -6268,11 +6359,6 @@ function buildReducedGraph(state, func, notice) {
6268
6359
  }
6269
6360
  case "VariableDeclarator":
6270
6361
  return ["init"];
6271
- case "MemberExpression":
6272
- if (!node.computed) {
6273
- return ["object"];
6274
- }
6275
- break;
6276
6362
  case "UnaryExpression":
6277
6363
  if (node.operator === ":") {
6278
6364
  return [];
@@ -6308,6 +6394,14 @@ function buildReducedGraph(state, func, notice) {
6308
6394
  case "ContinueStatement":
6309
6395
  localState.terminal(node.type);
6310
6396
  return [];
6397
+ case "CallExpression":
6398
+ if (node.callee.type === "Identifier") {
6399
+ const extra = state.stack.splice(func.stack.length);
6400
+ state.traverse(node.callee);
6401
+ state.stack.push(...extra);
6402
+ return ["arguments"];
6403
+ }
6404
+ break;
6311
6405
  }
6312
6406
  return null;
6313
6407
  };
@@ -6469,142 +6563,94 @@ function getPreOrder(head) {
6469
6563
 
6470
6564
  // EXTERNAL MODULE: ./node_modules/priorityqueuejs/index.js
6471
6565
  var priorityqueuejs = __webpack_require__(2789);
6472
- ;// CONCATENATED MODULE: ./src/pre.ts
6566
+ ;// CONCATENATED MODULE: ./src/data-flow.ts
6567
+
6473
6568
 
6474
6569
 
6475
6570
 
6476
6571
 
6477
6572
 
6478
- /**
6479
- * This implements a pseudo Partial Redundancy Elimination
6480
- * pass. It isn't quite like traditional PRE because we're
6481
- * aiming to minimize size, not dynamic instructions. So
6482
- * for us, its worthwhile to take something like:
6483
- *
6484
- * switch (x) {
6485
- * case 1: foo(A.B); break;
6486
- * case 2: foo(C); break;
6487
- * case 3: bar(A.B); break;
6488
- * }
6489
- *
6490
- * and rewrite it as
6491
- *
6492
- * var tmp = A.B;
6493
- * switch (x) {
6494
- * case 1: foo(tmp); break;
6495
- * case 2: foo(C); break;
6496
- * case 3: bar(tmp); break;
6497
- * }
6498
- *
6499
- * because even though A.B wasn't used on all paths where we
6500
- * inserted the temporary, we still reduced the code size.
6501
- */
6502
- const logging = false;
6503
6573
  function declFullName(decl) {
6574
+ if (Array.isArray(decl)) {
6575
+ decl = decl[0];
6576
+ }
6577
+ if (decl.type === "Literal") {
6578
+ return decl.raw || decl.value?.toString() || "null";
6579
+ }
6580
+ if ((0,external_api_cjs_namespaceObject.isStateNode)(decl))
6581
+ return decl.fullName;
6504
6582
  switch (decl.type) {
6505
- case "Literal":
6506
- return decl.raw || decl.value?.toString() || "null";
6507
- case "VariableDeclarator":
6508
- return decl.fullName;
6583
+ case "BinaryExpression":
6584
+ return decl.left.name;
6585
+ case "EnumStringMember":
6586
+ return decl.init
6587
+ ? `${decl.id.name}:${(0,external_api_cjs_namespaceObject.formatAst)(decl.init)}`
6588
+ : decl.id.name;
6509
6589
  default:
6510
6590
  throw new Error(`Unexpected EventDecl type: ${decl.type}`);
6511
6591
  }
6512
6592
  }
6513
6593
  function declName(decl) {
6594
+ if (Array.isArray(decl)) {
6595
+ decl = decl[0];
6596
+ }
6597
+ if (decl.type === "Literal") {
6598
+ return (decl.raw || decl.value?.toString() || "null").replace(/[^\w]/g, "_");
6599
+ }
6600
+ if ((0,external_api_cjs_namespaceObject.isStateNode)(decl))
6601
+ return decl.name;
6514
6602
  switch (decl.type) {
6515
- case "Literal":
6516
- return (decl.raw || decl.value?.toString() || "null").replace(/[^\w]/g, "_");
6517
- case "VariableDeclarator":
6518
- return decl.name;
6603
+ case "BinaryExpression":
6604
+ return decl.left.name;
6605
+ case "EnumStringMember":
6606
+ return decl.id.name;
6519
6607
  default:
6520
6608
  throw new Error(`Unexpected EventDecl type: ${decl.type}`);
6521
6609
  }
6522
6610
  }
6523
- function logAntState(s, decl) {
6524
- const defs = Array.from(s.ant).reduce((defs, event) => {
6525
- if (event.type === "def" || event.type === "mod")
6526
- defs++;
6527
- return defs;
6528
- }, 0);
6529
- console.log(` - ${declFullName(decl)}: ${candidateCost(s)} bytes, ${s.ant.size - defs} refs, ${defs} defs, ${s.live ? "" : "!"}live, ${s.isIsolated ? "" : "!"}isolated`);
6530
- console.log(` - members: ${Array.from(s.members)
6531
- .map(([block, live]) => block.order + (live ? "t" : "f"))
6532
- .join(", ")}`);
6533
- }
6534
- function logAntDecls(antDecls) {
6535
- antDecls.forEach(logAntState);
6536
- }
6537
- function sizeBasedPRE(state, func) {
6538
- if (!func.node.body)
6539
- return;
6540
- if (!state.config ||
6541
- !state.config.sizeBasedPRE ||
6542
- (typeof state.config.sizeBasedPRE === "string" &&
6543
- state.config.sizeBasedPRE !== func.fullName)) {
6544
- return;
6545
- }
6546
- const { graph: head, identifiers } = buildPREGraph(state, func);
6547
- const candidates = computeAttributes(state, head);
6548
- if (candidates) {
6549
- if (logging) {
6550
- console.log(`Found ${candidates.size} candidates in ${func.fullName}`);
6551
- logAntDecls(candidates);
6552
- }
6553
- const nodeMap = new Map();
6554
- const declMap = new Map();
6555
- const variableDecl = withLoc({
6556
- type: "VariableDeclaration",
6557
- declarations: [],
6558
- kind: "var",
6559
- }, func.node.body);
6560
- variableDecl.end = variableDecl.start;
6561
- variableDecl.loc.end = variableDecl.loc.start;
6562
- candidates.forEach((s, decl) => {
6563
- let name;
6564
- let i = 0;
6565
- do {
6566
- name = `pre_${declName(decl)}${i ? "_" + i : ""}`;
6567
- if (!identifiers.has(name)) {
6568
- identifiers.add(name);
6569
- break;
6570
- }
6571
- i++;
6572
- } while (true);
6573
- declMap.set(decl, name);
6574
- variableDecl.declarations.push(withLoc({
6575
- type: "VariableDeclarator",
6576
- id: withLoc({ type: "Identifier", name }, variableDecl),
6577
- kind: "var",
6578
- }, variableDecl));
6579
- s.ant.forEach((event) => {
6580
- const events = nodeMap.get(event.node);
6581
- if (!events) {
6582
- nodeMap.set(event.node, [event]);
6583
- }
6584
- else {
6585
- events.push(event);
6586
- }
6587
- });
6588
- });
6589
- applyReplacements(func.node, nodeMap, declMap);
6590
- func.node.body.body.unshift(variableDecl);
6591
- }
6592
- }
6593
6611
  function unhandledExpression(node) {
6594
6612
  throw new Error(`Unhandled expression type: ${node.type}`);
6595
6613
  }
6596
- function buildPREGraph(state, func) {
6614
+ function buildDataFlowGraph(state, func, wantsLiteral, trackInsertionPoints, wantsAllRefs) {
6615
+ const uniqueDeclMap = new Map();
6597
6616
  const findDecl = (node) => {
6598
6617
  if (node.type === "Identifier" ||
6599
6618
  (node.type === "MemberExpression" && !node.computed)) {
6600
6619
  const [, results] = state.lookup(node);
6601
- if (results &&
6602
- results.length === 1 &&
6603
- results[0].parent?.type != "BlockStatement" &&
6604
- results[0].results.length === 1 &&
6605
- results[0].results[0].type === "VariableDeclarator") {
6606
- return results[0].results[0];
6607
- }
6620
+ const decls = (results &&
6621
+ results.reduce((decls, result) => result.results.reduce((decls, result) => {
6622
+ if (!wantsAllRefs &&
6623
+ (result.type !== "VariableDeclarator" || (0,external_api_cjs_namespaceObject.isLocal)(result))) {
6624
+ return decls;
6625
+ }
6626
+ if (!decls)
6627
+ return result;
6628
+ if (Array.isArray(decls)) {
6629
+ decls.push(result);
6630
+ return decls;
6631
+ }
6632
+ else {
6633
+ return [decls, result];
6634
+ }
6635
+ }, decls), null)) ||
6636
+ null;
6637
+ if (!Array.isArray(decls))
6638
+ return decls;
6639
+ // We use EventDecl as a Map key, so we need to
6640
+ // uniquify it. Note that from any given function,
6641
+ // if state.lookup finds a set of non locals, it will
6642
+ // always find the same set, so we can use the first
6643
+ // such as the unique identifier.
6644
+ const canon = uniqueDeclMap.get(decls[0]);
6645
+ if (!canon) {
6646
+ uniqueDeclMap.set(decls[0], decls);
6647
+ return decls;
6648
+ }
6649
+ if (canon.length != decls.length ||
6650
+ !canon.every((v, i) => v === decls[i])) {
6651
+ throw new Error(`Canonical representation of ${declFullName(canon)} did not match`);
6652
+ }
6653
+ return canon;
6608
6654
  }
6609
6655
  return null;
6610
6656
  };
@@ -6612,18 +6658,22 @@ function buildPREGraph(state, func) {
6612
6658
  const identifiers = new Set();
6613
6659
  const liveDefs = new Map();
6614
6660
  const liveStmts = new Map();
6615
- const liveDef = (def, stmt) => {
6616
- let curNodes = liveDefs.get(def);
6617
- if (!curNodes) {
6618
- liveDefs.set(def, (curNodes = new Set()));
6619
- }
6620
- curNodes.add(stmt);
6621
- let defs = liveStmts.get(stmt);
6622
- if (!defs) {
6623
- liveStmts.set(stmt, (defs = new Map()));
6661
+ const liveDef = trackInsertionPoints
6662
+ ? (def, stmt) => {
6663
+ let curNodes = liveDefs.get(def);
6664
+ if (!curNodes) {
6665
+ liveDefs.set(def, (curNodes = new Set()));
6666
+ }
6667
+ curNodes.add(stmt);
6668
+ let defs = liveStmts.get(stmt);
6669
+ if (!defs) {
6670
+ liveStmts.set(stmt, (defs = new Map()));
6671
+ }
6672
+ defs.set(def, (defs.get(def) || 0) + 1);
6624
6673
  }
6625
- defs.set(def, (defs.get(def) || 0) + 1);
6626
- };
6674
+ : () => {
6675
+ /* do nothing */
6676
+ };
6627
6677
  return {
6628
6678
  identifiers,
6629
6679
  graph: buildReducedGraph(state, func, (node, stmt, mayThrow) => {
@@ -6658,7 +6708,7 @@ function buildPREGraph(state, func) {
6658
6708
  case "ParenthesizedExpression":
6659
6709
  break;
6660
6710
  case "Literal":
6661
- if (refCost(node) > LocalRefCost) {
6711
+ if (wantsLiteral(node)) {
6662
6712
  const result = getNodeValue(node);
6663
6713
  const key = result[1] +
6664
6714
  (result[0].value === null
@@ -6680,34 +6730,40 @@ function buildPREGraph(state, func) {
6680
6730
  case "Identifier":
6681
6731
  identifiers.add(node.name);
6682
6732
  // fall through
6683
- case "MemberExpression":
6684
- {
6685
- const decl = findDecl(node);
6686
- if (decl && decl.type === "VariableDeclarator") {
6687
- const defStmts = (decl.node.kind === "var" && liveDefs.get(null)) ||
6688
- liveDefs.get(decl);
6689
- if (defStmts) {
6690
- break;
6691
- /*
6692
- // hold off on this for now. we need to communicate
6693
- // which defs need to be fixed, which involves yet-another
6694
- // table.
6695
-
6696
- if (defStmts.size !== 1) break;
6697
- const fixable = isFixableStmt([...defStmts][0]);
6698
- if (fixable === false) break;
6699
- cost += fixable;
6700
- */
6733
+ case "MemberExpression": {
6734
+ const decls = findDecl(node);
6735
+ if (!decls)
6736
+ break;
6737
+ if (trackInsertionPoints &&
6738
+ (0,external_util_cjs_namespaceObject.some)(decls, (decl) => {
6739
+ if (decl.type === "VariableDeclarator") {
6740
+ const defStmts = (decl.node.kind === "var" && liveDefs.get(null)) ||
6741
+ liveDefs.get(decl);
6742
+ if (defStmts) {
6743
+ return true;
6744
+ /*
6745
+ // hold off on this for now. we need to communicate
6746
+ // which defs need to be fixed, which involves yet-another
6747
+ // table.
6748
+
6749
+ if (defStmts.size !== 1) break;
6750
+ const fixable = isFixableStmt([...defStmts][0]);
6751
+ if (fixable === false) break;
6752
+ cost += fixable;
6753
+ */
6754
+ }
6701
6755
  }
6702
- return {
6703
- type: "ref",
6704
- node,
6705
- decl,
6706
- mayThrow,
6707
- };
6708
- }
6756
+ return false;
6757
+ })) {
6758
+ break;
6709
6759
  }
6710
- break;
6760
+ return {
6761
+ type: "ref",
6762
+ node,
6763
+ decl: decls,
6764
+ mayThrow,
6765
+ };
6766
+ }
6711
6767
  case "VariableDeclarator": {
6712
6768
  const decl = findDecl(node.id.type === "BinaryExpression" ? node.id.left : node.id);
6713
6769
  if (decl) {
@@ -6755,8 +6811,10 @@ function buildPREGraph(state, func) {
6755
6811
  }
6756
6812
  case "CallExpression": {
6757
6813
  liveDef(null, stmt);
6758
- const [, results] = state.lookup(node.callee);
6759
- const callees = results ? findCallees(results) : null;
6814
+ const [, results] = state.lookupNonlocal(node.callee);
6815
+ const callees = results
6816
+ ? findCallees(results)
6817
+ : findCalleesByNode(state, node.callee);
6760
6818
  return { type: "mod", node, mayThrow, callees };
6761
6819
  }
6762
6820
  default:
@@ -6771,6 +6829,132 @@ function buildPREGraph(state, func) {
6771
6829
  }),
6772
6830
  };
6773
6831
  }
6832
+ class DataflowQueue {
6833
+ constructor() {
6834
+ this.enqueued = new Set();
6835
+ this.queue = new priorityqueuejs((b, a) => (a.order || 0) - (b.order || 0));
6836
+ }
6837
+ enqueue(block) {
6838
+ if (!this.enqueued.has(block)) {
6839
+ this.enqueued.add(block);
6840
+ this.queue.enq(block);
6841
+ }
6842
+ }
6843
+ dequeue() {
6844
+ const block = this.queue.deq();
6845
+ this.enqueued.delete(block);
6846
+ return block;
6847
+ }
6848
+ empty() {
6849
+ return this.queue.isEmpty();
6850
+ }
6851
+ }
6852
+
6853
+ ;// CONCATENATED MODULE: ./src/pre.ts
6854
+
6855
+
6856
+
6857
+
6858
+
6859
+
6860
+ /**
6861
+ * This implements a pseudo Partial Redundancy Elimination
6862
+ * pass. It isn't quite like traditional PRE because we're
6863
+ * aiming to minimize size, not dynamic instructions. So
6864
+ * for us, its worthwhile to take something like:
6865
+ *
6866
+ * switch (x) {
6867
+ * case 1: foo(A.B); break;
6868
+ * case 2: foo(C); break;
6869
+ * case 3: bar(A.B); break;
6870
+ * }
6871
+ *
6872
+ * and rewrite it as
6873
+ *
6874
+ * var tmp = A.B;
6875
+ * switch (x) {
6876
+ * case 1: foo(tmp); break;
6877
+ * case 2: foo(C); break;
6878
+ * case 3: bar(tmp); break;
6879
+ * }
6880
+ *
6881
+ * because even though A.B wasn't used on all paths where we
6882
+ * inserted the temporary, we still reduced the code size.
6883
+ */
6884
+ const logging = false;
6885
+ function logAntState(s, decl) {
6886
+ const defs = Array.from(s.ant).reduce((defs, event) => {
6887
+ if (event.type === "def" || event.type === "mod")
6888
+ defs++;
6889
+ return defs;
6890
+ }, 0);
6891
+ console.log(` - ${declFullName(decl)}: ${candidateCost(s)} bytes, ${s.ant.size - defs} refs, ${defs} defs, ${s.live ? "" : "!"}live, ${s.isIsolated ? "" : "!"}isolated`);
6892
+ console.log(` - members: ${Array.from(s.members)
6893
+ .map(([block, live]) => block.order + (live ? "t" : "f"))
6894
+ .join(", ")}`);
6895
+ }
6896
+ function logAntDecls(antDecls) {
6897
+ antDecls.forEach(logAntState);
6898
+ }
6899
+ function sizeBasedPRE(state, func) {
6900
+ if (!func.node.body)
6901
+ return;
6902
+ if (!state.config ||
6903
+ !state.config.sizeBasedPRE ||
6904
+ (typeof state.config.sizeBasedPRE === "string" &&
6905
+ state.config.sizeBasedPRE !== func.fullName)) {
6906
+ return;
6907
+ }
6908
+ const { graph: head, identifiers } = buildPREGraph(state, func);
6909
+ const candidates = computeAttributes(state, head);
6910
+ if (candidates) {
6911
+ if (logging) {
6912
+ console.log(`Found ${candidates.size} candidates in ${func.fullName}`);
6913
+ logAntDecls(candidates);
6914
+ }
6915
+ const nodeMap = new Map();
6916
+ const declMap = new Map();
6917
+ const variableDecl = withLoc({
6918
+ type: "VariableDeclaration",
6919
+ declarations: [],
6920
+ kind: "var",
6921
+ }, func.node.body);
6922
+ variableDecl.end = variableDecl.start;
6923
+ variableDecl.loc.end = variableDecl.loc.start;
6924
+ candidates.forEach((s, decl) => {
6925
+ let name;
6926
+ let i = 0;
6927
+ do {
6928
+ name = `pre_${declName(decl)}${i ? "_" + i : ""}`;
6929
+ if (!identifiers.has(name)) {
6930
+ identifiers.add(name);
6931
+ break;
6932
+ }
6933
+ i++;
6934
+ } while (true);
6935
+ declMap.set(decl, name);
6936
+ variableDecl.declarations.push(withLoc({
6937
+ type: "VariableDeclarator",
6938
+ id: withLoc({ type: "Identifier", name }, variableDecl),
6939
+ kind: "var",
6940
+ }, variableDecl));
6941
+ s.ant.forEach((event) => {
6942
+ const events = nodeMap.get(event.node);
6943
+ if (!events) {
6944
+ nodeMap.set(event.node, [event]);
6945
+ }
6946
+ else {
6947
+ events.push(event);
6948
+ }
6949
+ });
6950
+ });
6951
+ applyReplacements(func.node, nodeMap, declMap);
6952
+ func.node.body.body.unshift(variableDecl);
6953
+ }
6954
+ }
6955
+ function buildPREGraph(state, func) {
6956
+ return buildDataFlowGraph(state, func, (literal) => refCost(literal) > LocalRefCost, true, false);
6957
+ }
6774
6958
  function anticipatedDecls() {
6775
6959
  return new Map();
6776
6960
  }
@@ -6926,26 +7110,18 @@ function computeAttributes(state, head) {
6926
7110
  .join(", ")}`);
6927
7111
  if (block.events) {
6928
7112
  block.events.forEach((event) => event.type !== "exn" &&
6929
- console.log(` ${event.type}: ${event.decl ? declFullName(event.decl) : "??"}`));
7113
+ console.log(` ${event.type}: ${event.decl
7114
+ ? declFullName(event.decl)
7115
+ : event.node
7116
+ ? (0,external_api_cjs_namespaceObject.formatAst)(event.node)
7117
+ : "??"}`));
6930
7118
  }
6931
7119
  console.log(`Succs: ${(block.succs || [])
6932
7120
  .map((block) => block.order)
6933
7121
  .join(", ")} ExSucc: ${block.exsucc ? block.exsucc.order : ""}`);
6934
7122
  });
6935
7123
  }
6936
- const enqueued = new Set();
6937
- const queue = new priorityqueuejs((b, a) => (a.order || 0) - (b.order || 0));
6938
- const enqueue = (block) => {
6939
- if (!enqueued.has(block)) {
6940
- enqueued.add(block);
6941
- queue.enq(block);
6942
- }
6943
- };
6944
- const dequeue = () => {
6945
- const block = queue.deq();
6946
- enqueued.delete(block);
6947
- return block;
6948
- };
7124
+ const queue = new DataflowQueue();
6949
7125
  const blockStates = [];
6950
7126
  /*
6951
7127
  Algorithm
@@ -6979,9 +7155,9 @@ function computeAttributes(state, head) {
6979
7155
  }
6980
7156
  return result;
6981
7157
  };
6982
- order.forEach((block) => enqueue(block));
6983
- while (queue.size()) {
6984
- const top = dequeue();
7158
+ order.forEach((block) => queue.enqueue(block));
7159
+ while (!queue.empty()) {
7160
+ const top = queue.dequeue();
6985
7161
  if (top.order === undefined) {
6986
7162
  throw new Error(`Unreachable block was visited!`);
6987
7163
  }
@@ -7020,13 +7196,13 @@ function computeAttributes(state, head) {
7020
7196
  break;
7021
7197
  }
7022
7198
  case "mod": {
7023
- curState.forEach((candidates, decl) => {
7024
- if (decl.type === "VariableDeclarator" &&
7199
+ curState.forEach((candidates, decls) => {
7200
+ if ((0,external_util_cjs_namespaceObject.some)(decls, (decl) => decl.type === "VariableDeclarator" &&
7025
7201
  decl.node.kind === "var" &&
7026
7202
  candidates.live &&
7027
7203
  (!event.callees ||
7028
- event.callees.some((callee) => functionMayModify(state, callee, decl)))) {
7029
- candidates.ant.add(getMod(event, decl, candidates.node));
7204
+ event.callees.some((callee) => functionMayModify(state, callee, decl))))) {
7205
+ candidates.ant.add(getMod(event, decls, candidates.node));
7030
7206
  candidates.live = false;
7031
7207
  }
7032
7208
  });
@@ -7078,7 +7254,7 @@ function computeAttributes(state, head) {
7078
7254
  logAntDecls(curState);
7079
7255
  }
7080
7256
  if (top.preds) {
7081
- top.preds.forEach((pred) => enqueue(pred));
7257
+ top.preds.forEach((pred) => queue.enqueue(pred));
7082
7258
  }
7083
7259
  }
7084
7260
  const candidateDecls = anticipatedDecls();
@@ -7832,7 +8008,7 @@ function getLiteralNode(node) {
7832
8008
  case "-": {
7833
8009
  const [arg, type] = getNodeValue(node.argument);
7834
8010
  if (type === "Number" || type === "Long") {
7835
- return replacementLiteral(arg, -arg.value, type);
8011
+ return replacementLiteral(node, -arg.value, type);
7836
8012
  }
7837
8013
  }
7838
8014
  }
@@ -7882,8 +8058,14 @@ function isBooleanExpression(state, node) {
7882
8058
  }
7883
8059
  return false;
7884
8060
  }
8061
+ function roundToFloat(value) {
8062
+ return new Float32Array([value])[0];
8063
+ }
7885
8064
  function replacementLiteral(arg, value, type) {
7886
- if (typeof value === "boolean") {
8065
+ if (value === null) {
8066
+ type = "Null";
8067
+ }
8068
+ else if (typeof value === "boolean") {
7887
8069
  type = "Boolean";
7888
8070
  }
7889
8071
  else if (type === "Number") {
@@ -7892,32 +8074,213 @@ function replacementLiteral(arg, value, type) {
7892
8074
  else if (type === "Long") {
7893
8075
  value = BigInt.asIntN(64, BigInt(value));
7894
8076
  }
8077
+ else if (type === "Float") {
8078
+ value = roundToFloat(Number(value));
8079
+ }
8080
+ let raw = type === "String"
8081
+ ? JSON.stringify(value)
8082
+ : type === "Char"
8083
+ ? value === "'"
8084
+ ? "'\\''"
8085
+ : "'" + JSON.stringify(value).slice(1, -1) + "'"
8086
+ : value == null
8087
+ ? "null"
8088
+ : value.toString();
8089
+ if (type === "Long") {
8090
+ raw += "l";
8091
+ }
8092
+ else if (type === "Double") {
8093
+ raw += "d";
8094
+ }
8095
+ else if (type === "Float") {
8096
+ if (prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.test(raw)) {
8097
+ raw += "f";
8098
+ }
8099
+ else {
8100
+ const match = raw.match(/^(-)?(\d*)\.(\d+)(e\d+)?/);
8101
+ if (match && match[2].length + match[3].length > 9) {
8102
+ for (let l = 9 - match[2].length; l > 0; l--) {
8103
+ const s = `${match[1] || ""}${match[2]}.${match[3].substring(0, l)}${match[4] || ""}`;
8104
+ if (value !== roundToFloat(parseFloat(s)))
8105
+ break;
8106
+ raw = s;
8107
+ }
8108
+ }
8109
+ }
8110
+ }
8111
+ const { start, end, loc } = arg;
7895
8112
  return {
7896
- ...arg,
8113
+ type: "Literal",
7897
8114
  value,
7898
- raw: value.toString() + (type === "Long" ? "l" : ""),
8115
+ raw,
8116
+ start,
8117
+ end,
8118
+ loc,
7899
8119
  };
7900
8120
  }
8121
+ function classify(arg) {
8122
+ switch (arg) {
8123
+ case "Number":
8124
+ return { big: false, int: true };
8125
+ case "Long":
8126
+ return { big: true, int: true };
8127
+ case "Float":
8128
+ return { big: false, int: false };
8129
+ case "Double":
8130
+ return { big: true, int: false };
8131
+ }
8132
+ return null;
8133
+ }
8134
+ function common_arith_types(left, right) {
8135
+ const l = classify(left);
8136
+ if (!l)
8137
+ return null;
8138
+ const r = classify(right);
8139
+ if (!r)
8140
+ return null;
8141
+ if (l.big || r.big) {
8142
+ return l.int && r.int
8143
+ ? ["Long", (v) => BigInt.asIntN(64, BigInt(v))]
8144
+ : ["Double", (v) => Number(v)];
8145
+ }
8146
+ else {
8147
+ return l.int && r.int
8148
+ ? ["Number", (v) => BigInt.asIntN(32, BigInt(v))]
8149
+ : ["Float", (v) => roundToFloat(Number(v))];
8150
+ }
8151
+ }
8152
+ function common_bitwise_types(left, right) {
8153
+ if (left === "Boolean" && right === "Boolean") {
8154
+ return ["Boolean", (v) => (v ? true : false)];
8155
+ }
8156
+ const l = classify(left);
8157
+ if (!l)
8158
+ return null;
8159
+ const r = classify(right);
8160
+ if (!r)
8161
+ return null;
8162
+ if (!l.int || !r.int)
8163
+ return null;
8164
+ return l.big || r.big
8165
+ ? ["Long", (v) => BigInt.asIntN(64, BigInt(v))]
8166
+ : ["Number", (v) => Number(BigInt.asIntN(32, BigInt(v)))];
8167
+ }
8168
+ function plus_types(left, right) {
8169
+ if (left === "String" || right === "String") {
8170
+ // Boolean + String is an error, and
8171
+ // Float/Double + String is legal, but its hard to predict
8172
+ // the way the float will be formatted (and it won't match
8173
+ // what javascript would do by default)
8174
+ if (/Float|Double|Boolean/.test(left + right)) {
8175
+ return null;
8176
+ }
8177
+ return ["String", String];
8178
+ }
8179
+ if (left === "Char" || right === "Char") {
8180
+ if (left === right) {
8181
+ // adding two chars produces a string
8182
+ return ["String", String];
8183
+ }
8184
+ if (/Number|Long/.test(left + right)) {
8185
+ return ["Char", (v) => v];
8186
+ }
8187
+ }
8188
+ return common_arith_types(left, right);
8189
+ }
8190
+ function shift_mod_types(left, right) {
8191
+ const result = common_bitwise_types(left, right);
8192
+ if (result && result[0] === "Boolean") {
8193
+ return null;
8194
+ }
8195
+ return result;
8196
+ }
8197
+ function equalsFn(left, right) {
8198
+ const lt = typeof left;
8199
+ const rt = typeof right;
8200
+ return lt === "string" || rt === "string"
8201
+ ? // two string literals will compare unequal, becuase string
8202
+ // equality is object equality.
8203
+ false
8204
+ : (lt === "number" || lt === "bigint") &&
8205
+ (rt === "number" || rt === "bigint")
8206
+ ? // numeric types are compared for value equality
8207
+ left == right
8208
+ : // otherwise types and values must match
8209
+ left === right;
8210
+ }
7901
8211
  const operators = {
7902
- "+": (left, right) => left + right,
7903
- "-": (left, right) => left - right,
7904
- "*": (left, right) => left * right,
7905
- "/": (left, right) => left / right,
7906
- "%": (left, right) => left % right,
7907
- "&": (left, right) => left & right,
7908
- "|": (left, right) => left | right,
7909
- "^": (left, right) => left ^ right,
7910
- "<<": (left, right) => left << (right & 127n),
7911
- ">>": (left, right) => left >> (right & 127n),
7912
- "==": (left, right) =>
7913
- // two string literals will compare unequal, becuase string
7914
- // equality is object equality.
7915
- typeof left === "string" ? false : left === right,
7916
- "!=": (left, right) => typeof left === "string" ? true : left !== right,
7917
- "<=": (left, right) => left <= right,
7918
- ">=": (left, right) => left >= right,
7919
- "<": (left, right) => left < right,
7920
- ">": (left, right) => left > right,
8212
+ "+": {
8213
+ typeFn: plus_types,
8214
+ valueFn: (left, right) => typeof left === "string" && typeof right !== "string"
8215
+ ? String.fromCharCode(left.charCodeAt(0) + Number(right))
8216
+ : typeof left !== "string" && typeof right === "string"
8217
+ ? String.fromCharCode(right.charCodeAt(0) + Number(left))
8218
+ : left + right,
8219
+ },
8220
+ "-": {
8221
+ typeFn: common_arith_types,
8222
+ valueFn: (left, right) => left - right,
8223
+ },
8224
+ "*": {
8225
+ typeFn: common_arith_types,
8226
+ valueFn: (left, right) => left * right,
8227
+ },
8228
+ "/": {
8229
+ typeFn: common_arith_types,
8230
+ valueFn: (left, right) => left / right,
8231
+ },
8232
+ "%": {
8233
+ typeFn: shift_mod_types,
8234
+ valueFn: (left, right) => left % right,
8235
+ },
8236
+ "&": {
8237
+ typeFn: common_bitwise_types,
8238
+ valueFn: (left, right) => left & right,
8239
+ },
8240
+ "|": {
8241
+ typeFn: common_bitwise_types,
8242
+ valueFn: (left, right) => left | right,
8243
+ },
8244
+ "^": {
8245
+ typeFn: common_bitwise_types,
8246
+ valueFn: (left, right) => left ^ right,
8247
+ },
8248
+ "<<": {
8249
+ typeFn: shift_mod_types,
8250
+ valueFn: (left, right) => typeof right === "bigint"
8251
+ ? left << right
8252
+ : left << right,
8253
+ },
8254
+ ">>": {
8255
+ typeFn: shift_mod_types,
8256
+ valueFn: (left, right) => typeof right === "bigint"
8257
+ ? left >> right
8258
+ : left >> right,
8259
+ },
8260
+ "==": {
8261
+ typeFn: () => ["Boolean", (v) => v],
8262
+ valueFn: equalsFn,
8263
+ },
8264
+ "!=": {
8265
+ typeFn: () => ["Boolean", (v) => v],
8266
+ valueFn: (left, right) => !equalsFn(left, right),
8267
+ },
8268
+ "<=": {
8269
+ typeFn: common_arith_types,
8270
+ valueFn: (left, right) => left <= right,
8271
+ },
8272
+ ">=": {
8273
+ typeFn: common_arith_types,
8274
+ valueFn: (left, right) => left >= right,
8275
+ },
8276
+ "<": {
8277
+ typeFn: common_arith_types,
8278
+ valueFn: (left, right) => left < right,
8279
+ },
8280
+ ">": {
8281
+ typeFn: common_arith_types,
8282
+ valueFn: (left, right) => left > right,
8283
+ },
7921
8284
  as: null,
7922
8285
  instanceof: null,
7923
8286
  has: null,
@@ -7930,23 +8293,31 @@ function optimizeNode(state, node) {
7930
8293
  break;
7931
8294
  switch (node.operator) {
7932
8295
  case "+":
7933
- if (type === "Number" || type === "Long") {
8296
+ if (type === "Number" ||
8297
+ type === "Long" ||
8298
+ type === "Float" ||
8299
+ type === "Double" ||
8300
+ type === "Char" ||
8301
+ type === "String") {
7934
8302
  return arg;
7935
8303
  }
7936
8304
  break;
7937
8305
  case "-":
7938
- if (type === "Number" || type === "Long") {
7939
- return replacementLiteral(arg, -arg.value, type);
8306
+ if (type === "Number" ||
8307
+ type === "Long" ||
8308
+ type === "Float" ||
8309
+ type === "Double") {
8310
+ return replacementLiteral(node, -arg.value, type);
7940
8311
  }
7941
8312
  break;
7942
8313
  case "!":
7943
8314
  case "~":
7944
8315
  {
7945
8316
  if (type === "Number" || type === "Long") {
7946
- return replacementLiteral(arg, ~BigInt(arg.value), type);
8317
+ return replacementLiteral(node, ~BigInt(arg.value), type);
7947
8318
  }
7948
8319
  if (type === "Boolean" && node.operator == "!") {
7949
- return replacementLiteral(arg, !arg.value, type);
8320
+ return replacementLiteral(node, !arg.value, type);
7950
8321
  }
7951
8322
  }
7952
8323
  break;
@@ -7960,23 +8331,13 @@ function optimizeNode(state, node) {
7960
8331
  const [right, right_type] = getNodeValue(node.right);
7961
8332
  if (!left || !right)
7962
8333
  break;
7963
- let value = null;
7964
- let type;
7965
- if ((left_type != "Number" && left_type != "Long") ||
7966
- left_type != right_type) {
7967
- if (node.operator !== "==" && node.operator !== "!=") {
7968
- break;
7969
- }
7970
- value = operators[node.operator](left.value, right.value);
7971
- type = "Boolean";
7972
- }
7973
- else {
7974
- type = left_type;
7975
- value = op(BigInt(left.value), BigInt(right.value));
7976
- }
8334
+ const type = op.typeFn(left_type, right_type);
8335
+ if (!type)
8336
+ break;
8337
+ const value = op.valueFn(type[1](left.value), type[1](right.value));
7977
8338
  if (value === null)
7978
8339
  break;
7979
- return replacementLiteral(left, value, type);
8340
+ return replacementLiteral(node, value, type[0]);
7980
8341
  }
7981
8342
  break;
7982
8343
  }
@@ -8429,7 +8790,7 @@ async function optimizeMonkeyC(fnMap, resourcesMap, manifestXML, config) {
8429
8790
  if (!state.currentFunction) {
8430
8791
  throw new Error(`Finished function ${state.stack.slice(-1)[0].fullName}, but it was not marked current`);
8431
8792
  }
8432
- state.currentFunction.info = state.currentFunction.next_info;
8793
+ state.currentFunction.info = state.currentFunction.next_info || false;
8433
8794
  delete state.currentFunction.next_info;
8434
8795
  delete state.currentFunction;
8435
8796
  break;
@@ -8992,7 +9353,7 @@ async function createLocalBarrels(targets, options) {
8992
9353
  async function generateOptimizedProject(options) {
8993
9354
  const config = await getConfig(options);
8994
9355
  const workspace = config.workspace;
8995
- const { manifest, targets, xml, jungles } = await get_jungle(config.jungleFiles, config);
9356
+ const { manifest, targets, xml, devices, resources, buildDependencies } = await get_jungle(config.jungleFiles, config);
8996
9357
  if (xml.body instanceof Error) {
8997
9358
  throw xml.body;
8998
9359
  }
@@ -9004,7 +9365,7 @@ async function generateOptimizedProject(options) {
9004
9365
  xml.body.elements[0].loc || undefined;
9005
9366
  throw error;
9006
9367
  }
9007
- const dependencyFiles = [manifest, ...jungles];
9368
+ const dependencyFiles = Object.keys(resources).concat(Object.keys(buildDependencies));
9008
9369
  await createLocalBarrels(targets, config);
9009
9370
  const buildConfigs = {};
9010
9371
  const products = {};
@@ -9102,13 +9463,35 @@ async function generateOptimizedProject(options) {
9102
9463
  relative_manifest = "manifest.xml";
9103
9464
  }
9104
9465
  const parts = [`project.manifest=${relative_manifest}`];
9105
- const process_field = (prefix, base, name, mapper = null) => {
9466
+ const map_field = (base, name, mapper = null) => {
9106
9467
  const obj = base[name];
9107
9468
  if (!obj)
9108
- return;
9469
+ return null;
9109
9470
  const map_one = (s) => (mapper ? mapper(s) : s);
9110
9471
  const map = (s) => Array.isArray(s) ? `[${s.map(map_one).join(";")}]` : map_one(s);
9111
- parts.push(`${prefix}${name} = ${obj.map(map).join(";")}`);
9472
+ return `${obj.map(map).join(";")}`;
9473
+ };
9474
+ const process_field = (prefix, base, name, mapper = null) => {
9475
+ const mapped = map_field(base, name, mapper);
9476
+ if (!mapped)
9477
+ return;
9478
+ parts.push(`${prefix}${name} = ${mapped}`);
9479
+ };
9480
+ const languagesToInclude = Object.fromEntries((manifestLanguages(xml) || []).map((lang) => [lang, true]));
9481
+ const unsupportedLangsCache = {};
9482
+ let availableDefaults = null;
9483
+ const nextAvailableDefault = () => {
9484
+ if (!availableDefaults) {
9485
+ availableDefaults = Object.keys(Object.values(devices).reduce((m, d) => {
9486
+ m[d.deviceFamily] = true;
9487
+ const match = d.deviceFamily.match(/^(\w+)-\d+x\d+/);
9488
+ if (match)
9489
+ m[match[1]] = true;
9490
+ return m;
9491
+ }, {})).sort();
9492
+ availableDefaults.unshift("base");
9493
+ }
9494
+ return availableDefaults.shift();
9112
9495
  };
9113
9496
  targets.forEach((target) => {
9114
9497
  if (!buildConfigs[configKey(target)])
@@ -9145,8 +9528,39 @@ async function generateOptimizedProject(options) {
9145
9528
  process_field(prefix, qualifier, "excludeAnnotations");
9146
9529
  const qlang = qualifier.lang;
9147
9530
  if (qlang) {
9531
+ const devLang = devices[product].languages;
9532
+ const unsupportedLangs = Object.keys(qlang)
9533
+ .sort()
9534
+ .map((key) => {
9535
+ if ((0,external_api_cjs_namespaceObject.hasProperty)(devLang, key) ||
9536
+ !(0,external_api_cjs_namespaceObject.hasProperty)(languagesToInclude, key)) {
9537
+ return null;
9538
+ }
9539
+ const mapped = map_field(qlang, key, relative_path);
9540
+ if (!mapped)
9541
+ return null;
9542
+ return [key, mapped];
9543
+ })
9544
+ .filter((a) => a != null);
9545
+ let keysToSkip = null;
9546
+ if (unsupportedLangs.length) {
9547
+ const key = JSON.stringify(unsupportedLangs);
9548
+ if (!(0,external_api_cjs_namespaceObject.hasProperty)(unsupportedLangsCache, key)) {
9549
+ const base = nextAvailableDefault();
9550
+ if (base) {
9551
+ unsupportedLangs.forEach(([key, value]) => parts.push(`${base}.lang.${key} = ${value}`));
9552
+ unsupportedLangsCache[key] = `${base}.lang`;
9553
+ }
9554
+ }
9555
+ if ((0,external_api_cjs_namespaceObject.hasProperty)(unsupportedLangsCache, key)) {
9556
+ keysToSkip = Object.fromEntries(unsupportedLangs);
9557
+ parts.push(`${prefix}lang = $(${unsupportedLangsCache[key]})`);
9558
+ }
9559
+ }
9148
9560
  Object.keys(qlang).forEach((key) => {
9149
- process_field(`${prefix}lang.`, qlang, key, relative_path);
9561
+ (0,external_api_cjs_namespaceObject.hasProperty)(keysToSkip, key) ||
9562
+ !(0,external_api_cjs_namespaceObject.hasProperty)(languagesToInclude, key) ||
9563
+ process_field(`${prefix}lang.`, qlang, key, relative_path);
9150
9564
  });
9151
9565
  }
9152
9566
  });
@@ -9266,7 +9680,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
9266
9680
  // the oldest optimized file, we don't need to regenerate
9267
9681
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
9268
9682
  const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
9269
- if (source_time < opt_time && 1670458646779 < opt_time) {
9683
+ if (source_time < opt_time && 1672601827382 < opt_time) {
9270
9684
  return { hasTests, diagnostics: prevDiagnostics };
9271
9685
  }
9272
9686
  }
@@ -9293,7 +9707,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
9293
9707
  return promises_namespaceObject.writeFile(external_path_.join(output, "build-info.json"), JSON.stringify({
9294
9708
  hasTests,
9295
9709
  diagnostics,
9296
- optimizerVersion: "1.0.43",
9710
+ optimizerVersion: "1.0.45",
9297
9711
  ...Object.fromEntries(configOptionsToCheck.map((option) => [option, config[option]])),
9298
9712
  }))
9299
9713
  .then(() => ({ hasTests, diagnostics }));