@markw65/monkeyc-optimizer 1.0.13 → 1.0.14

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/README.md CHANGED
@@ -141,3 +141,17 @@ More fixes found via open source projects.
141
141
 
142
142
  - Tests
143
143
  - Add date/time to test logging
144
+
145
+ ### 1.0.14
146
+
147
+ - Bug fixes
148
+
149
+ - When reading a barrel project with no products, add all products by default
150
+ - Only set language specific paths for languages that are supported by the device
151
+ - Remove comments that are completely contained within removed nodes
152
+
153
+ - Code cleanup
154
+ - Upgrade to @markw65/prettier-plugin-monkeyc@1.0.21 for some typescript fixes
155
+ - npm upgrade to pickup ts 4.7.2
156
+ - Add types to package exports for ts 4.7.2
157
+ - Better handling of program-logic errors
package/build/api.cjs CHANGED
@@ -346,7 +346,7 @@ async function analyze(fnMap) {
346
346
  return drop;
347
347
  }, false);
348
348
  }
349
- return null;
349
+ return false;
350
350
  },
351
351
  post(node, state) {
352
352
  switch (node.type) {
@@ -973,71 +973,77 @@ async function optimizeMonkeyC(fnMap) {
973
973
  Object.values(fnMap).forEach((f) => {
974
974
  collectNamespaces(f.ast, state);
975
975
  });
976
- Object.values(fnMap).forEach((f) => {
977
- traverseAst(f.ast, undefined, (node) => {
978
- switch (node.type) {
979
- case "EnumStringBody":
980
- if (node.members.every((m) => {
981
- const name = "name" in m ? m.name : m.id.name;
982
- return (hasProperty(state.index, name) &&
983
- !hasProperty(state.exposed, name));
984
- })) {
985
- node.enumType = [
986
- ...new Set(node.members.map((m) => {
987
- if (!("init" in m))
988
- return "Number";
989
- const [node, type] = getNodeValue(m.init);
990
- if (!node) {
991
- throw new Error("Failed to get type for eliminated enum");
992
- }
993
- return type;
994
- })),
995
- ].join(" or ");
996
- node.members.splice(0);
997
- }
998
- break;
999
- case "EnumDeclaration":
1000
- if (!node.body.members.length) {
1001
- if (!node.id)
1002
- return false;
1003
- if (!node.body["enumType"]) {
1004
- throw new Error("Missing enumType on optimized enum");
1005
- }
1006
- replace(node, {
1007
- type: "TypedefDeclaration",
1008
- id: node.id,
1009
- ts: {
1010
- type: "UnaryExpression",
1011
- argument: { type: "TypeSpecList", ts: [node.body.enumType] },
1012
- prefix: true,
1013
- operator: " as",
1014
- },
1015
- });
1016
- }
1017
- break;
1018
- case "VariableDeclaration": {
1019
- node.declarations = node.declarations.filter((d) => {
1020
- const name = variableDeclarationName(d.id);
1021
- return (!hasProperty(state.index, name) ||
1022
- hasProperty(state.exposed, name));
1023
- });
1024
- if (!node.declarations.length) {
1025
- return false;
1026
- }
1027
- break;
976
+ const cleanup = (node) => {
977
+ switch (node.type) {
978
+ case "EnumStringBody":
979
+ if (node.members.every((m) => {
980
+ const name = "name" in m ? m.name : m.id.name;
981
+ return (hasProperty(state.index, name) &&
982
+ !hasProperty(state.exposed, name));
983
+ })) {
984
+ node.enumType = [
985
+ ...new Set(node.members.map((m) => {
986
+ if (!("init" in m))
987
+ return "Number";
988
+ const [node, type] = getNodeValue(m.init);
989
+ if (!node) {
990
+ throw new Error("Failed to get type for eliminated enum");
991
+ }
992
+ return type;
993
+ })),
994
+ ].join(" or ");
995
+ node.members.splice(0);
1028
996
  }
1029
- case "ClassElement":
1030
- if (!node.item) {
1031
- return false;
1032
- }
1033
- break;
1034
- case "FunctionDeclaration":
1035
- if (!maybeCalled(node)) {
997
+ break;
998
+ case "EnumDeclaration":
999
+ if (!node.body.members.length) {
1000
+ if (!node.id)
1036
1001
  return false;
1002
+ if (!node.body["enumType"]) {
1003
+ throw new Error("Missing enumType on optimized enum");
1037
1004
  }
1038
- break;
1005
+ replace(node, {
1006
+ type: "TypedefDeclaration",
1007
+ id: node.id,
1008
+ ts: {
1009
+ type: "UnaryExpression",
1010
+ argument: { type: "TypeSpecList", ts: [node.body.enumType] },
1011
+ prefix: true,
1012
+ operator: " as",
1013
+ },
1014
+ });
1015
+ }
1016
+ break;
1017
+ case "VariableDeclaration": {
1018
+ node.declarations = node.declarations.filter((d) => {
1019
+ const name = variableDeclarationName(d.id);
1020
+ return (!hasProperty(state.index, name) || hasProperty(state.exposed, name));
1021
+ });
1022
+ if (!node.declarations.length) {
1023
+ return false;
1024
+ }
1025
+ break;
1039
1026
  }
1040
- return null;
1027
+ case "ClassElement":
1028
+ if (!node.item) {
1029
+ return false;
1030
+ }
1031
+ break;
1032
+ case "FunctionDeclaration":
1033
+ if (!maybeCalled(node)) {
1034
+ return false;
1035
+ }
1036
+ break;
1037
+ }
1038
+ return null;
1039
+ };
1040
+ Object.values(fnMap).forEach((f) => {
1041
+ traverseAst(f.ast, undefined, (node) => {
1042
+ const ret = cleanup(node);
1043
+ if (ret === false) {
1044
+ state.removeNodeComments(node, f.ast);
1045
+ }
1046
+ return ret;
1041
1047
  });
1042
1048
  });
1043
1049
  }
@@ -1190,6 +1196,30 @@ function api_collectNamespaces(ast, stateIn) {
1190
1196
  }
1191
1197
  return null;
1192
1198
  };
1199
+ state.removeNodeComments = (node, ast) => {
1200
+ if (node.start && node.end && ast.comments && ast.comments.length) {
1201
+ let low = 0, high = ast.comments.length;
1202
+ while (true) {
1203
+ const mid = (low + high) >> 1;
1204
+ if (mid == low) {
1205
+ if (ast.comments[mid].start < node.start) {
1206
+ return;
1207
+ }
1208
+ break;
1209
+ }
1210
+ if (ast.comments[mid].start < node.start) {
1211
+ low = mid;
1212
+ }
1213
+ else {
1214
+ high = mid;
1215
+ }
1216
+ }
1217
+ for (high = low; high < ast.comments.length && ast.comments[high].end < node.end; high++) { }
1218
+ if (high > low) {
1219
+ ast.comments.splice(low, high - low);
1220
+ }
1221
+ }
1222
+ };
1193
1223
  state.lookup = (node, name, stack) => {
1194
1224
  stack || (stack = state.stack);
1195
1225
  switch (node.type) {
@@ -1400,12 +1430,17 @@ function api_collectNamespaces(ast, stateIn) {
1400
1430
  let ret;
1401
1431
  if (state.shouldExclude && state.shouldExclude(node)) {
1402
1432
  // delete the node.
1403
- return false;
1433
+ ret = false;
1434
+ }
1435
+ else {
1436
+ if (state.post)
1437
+ ret = state.post(node, state);
1438
+ if (state.stack.slice(-1).pop()?.node === node) {
1439
+ state.stack.pop();
1440
+ }
1404
1441
  }
1405
- if (state.post)
1406
- ret = state.post(node, state);
1407
- if (state.stack.slice(-1).pop()?.node === node) {
1408
- state.stack.pop();
1442
+ if (ret === false) {
1443
+ state.removeNodeComments(node, ast);
1409
1444
  }
1410
1445
  return ret;
1411
1446
  }
@@ -1500,7 +1535,6 @@ function formatAst(node, monkeyCSource = null) {
1500
1535
  });
1501
1536
  }
1502
1537
  function handleException(state, node, exception) {
1503
- let message;
1504
1538
  try {
1505
1539
  const fullName = state.stack
1506
1540
  .map((e) => e.name)
@@ -1510,12 +1544,19 @@ function handleException(state, node, exception) {
1510
1544
  const location = node.loc && node.loc.source
1511
1545
  ? `${node.loc.source}:${node.start || 0}:${node.end || 0}`
1512
1546
  : "<unknown>";
1513
- message = `Got exception \`${Object.prototype.toString.call(exception)}' while processing node ${fullName}:${node.type} from ${location}`;
1547
+ const message = `Got exception \`${exception instanceof Error
1548
+ ? exception.message
1549
+ : Object.prototype.toString.call(exception)}' while processing node ${fullName}:${node.type} from ${location}`;
1550
+ if (exception instanceof Error) {
1551
+ exception.message = message;
1552
+ }
1553
+ else {
1554
+ exception = new Error(message);
1555
+ }
1514
1556
  }
1515
- catch {
1557
+ finally {
1516
1558
  throw exception;
1517
1559
  }
1518
- throw new Error(message);
1519
1560
  }
1520
1561
 
1521
1562
  })();
@@ -1289,7 +1289,7 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
1289
1289
  const debug = __webpack_require__(1227)('extract-zip')
1290
1290
  // eslint-disable-next-line node/no-unsupported-features/node-builtins
1291
1291
  const { createWriteStream, promises: fs } = __webpack_require__(6231)
1292
- const getStream = __webpack_require__(7491)
1292
+ const getStream = __webpack_require__(31)
1293
1293
  const path = __webpack_require__(1423)
1294
1294
  const { promisify } = __webpack_require__(6464)
1295
1295
  const stream = __webpack_require__(8311)
@@ -1461,134 +1461,6 @@ module.exports = async function (zipPath, opts) {
1461
1461
  }
1462
1462
 
1463
1463
 
1464
- /***/ }),
1465
-
1466
- /***/ 2297:
1467
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1468
-
1469
- "use strict";
1470
-
1471
- const {PassThrough: PassThroughStream} = __webpack_require__(8311);
1472
-
1473
- module.exports = options => {
1474
- options = {...options};
1475
-
1476
- const {array} = options;
1477
- let {encoding} = options;
1478
- const isBuffer = encoding === 'buffer';
1479
- let objectMode = false;
1480
-
1481
- if (array) {
1482
- objectMode = !(encoding || isBuffer);
1483
- } else {
1484
- encoding = encoding || 'utf8';
1485
- }
1486
-
1487
- if (isBuffer) {
1488
- encoding = null;
1489
- }
1490
-
1491
- const stream = new PassThroughStream({objectMode});
1492
-
1493
- if (encoding) {
1494
- stream.setEncoding(encoding);
1495
- }
1496
-
1497
- let length = 0;
1498
- const chunks = [];
1499
-
1500
- stream.on('data', chunk => {
1501
- chunks.push(chunk);
1502
-
1503
- if (objectMode) {
1504
- length = chunks.length;
1505
- } else {
1506
- length += chunk.length;
1507
- }
1508
- });
1509
-
1510
- stream.getBufferedValue = () => {
1511
- if (array) {
1512
- return chunks;
1513
- }
1514
-
1515
- return isBuffer ? Buffer.concat(chunks, length) : chunks.join('');
1516
- };
1517
-
1518
- stream.getBufferedLength = () => length;
1519
-
1520
- return stream;
1521
- };
1522
-
1523
-
1524
- /***/ }),
1525
-
1526
- /***/ 7491:
1527
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1528
-
1529
- "use strict";
1530
-
1531
- const {constants: BufferConstants} = __webpack_require__(871);
1532
- const pump = __webpack_require__(4286);
1533
- const bufferStream = __webpack_require__(2297);
1534
-
1535
- class MaxBufferError extends Error {
1536
- constructor() {
1537
- super('maxBuffer exceeded');
1538
- this.name = 'MaxBufferError';
1539
- }
1540
- }
1541
-
1542
- async function getStream(inputStream, options) {
1543
- if (!inputStream) {
1544
- return Promise.reject(new Error('Expected a stream'));
1545
- }
1546
-
1547
- options = {
1548
- maxBuffer: Infinity,
1549
- ...options
1550
- };
1551
-
1552
- const {maxBuffer} = options;
1553
-
1554
- let stream;
1555
- await new Promise((resolve, reject) => {
1556
- const rejectPromise = error => {
1557
- // Don't retrieve an oversized buffer.
1558
- if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
1559
- error.bufferedData = stream.getBufferedValue();
1560
- }
1561
-
1562
- reject(error);
1563
- };
1564
-
1565
- stream = pump(inputStream, bufferStream(options), error => {
1566
- if (error) {
1567
- rejectPromise(error);
1568
- return;
1569
- }
1570
-
1571
- resolve();
1572
- });
1573
-
1574
- stream.on('data', () => {
1575
- if (stream.getBufferedLength() > maxBuffer) {
1576
- rejectPromise(new MaxBufferError());
1577
- }
1578
- });
1579
- });
1580
-
1581
- return stream.getBufferedValue();
1582
- }
1583
-
1584
- module.exports = getStream;
1585
- // TODO: Remove this for the next major release
1586
- module.exports["default"] = getStream;
1587
- module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'});
1588
- module.exports.array = (stream, options) => getStream(stream, {...options, array: true});
1589
- module.exports.MaxBufferError = MaxBufferError;
1590
-
1591
-
1592
1464
  /***/ }),
1593
1465
 
1594
1466
  /***/ 8913:
@@ -1892,6 +1764,134 @@ function createFromFd(fd, options) {
1892
1764
  }
1893
1765
 
1894
1766
 
1767
+ /***/ }),
1768
+
1769
+ /***/ 5105:
1770
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1771
+
1772
+ "use strict";
1773
+
1774
+ const {PassThrough: PassThroughStream} = __webpack_require__(8311);
1775
+
1776
+ module.exports = options => {
1777
+ options = {...options};
1778
+
1779
+ const {array} = options;
1780
+ let {encoding} = options;
1781
+ const isBuffer = encoding === 'buffer';
1782
+ let objectMode = false;
1783
+
1784
+ if (array) {
1785
+ objectMode = !(encoding || isBuffer);
1786
+ } else {
1787
+ encoding = encoding || 'utf8';
1788
+ }
1789
+
1790
+ if (isBuffer) {
1791
+ encoding = null;
1792
+ }
1793
+
1794
+ const stream = new PassThroughStream({objectMode});
1795
+
1796
+ if (encoding) {
1797
+ stream.setEncoding(encoding);
1798
+ }
1799
+
1800
+ let length = 0;
1801
+ const chunks = [];
1802
+
1803
+ stream.on('data', chunk => {
1804
+ chunks.push(chunk);
1805
+
1806
+ if (objectMode) {
1807
+ length = chunks.length;
1808
+ } else {
1809
+ length += chunk.length;
1810
+ }
1811
+ });
1812
+
1813
+ stream.getBufferedValue = () => {
1814
+ if (array) {
1815
+ return chunks;
1816
+ }
1817
+
1818
+ return isBuffer ? Buffer.concat(chunks, length) : chunks.join('');
1819
+ };
1820
+
1821
+ stream.getBufferedLength = () => length;
1822
+
1823
+ return stream;
1824
+ };
1825
+
1826
+
1827
+ /***/ }),
1828
+
1829
+ /***/ 31:
1830
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1831
+
1832
+ "use strict";
1833
+
1834
+ const {constants: BufferConstants} = __webpack_require__(871);
1835
+ const pump = __webpack_require__(4286);
1836
+ const bufferStream = __webpack_require__(5105);
1837
+
1838
+ class MaxBufferError extends Error {
1839
+ constructor() {
1840
+ super('maxBuffer exceeded');
1841
+ this.name = 'MaxBufferError';
1842
+ }
1843
+ }
1844
+
1845
+ async function getStream(inputStream, options) {
1846
+ if (!inputStream) {
1847
+ return Promise.reject(new Error('Expected a stream'));
1848
+ }
1849
+
1850
+ options = {
1851
+ maxBuffer: Infinity,
1852
+ ...options
1853
+ };
1854
+
1855
+ const {maxBuffer} = options;
1856
+
1857
+ let stream;
1858
+ await new Promise((resolve, reject) => {
1859
+ const rejectPromise = error => {
1860
+ // Don't retrieve an oversized buffer.
1861
+ if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
1862
+ error.bufferedData = stream.getBufferedValue();
1863
+ }
1864
+
1865
+ reject(error);
1866
+ };
1867
+
1868
+ stream = pump(inputStream, bufferStream(options), error => {
1869
+ if (error) {
1870
+ rejectPromise(error);
1871
+ return;
1872
+ }
1873
+
1874
+ resolve();
1875
+ });
1876
+
1877
+ stream.on('data', () => {
1878
+ if (stream.getBufferedLength() > maxBuffer) {
1879
+ rejectPromise(new MaxBufferError());
1880
+ }
1881
+ });
1882
+ });
1883
+
1884
+ return stream.getBufferedValue();
1885
+ }
1886
+
1887
+ module.exports = getStream;
1888
+ // TODO: Remove this for the next major release
1889
+ module.exports["default"] = getStream;
1890
+ module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'});
1891
+ module.exports.array = (stream, options) => getStream(stream, {...options, array: true});
1892
+ module.exports.MaxBufferError = MaxBufferError;
1893
+
1894
+
1895
1895
  /***/ }),
1896
1896
 
1897
1897
  /***/ 7824:
@@ -10077,7 +10077,8 @@ async function default_jungle() {
10077
10077
  }
10078
10078
  rezAndLang(deviceId, `resources-${deviceId}`, deviceFamily);
10079
10079
  });
10080
- return process_assignments(assignments, {});
10080
+ const state = await process_assignments(assignments, {});
10081
+ return { state, devices };
10081
10082
  }
10082
10083
  function process_assignments(assignments, current) {
10083
10084
  return assignments.reduce((state, a) => {
@@ -10179,9 +10180,9 @@ async function process_jungles(sources) {
10179
10180
  sources = [sources];
10180
10181
  }
10181
10182
  const results = await Promise.all(sources.map(parse_one));
10182
- const state = await default_jungle();
10183
+ const { state, devices } = await default_jungle();
10183
10184
  results.forEach((r) => process_assignments(r, state));
10184
- return state;
10185
+ return { state, devices };
10185
10186
  }
10186
10187
  function resolve_node_list(state, list) {
10187
10188
  if (!Array.isArray(list)) {
@@ -10303,7 +10304,7 @@ function resolve_filename(literal, default_source = null) {
10303
10304
  const root = external_path_.dirname(literal.source || default_source);
10304
10305
  return external_path_.resolve(root, literal.value);
10305
10306
  }
10306
- async function resolve_literals(qualifier, default_source) {
10307
+ async function resolve_literals(qualifier, default_source, deviceInfo) {
10307
10308
  const resolve_file_list = async (literals) => literals &&
10308
10309
  (await Promise.all(literals.map(async (v) => {
10309
10310
  if (!isJNode(v)) {
@@ -10346,7 +10347,13 @@ async function resolve_literals(qualifier, default_source) {
10346
10347
  await resolve_one_file_list(qualifier, "barrelPath");
10347
10348
  const lang = qualifier["lang"];
10348
10349
  if (lang) {
10349
- await Promise.all(Object.keys(lang).map((key) => resolve_one_file_list(lang, key)));
10350
+ await Promise.all(Object.keys(lang).map((key) => {
10351
+ if (!(0,external_api_cjs_namespaceObject.hasProperty)(deviceInfo.languages, key)) {
10352
+ delete lang[key];
10353
+ return null;
10354
+ }
10355
+ return resolve_one_file_list(lang, key);
10356
+ }));
10350
10357
  if (Object.keys(lang).length === 0)
10351
10358
  delete qualifier["lang"];
10352
10359
  }
@@ -10704,7 +10711,7 @@ async function get_jungle_and_barrels(jungleFiles, defaultProducts, options) {
10704
10711
  jungles.push(barrels_jungle);
10705
10712
  }
10706
10713
  }
10707
- const state = await process_jungles(jungles);
10714
+ const { state, devices } = await process_jungles(jungles);
10708
10715
  // apparently square_watch is an alias for rectangle_watch
10709
10716
  state["square_watch"] = state["rectangle_watch"];
10710
10717
  const manifest_node = resolve_node(state, resolve_node_by_path(state, ["project", "manifest"]));
@@ -10719,15 +10726,21 @@ async function get_jungle_and_barrels(jungleFiles, defaultProducts, options) {
10719
10726
  const barrels = manifestBarrels(xml);
10720
10727
  const annotations = manifestAnnotations(xml);
10721
10728
  const products = manifestProducts(xml);
10722
- if (products.length === 0)
10723
- products.push(...defaultProducts);
10729
+ if (products.length === 0) {
10730
+ if (defaultProducts) {
10731
+ products.push(...defaultProducts);
10732
+ }
10733
+ else if (xml["iq:manifest"]["iq:barrel"]) {
10734
+ products.push(...Object.keys(devices).sort());
10735
+ }
10736
+ }
10724
10737
  let promise = Promise.resolve();
10725
10738
  const add_one = (product, shape = undefined) => {
10726
10739
  const rawQualifier = resolve_node(state, state[product]);
10727
10740
  if (!rawQualifier || Array.isArray(rawQualifier))
10728
10741
  return;
10729
10742
  promise = promise
10730
- .then(() => resolve_literals(rawQualifier, manifest))
10743
+ .then(() => resolve_literals(rawQualifier, manifest, devices[product]))
10731
10744
  .then((qualifier) => {
10732
10745
  targets.push({ product, qualifier, shape });
10733
10746
  return resolve_barrels(product, qualifier, barrels, products, options);
@@ -10753,7 +10766,7 @@ async function get_jungle_and_barrels(jungleFiles, defaultProducts, options) {
10753
10766
  }
10754
10767
  async function get_jungle(jungles, options) {
10755
10768
  options = options || {};
10756
- const result = await get_jungle_and_barrels(jungles, [], options);
10769
+ const result = await get_jungle_and_barrels(jungles, null, options);
10757
10770
  identify_optimizer_groups(result.targets, options);
10758
10771
  return result;
10759
10772
  }
@@ -10888,7 +10901,7 @@ async function analyze(fnMap) {
10888
10901
  return drop;
10889
10902
  }, false);
10890
10903
  }
10891
- return null;
10904
+ return false;
10892
10905
  },
10893
10906
  post(node, state) {
10894
10907
  switch (node.type) {
@@ -11515,71 +11528,77 @@ async function optimizeMonkeyC(fnMap) {
11515
11528
  Object.values(fnMap).forEach((f) => {
11516
11529
  (0,external_api_cjs_namespaceObject.collectNamespaces)(f.ast, state);
11517
11530
  });
11518
- Object.values(fnMap).forEach((f) => {
11519
- (0,external_api_cjs_namespaceObject.traverseAst)(f.ast, undefined, (node) => {
11520
- switch (node.type) {
11521
- case "EnumStringBody":
11522
- if (node.members.every((m) => {
11523
- const name = "name" in m ? m.name : m.id.name;
11524
- return ((0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) &&
11525
- !(0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name));
11526
- })) {
11527
- node.enumType = [
11528
- ...new Set(node.members.map((m) => {
11529
- if (!("init" in m))
11530
- return "Number";
11531
- const [node, type] = getNodeValue(m.init);
11532
- if (!node) {
11533
- throw new Error("Failed to get type for eliminated enum");
11534
- }
11535
- return type;
11536
- })),
11537
- ].join(" or ");
11538
- node.members.splice(0);
11539
- }
11540
- break;
11541
- case "EnumDeclaration":
11542
- if (!node.body.members.length) {
11543
- if (!node.id)
11544
- return false;
11545
- if (!node.body["enumType"]) {
11546
- throw new Error("Missing enumType on optimized enum");
11547
- }
11548
- replace(node, {
11549
- type: "TypedefDeclaration",
11550
- id: node.id,
11551
- ts: {
11552
- type: "UnaryExpression",
11553
- argument: { type: "TypeSpecList", ts: [node.body.enumType] },
11554
- prefix: true,
11555
- operator: " as",
11556
- },
11557
- });
11558
- }
11559
- break;
11560
- case "VariableDeclaration": {
11561
- node.declarations = node.declarations.filter((d) => {
11562
- const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(d.id);
11563
- return (!(0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) ||
11564
- (0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name));
11565
- });
11566
- if (!node.declarations.length) {
11567
- return false;
11568
- }
11569
- break;
11531
+ const cleanup = (node) => {
11532
+ switch (node.type) {
11533
+ case "EnumStringBody":
11534
+ if (node.members.every((m) => {
11535
+ const name = "name" in m ? m.name : m.id.name;
11536
+ return ((0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) &&
11537
+ !(0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name));
11538
+ })) {
11539
+ node.enumType = [
11540
+ ...new Set(node.members.map((m) => {
11541
+ if (!("init" in m))
11542
+ return "Number";
11543
+ const [node, type] = getNodeValue(m.init);
11544
+ if (!node) {
11545
+ throw new Error("Failed to get type for eliminated enum");
11546
+ }
11547
+ return type;
11548
+ })),
11549
+ ].join(" or ");
11550
+ node.members.splice(0);
11570
11551
  }
11571
- case "ClassElement":
11572
- if (!node.item) {
11573
- return false;
11574
- }
11575
- break;
11576
- case "FunctionDeclaration":
11577
- if (!maybeCalled(node)) {
11552
+ break;
11553
+ case "EnumDeclaration":
11554
+ if (!node.body.members.length) {
11555
+ if (!node.id)
11578
11556
  return false;
11557
+ if (!node.body["enumType"]) {
11558
+ throw new Error("Missing enumType on optimized enum");
11579
11559
  }
11580
- break;
11560
+ replace(node, {
11561
+ type: "TypedefDeclaration",
11562
+ id: node.id,
11563
+ ts: {
11564
+ type: "UnaryExpression",
11565
+ argument: { type: "TypeSpecList", ts: [node.body.enumType] },
11566
+ prefix: true,
11567
+ operator: " as",
11568
+ },
11569
+ });
11570
+ }
11571
+ break;
11572
+ case "VariableDeclaration": {
11573
+ node.declarations = node.declarations.filter((d) => {
11574
+ const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(d.id);
11575
+ return (!(0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) || (0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name));
11576
+ });
11577
+ if (!node.declarations.length) {
11578
+ return false;
11579
+ }
11580
+ break;
11581
11581
  }
11582
- return null;
11582
+ case "ClassElement":
11583
+ if (!node.item) {
11584
+ return false;
11585
+ }
11586
+ break;
11587
+ case "FunctionDeclaration":
11588
+ if (!maybeCalled(node)) {
11589
+ return false;
11590
+ }
11591
+ break;
11592
+ }
11593
+ return null;
11594
+ };
11595
+ Object.values(fnMap).forEach((f) => {
11596
+ (0,external_api_cjs_namespaceObject.traverseAst)(f.ast, undefined, (node) => {
11597
+ const ret = cleanup(node);
11598
+ if (ret === false) {
11599
+ state.removeNodeComments(node, f.ast);
11600
+ }
11601
+ return ret;
11583
11602
  });
11584
11603
  });
11585
11604
  }
@@ -12006,7 +12025,7 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
12006
12025
  // the oldest optimized file, we don't need to regenerate
12007
12026
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
12008
12027
  const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
12009
- if (source_time < opt_time && 1653671578547 < opt_time) {
12028
+ if (source_time < opt_time && 1653864408816 < opt_time) {
12010
12029
  return hasTests;
12011
12030
  }
12012
12031
  }
@@ -7215,8 +7215,14 @@ async function getDeviceInfo() {
7215
7215
  }
7216
7216
  return Promise.all(files.map((file) => {
7217
7217
  return promises_namespaceObject.readFile(file).then((data) => {
7218
- const { deviceId, appTypes, deviceFamily, displayName } = JSON.parse(data.toString());
7219
- return [deviceId, { appTypes, deviceFamily, displayName }];
7218
+ const { deviceId, appTypes, deviceFamily, displayName, partNumbers } = JSON.parse(data.toString());
7219
+ const languages = Object.fromEntries(partNumbers
7220
+ .map((part) => part.languages.map((lang) => [lang.code, true]))
7221
+ .flat(1));
7222
+ return [
7223
+ deviceId,
7224
+ { appTypes, deviceFamily, displayName, languages },
7225
+ ];
7220
7226
  });
7221
7227
  })).then((info) => {
7222
7228
  return Object.fromEntries(info);
@@ -90,7 +90,8 @@ declare global {
90
90
  allFunctions?: FunctionStateNode[];
91
91
  allClasses?: ClassStateNode[];
92
92
  stack?: ProgramStateStack;
93
- shouldExclude?: (node: any) => any;
93
+ removeNodeComments?: (node: mctree.Node, ast: mctree.Program) => void;
94
+ shouldExclude?: (node: mctree.Node) => boolean;
94
95
  pre?: (node: mctree.Node, state: ProgramStateLive) => null | false | (keyof mctree.NodeAll)[];
95
96
  post?: (node: mctree.Node, state: ProgramStateLive) => null | false | mctree.Node;
96
97
  lookup?: (node: mctree.Node, name?: string | null, stack?: ProgramStateStack) => [string, StateNodeDecl[], ProgramStateStack] | [null, null, null];
@@ -120,7 +121,7 @@ declare global {
120
121
  type Finalized<T, Keys extends keyof T> = T & {
121
122
  [key in Keys]-?: NonNullable<T[key]>;
122
123
  };
123
- export type ProgramStateLive = Finalized<ProgramState, "stack" | "lookup" | "traverse" | "index" | "constants">;
124
+ export type ProgramStateLive = Finalized<ProgramState, "stack" | "lookup" | "traverse" | "index" | "constants" | "removeNodeComments">;
124
125
  export type ProgramStateAnalysis = Finalized<ProgramStateLive, "allClasses" | "allFunctions">;
125
126
  export type ProgramStateOptimizer = Finalized<ProgramStateAnalysis, "localsStack" | "exposed" | "calledFunctions">;
126
127
  type ExcludeAnnotationsMap = {
@@ -2,7 +2,7 @@ export declare const isWin: boolean;
2
2
  export declare const appSupport: string;
3
3
  export declare const connectiq: string;
4
4
  export declare function getSdkPath(): Promise<string>;
5
- export declare function getDeviceInfo(): Promise<{
5
+ export declare type DeviceInfo = {
6
6
  [key: string]: {
7
7
  appTypes: {
8
8
  memoryLimit: number;
@@ -10,6 +10,8 @@ export declare function getDeviceInfo(): Promise<{
10
10
  }[];
11
11
  deviceFamily: string;
12
12
  displayName: string;
13
+ languages: Record<string, true>;
13
14
  };
14
- }>;
15
+ };
16
+ export declare function getDeviceInfo(): Promise<DeviceInfo>;
15
17
  export declare function getLanguages(): Promise<any>;
package/build/util.cjs CHANGED
@@ -1303,6 +1303,8 @@ function setopts (self, pattern, options) {
1303
1303
  // Note that they are not supported in Glob itself anyway.
1304
1304
  options.nonegate = true
1305
1305
  options.nocomment = true
1306
+ // always treat \ in patterns as escapes, not path separators
1307
+ options.allowWindowsEscape = false
1306
1308
 
1307
1309
  self.minimatch = new Minimatch(pattern, options)
1308
1310
  self.options = self.minimatch.options
@@ -1778,7 +1780,10 @@ Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
1778
1780
  var read
1779
1781
  if (prefix === null)
1780
1782
  read = '.'
1781
- else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
1783
+ else if (isAbsolute(prefix) ||
1784
+ isAbsolute(pattern.map(function (p) {
1785
+ return typeof p === 'string' ? p : '[*]'
1786
+ }).join('/'))) {
1782
1787
  if (!prefix || !isAbsolute(prefix))
1783
1788
  prefix = '/' + prefix
1784
1789
  read = prefix
@@ -2278,7 +2283,7 @@ function GlobSync (pattern, options) {
2278
2283
  }
2279
2284
 
2280
2285
  GlobSync.prototype._finish = function () {
2281
- assert(this instanceof GlobSync)
2286
+ assert.ok(this instanceof GlobSync)
2282
2287
  if (this.realpath) {
2283
2288
  var self = this
2284
2289
  this.matches.forEach(function (matchset, index) {
@@ -2302,7 +2307,7 @@ GlobSync.prototype._finish = function () {
2302
2307
 
2303
2308
 
2304
2309
  GlobSync.prototype._process = function (pattern, index, inGlobStar) {
2305
- assert(this instanceof GlobSync)
2310
+ assert.ok(this instanceof GlobSync)
2306
2311
 
2307
2312
  // Get the first [n] parts of pattern that are all strings.
2308
2313
  var n = 0
@@ -2339,7 +2344,10 @@ GlobSync.prototype._process = function (pattern, index, inGlobStar) {
2339
2344
  var read
2340
2345
  if (prefix === null)
2341
2346
  read = '.'
2342
- else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
2347
+ else if (isAbsolute(prefix) ||
2348
+ isAbsolute(pattern.map(function (p) {
2349
+ return typeof p === 'string' ? p : '[*]'
2350
+ }).join('/'))) {
2343
2351
  if (!prefix || !isAbsolute(prefix))
2344
2352
  prefix = '/' + prefix
2345
2353
  read = prefix
package/package.json CHANGED
@@ -1,13 +1,19 @@
1
1
  {
2
2
  "name": "@markw65/monkeyc-optimizer",
3
3
  "type": "module",
4
- "version": "1.0.13",
4
+ "version": "1.0.14",
5
5
  "description": "Source to source optimizer for Garmin Monkey C code",
6
6
  "main": "build/optimizer.cjs",
7
7
  "types": "build/src/optimizer.d.ts",
8
8
  "exports": {
9
- ".": "./build/optimizer.cjs",
10
- "./*.js": "./build/*.cjs"
9
+ ".": {
10
+ "types": "./build/src/optimizer.d.ts",
11
+ "default": "./build/optimizer.cjs"
12
+ },
13
+ "./*.js": {
14
+ "types": "./build/src/*.d.ts",
15
+ "default": "./build/*.cjs"
16
+ }
11
17
  },
12
18
  "scripts": {
13
19
  "watch": "webpack --mode development --watch",
@@ -27,7 +33,7 @@
27
33
  "author": "markw65",
28
34
  "license": "MIT",
29
35
  "dependencies": {
30
- "@markw65/prettier-plugin-monkeyc": "^1.0.20"
36
+ "@markw65/prettier-plugin-monkeyc": "^1.0.21"
31
37
  },
32
38
  "devDependencies": {
33
39
  "@types/glob": "^7.2.0",