bare-script 3.8.2 → 3.8.3

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/lib/model.js CHANGED
@@ -433,9 +433,15 @@ export function lintScript(script, globals = null) {
433
433
  // Iterate function statements
434
434
  const fnLabelsDefined = {};
435
435
  const fnLabelsUsed = {};
436
+ let hasAsyncStatement = false;
436
437
  for (const [ixFnStatement, fnStatement] of fnStatements.entries()) {
437
438
  const [fnStatementKey] = Object.keys(fnStatement);
438
439
 
440
+ // Any async statements?
441
+ if (globals !== null) {
442
+ hasAsyncStatement ||= isAsyncStatement(fnStatement, globals, statement.function.async ?? false);
443
+ }
444
+
439
445
  // Function expression statement checks
440
446
  if (fnStatementKey === 'expr') {
441
447
  // Pointless function expression statement?
@@ -478,6 +484,15 @@ export function lintScript(script, globals = null) {
478
484
  }
479
485
  }
480
486
 
487
+ // Async function issues?
488
+ if (globals !== null) {
489
+ if (statement.function.async && !hasAsyncStatement) {
490
+ lintScriptWarning(warnings, script, statement, `Unecessary async function "${statement.function.name}"`);
491
+ } else if (!statement.function.async && hasAsyncStatement) {
492
+ lintScriptWarning(warnings, script, statement, `Function "${statement.function.name}" requires async`);
493
+ }
494
+ }
495
+
481
496
  // Global expression statement checks
482
497
  } else if (statementKey === 'expr') {
483
498
  // Pointless global expression statement?
@@ -549,6 +564,43 @@ function isPointlessExpression(expr) {
549
564
  }
550
565
 
551
566
 
567
+ // Helper function to determine if a statement requires async
568
+ function isAsyncStatement(statement, globals, isAsync) {
569
+ const [statementKey] = Object.keys(statement);
570
+ if (statementKey === 'expr') {
571
+ return isAsyncExpression(statement.expr.expr, globals, isAsync);
572
+ } else if (statementKey === 'jump') {
573
+ return 'expr' in statement.jump ? isAsyncExpression(statement.jump.expr, globals, isAsync) : false;
574
+ } else if (statementKey === 'return') {
575
+ return 'expr' in statement.return ? isAsyncExpression(statement.return.expr, globals, isAsync) : false;
576
+ }
577
+ return false;
578
+ }
579
+
580
+
581
+ // Helper function to determine if an expression statement requires async
582
+ function isAsyncExpression(expr, globals, isAsync) {
583
+ const [exprKey] = Object.keys(expr);
584
+ if (exprKey === 'function') {
585
+ // Global function not exist? Assume its OK for the scope
586
+ const funcValue = globals[expr.function.name] ?? null;
587
+ if (funcValue === null) {
588
+ return isAsync;
589
+ }
590
+
591
+ // Is function async?
592
+ return typeof funcValue === 'function' && funcValue.constructor.name === 'AsyncFunction';
593
+ } else if (exprKey === 'binary') {
594
+ return isAsyncExpression(expr.binary.left, globals, isAsync) || isAsyncExpression(expr.binary.right, globals, isAsync);
595
+ } else if (exprKey === 'unary') {
596
+ return isAsyncExpression(expr.unary.expr, globals, isAsync);
597
+ } else if (exprKey === 'group') {
598
+ return isAsyncExpression(expr.group, globals, isAsync);
599
+ }
600
+ return false;
601
+ }
602
+
603
+
552
604
  // Helper function to set variable assignments/uses for a statements array
553
605
  function getVariableAssignmentsAndUses(statements, assigns, uses) {
554
606
  for (const [ixStatement, statement] of statements.entries()) {
@@ -187,9 +187,14 @@ async function executeScriptHelperAsync(script, statements, options, locals) {
187
187
  includeScript.system = true;
188
188
  }
189
189
 
190
+ // Execute the include script
191
+ const includeOptions = {...options};
192
+ includeOptions.urlFn = (url) => urlFileRelative(includeURL, url);
193
+ await executeScriptHelperAsync(includeScript, includeScript.statements, includeOptions, null);
194
+
190
195
  // Run the bare-script linter?
191
196
  if ('logFn' in options && options.debug) {
192
- const warnings = lintScript(includeScript);
197
+ const warnings = lintScript(includeScript, globals);
193
198
  const warningPrefix = `BareScript: Include "${includeURL}" static analysis...`;
194
199
  if (warnings.length) {
195
200
  options.logFn(`${warningPrefix} ${warnings.length} warning${warnings.length > 1 ? 's' : ''}:`);
@@ -198,11 +203,6 @@ async function executeScriptHelperAsync(script, statements, options, locals) {
198
203
  }
199
204
  }
200
205
  }
201
-
202
- // Execute the include script
203
- const includeOptions = {...options};
204
- includeOptions.urlFn = (url) => urlFileRelative(includeURL, url);
205
- await executeScriptHelperAsync(includeScript, includeScript.statements, includeOptions, null);
206
206
  }
207
207
  }
208
208
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "bare-script",
4
- "version": "3.8.2",
4
+ "version": "3.8.3",
5
5
  "description": "BareScript; a lightweight scripting and expression language",
6
6
  "keywords": [
7
7
  "expression",