@weborigami/language 0.3.4-jse.8 → 0.4.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/language",
3
- "version": "0.3.4-jse.8",
3
+ "version": "0.4.0",
4
4
  "description": "Web Origami expression language compiler and runtime",
5
5
  "type": "module",
6
6
  "main": "./main.js",
@@ -11,8 +11,8 @@
11
11
  "typescript": "5.8.2"
12
12
  },
13
13
  "dependencies": {
14
- "@weborigami/async-tree": "0.3.4-jse.8",
15
- "@weborigami/types": "0.3.4-jse.8",
14
+ "@weborigami/async-tree": "0.4.0",
15
+ "@weborigami/types": "0.4.0",
16
16
  "watcher": "2.3.1",
17
17
  "yaml": "2.7.0"
18
18
  },
@@ -56,7 +56,7 @@ export default function optimize(code, options = {}) {
56
56
 
57
57
  case ops.object:
58
58
  const entries = args;
59
- const keys = entries.map(entryKey);
59
+ const keys = entries.map((entry) => entryKey(entry));
60
60
  locals.push(keys);
61
61
  break;
62
62
  }
@@ -70,13 +70,16 @@ export default function optimize(code, options = {}) {
70
70
  } else if (op === ops.object && index > 0) {
71
71
  const [key, value] = child;
72
72
  const adjustedLocals = avoidLocalRecursion(locals, key);
73
- return [
74
- key,
75
- optimize(/** @type {AnnotatedCode} */ (value), {
76
- ...options,
77
- locals: adjustedLocals,
78
- }),
79
- ];
73
+ return annotate(
74
+ [
75
+ key,
76
+ optimize(/** @type {AnnotatedCode} */ (value), {
77
+ ...options,
78
+ locals: adjustedLocals,
79
+ }),
80
+ ],
81
+ child.location
82
+ );
80
83
  } else if (Array.isArray(child) && "location" in child) {
81
84
  // Review: Aside from ops.object (above), what non-instruction arrays
82
85
  // does this descend into?
@@ -191,6 +194,7 @@ function inlineLiteral(code) {
191
194
  function localReference(key, locals, location) {
192
195
  const normalized = trailingSlash.remove(key);
193
196
  const depth = getLocalReferenceDepth(locals, normalized);
197
+ /** @type {any[]} */
194
198
  const context = [ops.context];
195
199
  if (depth > 0) {
196
200
  context.push(depth);
@@ -310,6 +314,7 @@ function resolvePath(code, globals, locals, cache) {
310
314
 
311
315
  function scopeCall(locals, location) {
312
316
  const depth = locals.length;
317
+ /** @type {any[]} */
313
318
  const code = [ops.scope];
314
319
  if (depth > 0) {
315
320
  // Add context for appropriate depth to scope call
@@ -651,6 +651,9 @@ primary
651
651
  program "Origami program"
652
652
  = shebang? @expression
653
653
 
654
+ programMode
655
+ = &{ return options.mode === "program" }
656
+
654
657
  propertyAccess
655
658
  = __ "." __ property:identifierLiteral {
656
659
  return annotate([markers.property, property], location());
@@ -709,7 +712,10 @@ shiftOperator
709
712
  // A shorthand lambda expression: `=foo(_)`
710
713
  shorthandFunction "lambda function"
711
714
  // Avoid a following equal sign (for an equality)
712
- = shellMode "=" !"=" __ definition:implicitParenthesesCallExpression {
715
+ = (shellMode / programMode) "=" !"=" __ definition:implicitParenthesesCallExpression {
716
+ if (options.mode === "program") {
717
+ console.warn("Warning: the shorthand function syntax is deprecated in Origami programs. Use arrow syntax instead.");
718
+ }
713
719
  const lambdaParameters = annotate(
714
720
  [annotate([ops.literal, "_"], location())],
715
721
  location()
@@ -866,8 +872,8 @@ uriKey
866
872
  // A single character in a URI key
867
873
  uriKeyChar
868
874
  // Accept anything that doesn't end the URI key or path
869
- // Note: Peggy doesn't support `/s` so we list space and tab explicitly.
870
- = [^/,\)\]\} \t]
875
+ // Reject whitespace; see notes for `whitespace` term
876
+ = char:[^/,\)\]\}] !&{ return /\s/.test(char); } { return char; }
871
877
  / escapedChar
872
878
 
873
879
  // A slash-separated path of keys: `a/b/c`
@@ -890,10 +896,12 @@ unaryOperator
890
896
  / minus
891
897
 
892
898
  whitespace
899
+ = (whitespaceChar / comment)+
900
+
901
+ whitespaceChar
893
902
  // JavaScript considers a large number of characters whitespace so we use the
894
903
  // `/s` definition to avoid missing any.
895
904
  = char:. &{ return /\s/.test(char); } { return char; }
896
- / comment
897
905
 
898
906
  whitespaceWithNewLine
899
907
  = inlineSpace* comment? newLine __
@@ -205,7 +205,7 @@ function peg$parse(input, options) {
205
205
  var peg$FAILED = {};
206
206
  var peg$source = options.grammarSource;
207
207
 
208
- var peg$startRuleFunctions = { __: peg$parse__, additiveExpression: peg$parseadditiveExpression, additiveOperator: peg$parseadditiveOperator, angleBracketLiteral: peg$parseangleBracketLiteral, angleBracketPath: peg$parseangleBracketPath, angleBracketKey: peg$parseangleBracketKey, angleBracketPathChar: peg$parseangleBracketPathChar, arguments: peg$parsearguments, arrayLiteral: peg$parsearrayLiteral, arrayEntries: peg$parsearrayEntries, arrayEntry: peg$parsearrayEntry, arrowFunction: peg$parsearrowFunction, bitwiseAndExpression: peg$parsebitwiseAndExpression, bitwiseAndOperator: peg$parsebitwiseAndOperator, bitwiseOrExpression: peg$parsebitwiseOrExpression, bitwiseOrOperator: peg$parsebitwiseOrOperator, bitwiseXorExpression: peg$parsebitwiseXorExpression, bitwiseXorOperator: peg$parsebitwiseXorOperator, callExpression: peg$parsecallExpression, commaExpression: peg$parsecommaExpression, comment: peg$parsecomment, computedPropertyAccess: peg$parsecomputedPropertyAccess, computedPropertySpace: peg$parsecomputedPropertySpace, conditionalExpression: peg$parseconditionalExpression, digits: peg$parsedigits, doubleArrow: peg$parsedoubleArrow, doubleQuoteString: peg$parsedoubleQuoteString, doubleQuoteStringChar: peg$parsedoubleQuoteStringChar, ellipsis: peg$parseellipsis, equalityExpression: peg$parseequalityExpression, equalityOperator: peg$parseequalityOperator, escapedChar: peg$parseescapedChar, expectBacktick: peg$parseexpectBacktick, expectClosingBrace: peg$parseexpectClosingBrace, expectClosingBracket: peg$parseexpectClosingBracket, expectClosingParenthesis: peg$parseexpectClosingParenthesis, expectDoubleQuote: peg$parseexpectDoubleQuote, expectExpression: peg$parseexpectExpression, expectFrontDelimiter: peg$parseexpectFrontDelimiter, expectGuillemet: peg$parseexpectGuillemet, expectSingleQuote: peg$parseexpectSingleQuote, expectPipelineExpression: peg$parseexpectPipelineExpression, expectUnaryExpression: peg$parseexpectUnaryExpression, exponentiationExpression: peg$parseexponentiationExpression, expression: peg$parseexpression, floatLiteral: peg$parsefloatLiteral, frontDelimiter: peg$parsefrontDelimiter, frontMatterExpression: peg$parsefrontMatterExpression, frontMatterText: peg$parsefrontMatterText, frontMatterYaml: peg$parsefrontMatterYaml, group: peg$parsegroup, guillemetString: peg$parseguillemetString, guillemetStringChar: peg$parseguillemetStringChar, host: peg$parsehost, hostname: peg$parsehostname, identifier: peg$parseidentifier, identifierLiteral: peg$parseidentifierLiteral, identifierPart: peg$parseidentifierPart, identifierStart: peg$parseidentifierStart, implicitParenthesesCallExpression: peg$parseimplicitParenthesesCallExpression, implicitParensthesesArguments: peg$parseimplicitParensthesesArguments, inlineSpace: peg$parseinlineSpace, integerLiteral: peg$parseintegerLiteral, key: peg$parsekey, keyChar: peg$parsekeyChar, keyCharStart: peg$parsekeyCharStart, list: peg$parselist, logicalAndExpression: peg$parselogicalAndExpression, logicalOrExpression: peg$parselogicalOrExpression, minus: peg$parseminus, multiLineComment: peg$parsemultiLineComment, multiplicativeExpression: peg$parsemultiplicativeExpression, multiplicativeOperator: peg$parsemultiplicativeOperator, newExpression: peg$parsenewExpression, newLine: peg$parsenewLine, numericLiteral: peg$parsenumericLiteral, nullishCoalescingExpression: peg$parsenullishCoalescingExpression, objectLiteral: peg$parseobjectLiteral, objectEntries: peg$parseobjectEntries, objectEntry: peg$parseobjectEntry, objectGetter: peg$parseobjectGetter, objectHiddenKey: peg$parseobjectHiddenKey, objectKey: peg$parseobjectKey, objectProperty: peg$parseobjectProperty, objectShorthandProperty: peg$parseobjectShorthandProperty, objectPublicKey: peg$parseobjectPublicKey, optionalChaining: peg$parseoptionalChaining, parameter: peg$parseparameter, parameterList: peg$parseparameterList, parameterSingleton: peg$parseparameterSingleton, parenthesesArguments: peg$parseparenthesesArguments, pathArguments: peg$parsepathArguments, pathKeys: peg$parsepathKeys, pathLiteral: peg$parsepathLiteral, pathSegment: peg$parsepathSegment, pipelineExpression: peg$parsepipelineExpression, primary: peg$parseprimary, program: peg$parseprogram, propertyAccess: peg$parsepropertyAccess, regexFlags: peg$parseregexFlags, regexLiteral: peg$parseregexLiteral, regexLiteralChar: peg$parseregexLiteralChar, relationalExpression: peg$parserelationalExpression, relationalOperator: peg$parserelationalOperator, separator: peg$parseseparator, shebang: peg$parseshebang, shellMode: peg$parseshellMode, shiftExpression: peg$parseshiftExpression, shiftOperator: peg$parseshiftOperator, shorthandFunction: peg$parseshorthandFunction, singleArrow: peg$parsesingleArrow, singleLineComment: peg$parsesingleLineComment, singleQuoteString: peg$parsesingleQuoteString, singleQuoteStringChar: peg$parsesingleQuoteStringChar, slash: peg$parseslash, slashes: peg$parseslashes, slashFollows: peg$parseslashFollows, spreadElement: peg$parsespreadElement, stringLiteral: peg$parsestringLiteral, templateBody: peg$parsetemplateBody, templateBodyChar: peg$parsetemplateBodyChar, templateBodyText: peg$parsetemplateBodyText, templateDocument: peg$parsetemplateDocument, templateLiteral: peg$parsetemplateLiteral, templateLiteralChar: peg$parsetemplateLiteralChar, templateLiteralText: peg$parsetemplateLiteralText, templateSubstitution: peg$parsetemplateSubstitution, textChar: peg$parsetextChar, unaryExpression: peg$parseunaryExpression, uri: peg$parseuri, uriExpression: peg$parseuriExpression, uriKey: peg$parseuriKey, uriKeyChar: peg$parseuriKeyChar, uriPath: peg$parseuriPath, uriScheme: peg$parseuriScheme, unaryOperator: peg$parseunaryOperator, whitespace: peg$parsewhitespace, whitespaceWithNewLine: peg$parsewhitespaceWithNewLine };
208
+ var peg$startRuleFunctions = { __: peg$parse__, additiveExpression: peg$parseadditiveExpression, additiveOperator: peg$parseadditiveOperator, angleBracketLiteral: peg$parseangleBracketLiteral, angleBracketPath: peg$parseangleBracketPath, angleBracketKey: peg$parseangleBracketKey, angleBracketPathChar: peg$parseangleBracketPathChar, arguments: peg$parsearguments, arrayLiteral: peg$parsearrayLiteral, arrayEntries: peg$parsearrayEntries, arrayEntry: peg$parsearrayEntry, arrowFunction: peg$parsearrowFunction, bitwiseAndExpression: peg$parsebitwiseAndExpression, bitwiseAndOperator: peg$parsebitwiseAndOperator, bitwiseOrExpression: peg$parsebitwiseOrExpression, bitwiseOrOperator: peg$parsebitwiseOrOperator, bitwiseXorExpression: peg$parsebitwiseXorExpression, bitwiseXorOperator: peg$parsebitwiseXorOperator, callExpression: peg$parsecallExpression, commaExpression: peg$parsecommaExpression, comment: peg$parsecomment, computedPropertyAccess: peg$parsecomputedPropertyAccess, computedPropertySpace: peg$parsecomputedPropertySpace, conditionalExpression: peg$parseconditionalExpression, digits: peg$parsedigits, doubleArrow: peg$parsedoubleArrow, doubleQuoteString: peg$parsedoubleQuoteString, doubleQuoteStringChar: peg$parsedoubleQuoteStringChar, ellipsis: peg$parseellipsis, equalityExpression: peg$parseequalityExpression, equalityOperator: peg$parseequalityOperator, escapedChar: peg$parseescapedChar, expectBacktick: peg$parseexpectBacktick, expectClosingBrace: peg$parseexpectClosingBrace, expectClosingBracket: peg$parseexpectClosingBracket, expectClosingParenthesis: peg$parseexpectClosingParenthesis, expectDoubleQuote: peg$parseexpectDoubleQuote, expectExpression: peg$parseexpectExpression, expectFrontDelimiter: peg$parseexpectFrontDelimiter, expectGuillemet: peg$parseexpectGuillemet, expectSingleQuote: peg$parseexpectSingleQuote, expectPipelineExpression: peg$parseexpectPipelineExpression, expectUnaryExpression: peg$parseexpectUnaryExpression, exponentiationExpression: peg$parseexponentiationExpression, expression: peg$parseexpression, floatLiteral: peg$parsefloatLiteral, frontDelimiter: peg$parsefrontDelimiter, frontMatterExpression: peg$parsefrontMatterExpression, frontMatterText: peg$parsefrontMatterText, frontMatterYaml: peg$parsefrontMatterYaml, group: peg$parsegroup, guillemetString: peg$parseguillemetString, guillemetStringChar: peg$parseguillemetStringChar, host: peg$parsehost, hostname: peg$parsehostname, identifier: peg$parseidentifier, identifierLiteral: peg$parseidentifierLiteral, identifierPart: peg$parseidentifierPart, identifierStart: peg$parseidentifierStart, implicitParenthesesCallExpression: peg$parseimplicitParenthesesCallExpression, implicitParensthesesArguments: peg$parseimplicitParensthesesArguments, inlineSpace: peg$parseinlineSpace, integerLiteral: peg$parseintegerLiteral, key: peg$parsekey, keyChar: peg$parsekeyChar, keyCharStart: peg$parsekeyCharStart, list: peg$parselist, logicalAndExpression: peg$parselogicalAndExpression, logicalOrExpression: peg$parselogicalOrExpression, minus: peg$parseminus, multiLineComment: peg$parsemultiLineComment, multiplicativeExpression: peg$parsemultiplicativeExpression, multiplicativeOperator: peg$parsemultiplicativeOperator, newExpression: peg$parsenewExpression, newLine: peg$parsenewLine, numericLiteral: peg$parsenumericLiteral, nullishCoalescingExpression: peg$parsenullishCoalescingExpression, objectLiteral: peg$parseobjectLiteral, objectEntries: peg$parseobjectEntries, objectEntry: peg$parseobjectEntry, objectGetter: peg$parseobjectGetter, objectHiddenKey: peg$parseobjectHiddenKey, objectKey: peg$parseobjectKey, objectProperty: peg$parseobjectProperty, objectShorthandProperty: peg$parseobjectShorthandProperty, objectPublicKey: peg$parseobjectPublicKey, optionalChaining: peg$parseoptionalChaining, parameter: peg$parseparameter, parameterList: peg$parseparameterList, parameterSingleton: peg$parseparameterSingleton, parenthesesArguments: peg$parseparenthesesArguments, pathArguments: peg$parsepathArguments, pathKeys: peg$parsepathKeys, pathLiteral: peg$parsepathLiteral, pathSegment: peg$parsepathSegment, pipelineExpression: peg$parsepipelineExpression, primary: peg$parseprimary, program: peg$parseprogram, programMode: peg$parseprogramMode, propertyAccess: peg$parsepropertyAccess, regexFlags: peg$parseregexFlags, regexLiteral: peg$parseregexLiteral, regexLiteralChar: peg$parseregexLiteralChar, relationalExpression: peg$parserelationalExpression, relationalOperator: peg$parserelationalOperator, separator: peg$parseseparator, shebang: peg$parseshebang, shellMode: peg$parseshellMode, shiftExpression: peg$parseshiftExpression, shiftOperator: peg$parseshiftOperator, shorthandFunction: peg$parseshorthandFunction, singleArrow: peg$parsesingleArrow, singleLineComment: peg$parsesingleLineComment, singleQuoteString: peg$parsesingleQuoteString, singleQuoteStringChar: peg$parsesingleQuoteStringChar, slash: peg$parseslash, slashes: peg$parseslashes, slashFollows: peg$parseslashFollows, spreadElement: peg$parsespreadElement, stringLiteral: peg$parsestringLiteral, templateBody: peg$parsetemplateBody, templateBodyChar: peg$parsetemplateBodyChar, templateBodyText: peg$parsetemplateBodyText, templateDocument: peg$parsetemplateDocument, templateLiteral: peg$parsetemplateLiteral, templateLiteralChar: peg$parsetemplateLiteralChar, templateLiteralText: peg$parsetemplateLiteralText, templateSubstitution: peg$parsetemplateSubstitution, textChar: peg$parsetextChar, unaryExpression: peg$parseunaryExpression, uri: peg$parseuri, uriExpression: peg$parseuriExpression, uriKey: peg$parseuriKey, uriKeyChar: peg$parseuriKeyChar, uriPath: peg$parseuriPath, uriScheme: peg$parseuriScheme, unaryOperator: peg$parseunaryOperator, whitespace: peg$parsewhitespace, whitespaceChar: peg$parsewhitespaceChar, whitespaceWithNewLine: peg$parsewhitespaceWithNewLine };
209
209
  var peg$startRuleFunction = peg$parse__;
210
210
 
211
211
  var peg$c0 = "+";
@@ -285,7 +285,7 @@ function peg$parse(input, options) {
285
285
  var peg$r7 = /^[gimuy]/;
286
286
  var peg$r8 = /^[^\/\n\r]/;
287
287
  var peg$r9 = /^[^\n\r]/;
288
- var peg$r10 = /^[^\/,)\]} \t]/;
288
+ var peg$r10 = /^[^\/,)\]}]/;
289
289
  var peg$r11 = /^[a-z]/;
290
290
  var peg$r12 = /^[a-z0-9+-.]/;
291
291
  var peg$r13 = /^[:]/;
@@ -399,7 +399,7 @@ function peg$parse(input, options) {
399
399
  var peg$e105 = peg$otherExpectation("template document");
400
400
  var peg$e106 = peg$otherExpectation("template literal");
401
401
  var peg$e107 = peg$otherExpectation("template substitution");
402
- var peg$e108 = peg$classExpectation(["/", ",", ")", "]", "}", " ", "\t"], true, false);
402
+ var peg$e108 = peg$classExpectation(["/", ",", ")", "]", "}"], true, false);
403
403
  var peg$e109 = peg$otherExpectation("slash-separated path");
404
404
  var peg$e110 = peg$classExpectation([["a", "z"]], false, false);
405
405
  var peg$e111 = peg$classExpectation([["a", "z"], ["0", "9"], ["+", "."]], false, false);
@@ -684,54 +684,58 @@ function peg$parse(input, options) {
684
684
  location()
685
685
  );
686
686
  };
687
- var peg$f83 = function(property) {
687
+ var peg$f83 = function() { return options.mode === "program" };
688
+ var peg$f84 = function(property) {
688
689
  return annotate([markers.property, property], location());
689
690
  };
690
- var peg$f84 = function(flags) {
691
+ var peg$f85 = function(flags) {
691
692
  return flags.join("");
692
693
  };
693
- var peg$f85 = function(chars, flags) {
694
+ var peg$f86 = function(chars, flags) {
694
695
  const regex = new RegExp(chars.join(""), flags);
695
696
  return annotate([ops.literal, regex], location());
696
697
  };
697
- var peg$f86 = function(head, tail) {
698
+ var peg$f87 = function(head, tail) {
698
699
  return tail.reduce(makeBinaryOperation, head);
699
700
  };
700
- var peg$f87 = function() { return null; };
701
- var peg$f88 = function() { return options.mode === "shell" };
702
- var peg$f89 = function(head, tail) {
701
+ var peg$f88 = function() { return null; };
702
+ var peg$f89 = function() { return options.mode === "shell" };
703
+ var peg$f90 = function(head, tail) {
703
704
  return tail.reduce(makeBinaryOperation, head);
704
705
  };
705
- var peg$f90 = function(definition) {
706
+ var peg$f91 = function(definition) {
707
+ if (options.mode === "program") {
708
+ console.warn("Warning: the shorthand function syntax is deprecated in Origami programs. Use arrow syntax instead.");
709
+ }
706
710
  const lambdaParameters = annotate(
707
711
  [annotate([ops.literal, "_"], location())],
708
712
  location()
709
713
  );
710
714
  return annotate([ops.lambda, lambdaParameters, definition], location());
711
715
  };
712
- var peg$f91 = function() { return null; };
713
- var peg$f92 = function(chars) {
716
+ var peg$f92 = function() { return null; };
717
+ var peg$f93 = function(chars) {
714
718
  return annotate([ops.literal, chars.join("")], location());
715
719
  };
716
- var peg$f93 = function() {
720
+ var peg$f94 = function() {
717
721
  return annotate([ops.literal, "/"], location());
718
722
  };
719
- var peg$f94 = function() {
723
+ var peg$f95 = function() {
720
724
  return annotate([ops.literal, "/"], location());
721
725
  };
722
- var peg$f95 = function() {
726
+ var peg$f96 = function() {
723
727
  return true;
724
728
  };
725
- var peg$f96 = function(value) {
729
+ var peg$f97 = function(value) {
726
730
  return annotate([ops.spread, value], location());
727
731
  };
728
- var peg$f97 = function(head, tail) {
732
+ var peg$f98 = function(head, tail) {
729
733
  return makeTemplate(ops.templateIndent, head, tail, location());
730
734
  };
731
- var peg$f98 = function(chars) {
735
+ var peg$f99 = function(chars) {
732
736
  return annotate([ops.literal, chars.join("")], location());
733
737
  };
734
- var peg$f99 = function(front, body) {
738
+ var peg$f100 = function(front, body) {
735
739
  // TODO: Deprecate @template
736
740
  const macroName = text().includes("@template") ? "@template" : "_template";
737
741
  if (macroName === "@template") {
@@ -740,10 +744,10 @@ function peg$parse(input, options) {
740
744
  }
741
745
  return annotate(applyMacro(front, macroName, body), location());
742
746
  };
743
- var peg$f100 = function(front, body) {
747
+ var peg$f101 = function(front, body) {
744
748
  return makeDocument(front, body, location());
745
749
  };
746
- var peg$f101 = function(body) {
750
+ var peg$f102 = function(body) {
747
751
  if (options.front) {
748
752
  return makeDocument(options.front, body, location());
749
753
  }
@@ -753,41 +757,43 @@ function peg$parse(input, options) {
753
757
  );
754
758
  return annotate([ops.lambda, lambdaParameters, body], location());
755
759
  };
756
- var peg$f102 = function(head, tail) {
760
+ var peg$f103 = function(head, tail) {
757
761
  return makeTemplate(ops.templateTree, head, tail, location());
758
762
  };
759
- var peg$f103 = function(chars) {
763
+ var peg$f104 = function(chars) {
760
764
  return annotate([ops.literal, chars.join("")], location());
761
765
  };
762
- var peg$f104 = function(expression) {
766
+ var peg$f105 = function(expression) {
763
767
  return annotate(expression, location());
764
768
  };
765
- var peg$f105 = function(operator, expression) {
769
+ var peg$f106 = function(operator, expression) {
766
770
  return makeUnaryOperation(operator, expression, location());
767
771
  };
768
- var peg$f106 = function(scheme, host, path) {
772
+ var peg$f107 = function(scheme, host, path) {
769
773
  const rest = path ? path[1] : [];
770
774
  const keys = annotate([host, ...rest], location());
771
775
  return makeCall(scheme, keys, location());
772
776
  };
773
- var peg$f107 = function(scheme, keys) {
777
+ var peg$f108 = function(scheme, keys) {
774
778
  return makeCall(scheme, keys, location());
775
779
  };
776
- var peg$f108 = function(chars) {
780
+ var peg$f109 = function(chars) {
777
781
  return annotate([ops.literal, text()], location());
778
782
  };
779
- var peg$f109 = function() {
783
+ var peg$f110 = function() {
780
784
  // A single slash is a path key
781
785
  return annotate([ops.literal, ""], location());
782
786
  };
783
- var peg$f110 = function(keys) {
787
+ var peg$f111 = function(char) { return /\s/.test(char); };
788
+ var peg$f112 = function(char) { return char; };
789
+ var peg$f113 = function(keys) {
784
790
  return annotate(keys, location());
785
791
  };
786
- var peg$f111 = function() {
792
+ var peg$f114 = function() {
787
793
  return annotate([markers.global, text()], location());
788
794
  };
789
- var peg$f112 = function(char) { return /\s/.test(char); };
790
- var peg$f113 = function(char) { return char; };
795
+ var peg$f115 = function(char) { return /\s/.test(char); };
796
+ var peg$f116 = function(char) { return char; };
791
797
  var peg$currPos = options.peg$currPos | 0;
792
798
  var peg$savedPos = peg$currPos;
793
799
  var peg$posDetailsCache = [{ line: 1, column: 1 }];
@@ -4828,6 +4834,20 @@ function peg$parse(input, options) {
4828
4834
  return s0;
4829
4835
  }
4830
4836
 
4837
+ function peg$parseprogramMode() {
4838
+ var s0;
4839
+
4840
+ peg$savedPos = peg$currPos;
4841
+ s0 = peg$f83();
4842
+ if (s0) {
4843
+ s0 = undefined;
4844
+ } else {
4845
+ s0 = peg$FAILED;
4846
+ }
4847
+
4848
+ return s0;
4849
+ }
4850
+
4831
4851
  function peg$parsepropertyAccess() {
4832
4852
  var s0, s1, s2, s3, s4;
4833
4853
 
@@ -4845,7 +4865,7 @@ function peg$parse(input, options) {
4845
4865
  s4 = peg$parseidentifierLiteral();
4846
4866
  if (s4 !== peg$FAILED) {
4847
4867
  peg$savedPos = s0;
4848
- s0 = peg$f83(s4);
4868
+ s0 = peg$f84(s4);
4849
4869
  } else {
4850
4870
  peg$currPos = s0;
4851
4871
  s0 = peg$FAILED;
@@ -4881,7 +4901,7 @@ function peg$parse(input, options) {
4881
4901
  }
4882
4902
  }
4883
4903
  peg$savedPos = s0;
4884
- s1 = peg$f84(s1);
4904
+ s1 = peg$f85(s1);
4885
4905
  s0 = s1;
4886
4906
 
4887
4907
  return s0;
@@ -4915,7 +4935,7 @@ function peg$parse(input, options) {
4915
4935
  if (s3 !== peg$FAILED) {
4916
4936
  s4 = peg$parseregexFlags();
4917
4937
  peg$savedPos = s0;
4918
- s0 = peg$f85(s2, s4);
4938
+ s0 = peg$f86(s2, s4);
4919
4939
  } else {
4920
4940
  peg$currPos = s0;
4921
4941
  s0 = peg$FAILED;
@@ -4998,7 +5018,7 @@ function peg$parse(input, options) {
4998
5018
  }
4999
5019
  }
5000
5020
  peg$savedPos = s0;
5001
- s0 = peg$f86(s1, s2);
5021
+ s0 = peg$f87(s1, s2);
5002
5022
  } else {
5003
5023
  peg$currPos = s0;
5004
5024
  s0 = peg$FAILED;
@@ -5113,7 +5133,7 @@ function peg$parse(input, options) {
5113
5133
  }
5114
5134
  }
5115
5135
  peg$savedPos = s0;
5116
- s0 = peg$f87();
5136
+ s0 = peg$f88();
5117
5137
  } else {
5118
5138
  peg$currPos = s0;
5119
5139
  s0 = peg$FAILED;
@@ -5126,7 +5146,7 @@ function peg$parse(input, options) {
5126
5146
  var s0;
5127
5147
 
5128
5148
  peg$savedPos = peg$currPos;
5129
- s0 = peg$f88();
5149
+ s0 = peg$f89();
5130
5150
  if (s0) {
5131
5151
  s0 = undefined;
5132
5152
  } else {
@@ -5179,7 +5199,7 @@ function peg$parse(input, options) {
5179
5199
  }
5180
5200
  }
5181
5201
  peg$savedPos = s0;
5182
- s0 = peg$f89(s1, s2);
5202
+ s0 = peg$f90(s1, s2);
5183
5203
  } else {
5184
5204
  peg$currPos = s0;
5185
5205
  s0 = peg$FAILED;
@@ -5226,6 +5246,9 @@ function peg$parse(input, options) {
5226
5246
  peg$silentFails++;
5227
5247
  s0 = peg$currPos;
5228
5248
  s1 = peg$parseshellMode();
5249
+ if (s1 === peg$FAILED) {
5250
+ s1 = peg$parseprogramMode();
5251
+ }
5229
5252
  if (s1 !== peg$FAILED) {
5230
5253
  if (input.charCodeAt(peg$currPos) === 61) {
5231
5254
  s2 = peg$c54;
@@ -5256,7 +5279,7 @@ function peg$parse(input, options) {
5256
5279
  s5 = peg$parseimplicitParenthesesCallExpression();
5257
5280
  if (s5 !== peg$FAILED) {
5258
5281
  peg$savedPos = s0;
5259
- s0 = peg$f90(s5);
5282
+ s0 = peg$f91(s5);
5260
5283
  } else {
5261
5284
  peg$currPos = s0;
5262
5285
  s0 = peg$FAILED;
@@ -5339,7 +5362,7 @@ function peg$parse(input, options) {
5339
5362
  }
5340
5363
  }
5341
5364
  peg$savedPos = s0;
5342
- s0 = peg$f91();
5365
+ s0 = peg$f92();
5343
5366
  } else {
5344
5367
  peg$currPos = s0;
5345
5368
  s0 = peg$FAILED;
@@ -5370,7 +5393,7 @@ function peg$parse(input, options) {
5370
5393
  s3 = peg$parseexpectSingleQuote();
5371
5394
  if (s3 !== peg$FAILED) {
5372
5395
  peg$savedPos = s0;
5373
- s0 = peg$f92(s2);
5396
+ s0 = peg$f93(s2);
5374
5397
  } else {
5375
5398
  peg$currPos = s0;
5376
5399
  s0 = peg$FAILED;
@@ -5434,7 +5457,7 @@ function peg$parse(input, options) {
5434
5457
  s1 = peg$parseslashFollows();
5435
5458
  if (s1 !== peg$FAILED) {
5436
5459
  peg$savedPos = s0;
5437
- s1 = peg$f93();
5460
+ s1 = peg$f94();
5438
5461
  }
5439
5462
  s0 = s1;
5440
5463
 
@@ -5469,7 +5492,7 @@ function peg$parse(input, options) {
5469
5492
  }
5470
5493
  if (s1 !== peg$FAILED) {
5471
5494
  peg$savedPos = s0;
5472
- s1 = peg$f94();
5495
+ s1 = peg$f95();
5473
5496
  }
5474
5497
  s0 = s1;
5475
5498
 
@@ -5498,7 +5521,7 @@ function peg$parse(input, options) {
5498
5521
  }
5499
5522
  if (s1 !== peg$FAILED) {
5500
5523
  peg$savedPos = s0;
5501
- s1 = peg$f95();
5524
+ s1 = peg$f96();
5502
5525
  }
5503
5526
  s0 = s1;
5504
5527
 
@@ -5515,7 +5538,7 @@ function peg$parse(input, options) {
5515
5538
  s3 = peg$parseexpectPipelineExpression();
5516
5539
  if (s3 !== peg$FAILED) {
5517
5540
  peg$savedPos = s0;
5518
- s0 = peg$f96(s3);
5541
+ s0 = peg$f97(s3);
5519
5542
  } else {
5520
5543
  peg$currPos = s0;
5521
5544
  s0 = peg$FAILED;
@@ -5592,7 +5615,7 @@ function peg$parse(input, options) {
5592
5615
  }
5593
5616
  }
5594
5617
  peg$savedPos = s0;
5595
- s0 = peg$f97(s1, s2);
5618
+ s0 = peg$f98(s1, s2);
5596
5619
  peg$silentFails--;
5597
5620
  s1 = peg$FAILED;
5598
5621
  if (peg$silentFails === 0) { peg$fail(peg$e102); }
@@ -5648,7 +5671,7 @@ function peg$parse(input, options) {
5648
5671
  s2 = peg$parsetemplateBodyChar();
5649
5672
  }
5650
5673
  peg$savedPos = s0;
5651
- s1 = peg$f98(s1);
5674
+ s1 = peg$f99(s1);
5652
5675
  s0 = s1;
5653
5676
  peg$silentFails--;
5654
5677
  s1 = peg$FAILED;
@@ -5667,7 +5690,7 @@ function peg$parse(input, options) {
5667
5690
  s2 = peg$parse__();
5668
5691
  s3 = peg$parsetemplateBody();
5669
5692
  peg$savedPos = s0;
5670
- s0 = peg$f99(s1, s3);
5693
+ s0 = peg$f100(s1, s3);
5671
5694
  } else {
5672
5695
  peg$currPos = s0;
5673
5696
  s0 = peg$FAILED;
@@ -5678,7 +5701,7 @@ function peg$parse(input, options) {
5678
5701
  if (s1 !== peg$FAILED) {
5679
5702
  s2 = peg$parsetemplateBody();
5680
5703
  peg$savedPos = s0;
5681
- s0 = peg$f100(s1, s2);
5704
+ s0 = peg$f101(s1, s2);
5682
5705
  } else {
5683
5706
  peg$currPos = s0;
5684
5707
  s0 = peg$FAILED;
@@ -5687,7 +5710,7 @@ function peg$parse(input, options) {
5687
5710
  s0 = peg$currPos;
5688
5711
  s1 = peg$parsetemplateBody();
5689
5712
  peg$savedPos = s0;
5690
- s1 = peg$f101(s1);
5713
+ s1 = peg$f102(s1);
5691
5714
  s0 = s1;
5692
5715
  }
5693
5716
  }
@@ -5741,7 +5764,7 @@ function peg$parse(input, options) {
5741
5764
  s4 = peg$parseexpectBacktick();
5742
5765
  if (s4 !== peg$FAILED) {
5743
5766
  peg$savedPos = s0;
5744
- s0 = peg$f102(s2, s3);
5767
+ s0 = peg$f103(s2, s3);
5745
5768
  } else {
5746
5769
  peg$currPos = s0;
5747
5770
  s0 = peg$FAILED;
@@ -5815,7 +5838,7 @@ function peg$parse(input, options) {
5815
5838
  s2 = peg$parsetemplateLiteralChar();
5816
5839
  }
5817
5840
  peg$savedPos = s0;
5818
- s1 = peg$f103(s1);
5841
+ s1 = peg$f104(s1);
5819
5842
  s0 = s1;
5820
5843
 
5821
5844
  return s0;
@@ -5845,7 +5868,7 @@ function peg$parse(input, options) {
5845
5868
  }
5846
5869
  if (s3 !== peg$FAILED) {
5847
5870
  peg$savedPos = s0;
5848
- s0 = peg$f104(s2);
5871
+ s0 = peg$f105(s2);
5849
5872
  } else {
5850
5873
  peg$currPos = s0;
5851
5874
  s0 = peg$FAILED;
@@ -5894,7 +5917,7 @@ function peg$parse(input, options) {
5894
5917
  s3 = peg$parseexpectUnaryExpression();
5895
5918
  if (s3 !== peg$FAILED) {
5896
5919
  peg$savedPos = s0;
5897
- s0 = peg$f105(s1, s3);
5920
+ s0 = peg$f106(s1, s3);
5898
5921
  } else {
5899
5922
  peg$currPos = s0;
5900
5923
  s0 = peg$FAILED;
@@ -5951,7 +5974,7 @@ function peg$parse(input, options) {
5951
5974
  s4 = null;
5952
5975
  }
5953
5976
  peg$savedPos = s0;
5954
- s0 = peg$f106(s1, s3, s4);
5977
+ s0 = peg$f107(s1, s3, s4);
5955
5978
  } else {
5956
5979
  peg$currPos = s0;
5957
5980
  s0 = peg$FAILED;
@@ -5971,7 +5994,7 @@ function peg$parse(input, options) {
5971
5994
  s2 = peg$parsepathKeys();
5972
5995
  if (s2 !== peg$FAILED) {
5973
5996
  peg$savedPos = s0;
5974
- s0 = peg$f107(s1, s2);
5997
+ s0 = peg$f108(s1, s2);
5975
5998
  } else {
5976
5999
  peg$currPos = s0;
5977
6000
  s0 = peg$FAILED;
@@ -6025,7 +6048,7 @@ function peg$parse(input, options) {
6025
6048
  s2 = null;
6026
6049
  }
6027
6050
  peg$savedPos = s0;
6028
- s0 = peg$f108(s1);
6051
+ s0 = peg$f109(s1);
6029
6052
  } else {
6030
6053
  peg$currPos = s0;
6031
6054
  s0 = peg$FAILED;
@@ -6041,7 +6064,7 @@ function peg$parse(input, options) {
6041
6064
  }
6042
6065
  if (s1 !== peg$FAILED) {
6043
6066
  peg$savedPos = s0;
6044
- s1 = peg$f109();
6067
+ s1 = peg$f110();
6045
6068
  }
6046
6069
  s0 = s1;
6047
6070
  }
@@ -6050,15 +6073,44 @@ function peg$parse(input, options) {
6050
6073
  }
6051
6074
 
6052
6075
  function peg$parseuriKeyChar() {
6053
- var s0;
6076
+ var s0, s1, s2, s3;
6054
6077
 
6055
- s0 = input.charAt(peg$currPos);
6056
- if (peg$r10.test(s0)) {
6078
+ s0 = peg$currPos;
6079
+ s1 = input.charAt(peg$currPos);
6080
+ if (peg$r10.test(s1)) {
6057
6081
  peg$currPos++;
6058
6082
  } else {
6059
- s0 = peg$FAILED;
6083
+ s1 = peg$FAILED;
6060
6084
  if (peg$silentFails === 0) { peg$fail(peg$e108); }
6061
6085
  }
6086
+ if (s1 !== peg$FAILED) {
6087
+ s2 = peg$currPos;
6088
+ peg$silentFails++;
6089
+ peg$savedPos = peg$currPos;
6090
+ s3 = peg$f111(s1);
6091
+ if (s3) {
6092
+ s3 = undefined;
6093
+ } else {
6094
+ s3 = peg$FAILED;
6095
+ }
6096
+ peg$silentFails--;
6097
+ if (s3 === peg$FAILED) {
6098
+ s2 = undefined;
6099
+ } else {
6100
+ peg$currPos = s2;
6101
+ s2 = peg$FAILED;
6102
+ }
6103
+ if (s2 !== peg$FAILED) {
6104
+ peg$savedPos = s0;
6105
+ s0 = peg$f112(s1);
6106
+ } else {
6107
+ peg$currPos = s0;
6108
+ s0 = peg$FAILED;
6109
+ }
6110
+ } else {
6111
+ peg$currPos = s0;
6112
+ s0 = peg$FAILED;
6113
+ }
6062
6114
  if (s0 === peg$FAILED) {
6063
6115
  s0 = peg$parseescapedChar();
6064
6116
  }
@@ -6086,7 +6138,7 @@ function peg$parse(input, options) {
6086
6138
  }
6087
6139
  if (s1 !== peg$FAILED) {
6088
6140
  peg$savedPos = s0;
6089
- s1 = peg$f110(s1);
6141
+ s1 = peg$f113(s1);
6090
6142
  }
6091
6143
  s0 = s1;
6092
6144
  peg$silentFails--;
@@ -6137,7 +6189,7 @@ function peg$parse(input, options) {
6137
6189
  }
6138
6190
  if (s3 !== peg$FAILED) {
6139
6191
  peg$savedPos = s0;
6140
- s0 = peg$f111();
6192
+ s0 = peg$f114();
6141
6193
  } else {
6142
6194
  peg$currPos = s0;
6143
6195
  s0 = peg$FAILED;
@@ -6205,6 +6257,29 @@ function peg$parse(input, options) {
6205
6257
  }
6206
6258
 
6207
6259
  function peg$parsewhitespace() {
6260
+ var s0, s1;
6261
+
6262
+ s0 = [];
6263
+ s1 = peg$parsewhitespaceChar();
6264
+ if (s1 === peg$FAILED) {
6265
+ s1 = peg$parsecomment();
6266
+ }
6267
+ if (s1 !== peg$FAILED) {
6268
+ while (s1 !== peg$FAILED) {
6269
+ s0.push(s1);
6270
+ s1 = peg$parsewhitespaceChar();
6271
+ if (s1 === peg$FAILED) {
6272
+ s1 = peg$parsecomment();
6273
+ }
6274
+ }
6275
+ } else {
6276
+ s0 = peg$FAILED;
6277
+ }
6278
+
6279
+ return s0;
6280
+ }
6281
+
6282
+ function peg$parsewhitespaceChar() {
6208
6283
  var s0, s1, s2;
6209
6284
 
6210
6285
  s0 = peg$currPos;
@@ -6217,7 +6292,7 @@ function peg$parse(input, options) {
6217
6292
  }
6218
6293
  if (s1 !== peg$FAILED) {
6219
6294
  peg$savedPos = peg$currPos;
6220
- s2 = peg$f112(s1);
6295
+ s2 = peg$f115(s1);
6221
6296
  if (s2) {
6222
6297
  s2 = undefined;
6223
6298
  } else {
@@ -6225,7 +6300,7 @@ function peg$parse(input, options) {
6225
6300
  }
6226
6301
  if (s2 !== peg$FAILED) {
6227
6302
  peg$savedPos = s0;
6228
- s0 = peg$f113(s1);
6303
+ s0 = peg$f116(s1);
6229
6304
  } else {
6230
6305
  peg$currPos = s0;
6231
6306
  s0 = peg$FAILED;
@@ -6234,9 +6309,6 @@ function peg$parse(input, options) {
6234
6309
  peg$currPos = s0;
6235
6310
  s0 = peg$FAILED;
6236
6311
  }
6237
- if (s0 === peg$FAILED) {
6238
- s0 = peg$parsecomment();
6239
- }
6240
6312
 
6241
6313
  return s0;
6242
6314
  }
@@ -6395,6 +6467,7 @@ const peg$allowedStartRules = [
6395
6467
  "pipelineExpression",
6396
6468
  "primary",
6397
6469
  "program",
6470
+ "programMode",
6398
6471
  "propertyAccess",
6399
6472
  "regexFlags",
6400
6473
  "regexLiteral",
@@ -6434,6 +6507,7 @@ const peg$allowedStartRules = [
6434
6507
  "uriScheme",
6435
6508
  "unaryOperator",
6436
6509
  "whitespace",
6510
+ "whitespaceChar",
6437
6511
  "whitespaceWithNewLine"
6438
6512
  ];
6439
6513
 
@@ -28,7 +28,7 @@ export const markers = {
28
28
  * If a parse result is an object that will be evaluated at runtime, attach the
29
29
  * location of the source code that produced it for debugging and error messages.
30
30
  *
31
- * @param {Code[]} code
31
+ * @param {any[]} code
32
32
  * @param {CodeLocation} location
33
33
  */
34
34
  export function annotate(code, location) {
@@ -375,11 +375,12 @@ export function makePath(keys) {
375
375
  const reference = annotate([markers.reference, headKey], head.location);
376
376
 
377
377
  let code = [markers.traverse, reference, ...tail];
378
- code.location = spanLocations(code);
378
+ const location = spanLocations(code);
379
+ code = annotate(code, location);
379
380
 
380
381
  // Last key has trailing slash implies unpack operation
381
382
  if (trailingSlash.has(args.at(-1)[1])) {
382
- code = annotate([ops.unpack, code], code.location);
383
+ code = annotate([ops.unpack, code], location);
383
384
  }
384
385
 
385
386
  return code;
@@ -6,5 +6,5 @@ export default function getHandlers(tree) {
6
6
  return null;
7
7
  }
8
8
  const root = Tree.root(tree);
9
- return root.handlers;
9
+ return /** @type {any} */ (root).handlers;
10
10
  }
@@ -12,22 +12,46 @@ import path from "node:path";
12
12
  * Fetch API
13
13
  * URL API
14
14
  */
15
- export default {
15
+ const globals = {
16
+ AbortController,
17
+ AbortSignal,
16
18
  AggregateError,
17
19
  Array,
18
20
  ArrayBuffer,
21
+ // @ts-ignore this exists despite what TypeScript thinks
22
+ AsyncDisposableStack,
19
23
  Atomics,
20
24
  BigInt,
21
25
  BigInt64Array,
22
26
  BigUint64Array,
27
+ Blob,
23
28
  Boolean,
29
+ BroadcastChannel,
30
+ Buffer,
31
+ ByteLengthQueuingStrategy,
32
+ CloseEvent,
33
+ CompressionStream,
34
+ CountQueuingStrategy,
35
+ Crypto,
36
+ CryptoKey,
37
+ CustomEvent,
38
+ DOMException,
24
39
  DataView,
25
40
  Date,
41
+ DecompressionStream,
42
+ // @ts-ignore this exists despite what TypeScript thinks
43
+ DisposableStack,
26
44
  Error,
27
45
  EvalError,
46
+ Event,
47
+ EventTarget,
48
+ File,
28
49
  FinalizationRegistry,
50
+ // @ts-ignore this exists despite what TypeScript thinks
51
+ Float16Array,
29
52
  Float32Array,
30
53
  Float64Array,
54
+ FormData,
31
55
  Function,
32
56
  Headers,
33
57
  Infinity,
@@ -35,17 +59,33 @@ export default {
35
59
  Int32Array,
36
60
  Int8Array,
37
61
  Intl,
38
- // @ts-ignore Iterator does exist despite what TypeScript thinks
62
+ // @ts-ignore this exists despite what TypeScript thinks
39
63
  Iterator,
40
64
  JSON,
41
65
  Map,
42
66
  Math,
67
+ MessageChannel,
68
+ MessageEvent,
69
+ MessagePort,
43
70
  NaN,
44
71
  Number,
45
72
  Object,
73
+ Performance,
74
+ PerformanceEntry,
75
+ PerformanceMark,
76
+ PerformanceMeasure,
77
+ PerformanceObserver,
78
+ PerformanceObserverEntryList,
79
+ PerformanceResourceTiming,
46
80
  Promise,
47
81
  Proxy,
48
82
  RangeError,
83
+ ReadableByteStreamController,
84
+ ReadableStream,
85
+ ReadableStreamBYOBReader,
86
+ ReadableStreamBYOBRequest,
87
+ ReadableStreamDefaultController,
88
+ ReadableStreamDefaultReader,
49
89
  ReferenceError,
50
90
  Reflect,
51
91
  RegExp,
@@ -54,10 +94,23 @@ export default {
54
94
  Set,
55
95
  SharedArrayBuffer,
56
96
  String,
97
+ SubtleCrypto,
98
+ // @ts-ignore this exists despite what TypeScript thinks
99
+ SuppressedError,
57
100
  Symbol,
58
101
  SyntaxError,
102
+ TextDecoder,
103
+ TextDecoderStream,
104
+ TextEncoder,
105
+ TextEncoderStream,
106
+ TransformStream,
107
+ TransformStreamDefaultController,
59
108
  TypeError,
60
109
  URIError,
110
+ URL,
111
+ // @ts-ignore this exists despite what TypeScript thinks
112
+ URLPattern,
113
+ URLSearchParams,
61
114
  Uint16Array,
62
115
  Uint32Array,
63
116
  Uint8Array,
@@ -65,24 +118,58 @@ export default {
65
118
  WeakMap,
66
119
  WeakRef,
67
120
  WeakSet,
121
+ WebAssembly,
122
+ WebSocket,
123
+ WritableStream,
124
+ WritableStreamDefaultController,
125
+ WritableStreamDefaultWriter,
126
+ atob,
127
+ btoa,
128
+ clearImmediate,
129
+ clearInterval,
130
+ clearTimeout,
131
+ console,
132
+ crypto,
68
133
  decodeURI,
69
134
  decodeURIComponent,
70
135
  encodeURI,
71
136
  encodeURIComponent,
137
+ escape,
72
138
  eval,
73
- false: false, // treat like a global
74
- fetch: fetchWrapper, // special case
139
+ // fetch -- special case, see below
75
140
  globalThis,
76
- import: importWrapper, // not a function in JS but acts like one
77
141
  isFinite,
78
142
  isNaN,
79
- null: null, // treat like a global
80
143
  parseFloat,
81
144
  parseInt,
82
- true: true, // treat like a global
145
+ performance,
146
+ process,
147
+ queueMicrotask,
148
+ setImmediate,
149
+ setInterval,
150
+ setTimeout,
151
+ structuredClone,
83
152
  undefined,
153
+ unescape,
154
+
155
+ // Treat these like globals
156
+ false: false,
157
+ null: null,
158
+ true: true,
159
+
160
+ // Special cases
161
+ fetch: fetchWrapper,
162
+ import: importWrapper,
84
163
  };
85
164
 
165
+ // Give access to our own custom globals as `globalThis`
166
+ Object.defineProperty(globals, "globalThis", {
167
+ enumerable: true,
168
+ value: globals,
169
+ });
170
+
171
+ export default globals;
172
+
86
173
  async function fetchWrapper(resource, options) {
87
174
  const response = await fetch(resource, options);
88
175
  return response.ok ? await response.arrayBuffer() : undefined;
@@ -99,13 +99,18 @@ cache.unevaluatedArgs = true;
99
99
  /**
100
100
  * JavaScript comma operator, returns the last argument.
101
101
  *
102
- * @param {...any} args
103
- * @returns
102
+ * @this {AsyncTree|null}
103
+ * @param {...AnnotatedCode} args
104
104
  */
105
- export function comma(...args) {
106
- return args.at(-1);
105
+ export async function comma(...args) {
106
+ let result;
107
+ for (const arg of args) {
108
+ result = await evaluate.call(this, arg);
109
+ }
110
+ return result;
107
111
  }
108
112
  addOpLabel(comma, "«ops.comma»");
113
+ comma.unevaluatedArgs = true;
109
114
 
110
115
  /**
111
116
  * Concatenate the given arguments.
@@ -204,7 +209,7 @@ addOpLabel(greaterThanOrEqual, "«ops.greaterThanOrEqual»");
204
209
  export async function homeDirectory(...keys) {
205
210
  const tree = new OrigamiFiles(os.homedir());
206
211
  // Use the same handlers as the current tree
207
- tree.handlers = getHandlers(this);
212
+ /** @type {any} */ (tree).handlers = getHandlers(this);
208
213
  return keys.length > 0 ? Tree.traverse(tree, ...keys) : tree;
209
214
  }
210
215
  addOpLabel(homeDirectory, "«ops.homeDirectory»");
@@ -424,7 +429,7 @@ addOpLabel(remainder, "«ops.remainder»");
424
429
  export async function rootDirectory(...keys) {
425
430
  const tree = new OrigamiFiles("/");
426
431
  // Use the same handlers as the current tree
427
- tree.handlers = getHandlers(this);
432
+ /** @type {any} */ (tree).handlers = getHandlers(this);
428
433
  return keys.length > 0 ? Tree.traverse(tree, ...keys) : tree;
429
434
  }
430
435
  addOpLabel(rootDirectory, "«ops.rootDirectory»");
@@ -7,6 +7,15 @@ export function assertCodeEqual(actual, expected) {
7
7
  assert.deepStrictEqual(actualStripped, expectedStripped);
8
8
  }
9
9
 
10
+ export function assertCodeLocations(code) {
11
+ assert(code.location, "no location");
12
+ for (const item of code) {
13
+ if (Array.isArray(item)) {
14
+ assertCodeLocations(item);
15
+ }
16
+ }
17
+ }
18
+
10
19
  /**
11
20
  * Adds a fake source to code.
12
21
  *
@@ -4,7 +4,11 @@ import * as compile from "../../src/compiler/compile.js";
4
4
  import optimize from "../../src/compiler/optimize.js";
5
5
  import { markers } from "../../src/compiler/parserHelpers.js";
6
6
  import { ops } from "../../src/runtime/internal.js";
7
- import { assertCodeEqual, createCode } from "./codeHelpers.js";
7
+ import {
8
+ assertCodeEqual,
9
+ assertCodeLocations,
10
+ createCode,
11
+ } from "./codeHelpers.js";
8
12
 
9
13
  describe("optimize", () => {
10
14
  test("change local references to context references", () => {
@@ -277,5 +281,6 @@ function assertCompile(expression, expected, mode = "shell") {
277
281
  const globals = new ObjectTree({});
278
282
  const fn = compile.expression(expression, { globals, mode, parent });
279
283
  const actual = fn.code;
284
+ assertCodeLocations(actual);
280
285
  assertCodeEqual(actual, expected);
281
286
  }
@@ -3,7 +3,7 @@ import { describe, test } from "node:test";
3
3
  import { parse } from "../../src/compiler/parse.js";
4
4
  import { markers } from "../../src/compiler/parserHelpers.js";
5
5
  import * as ops from "../../src/runtime/ops.js";
6
- import { assertCodeEqual } from "./codeHelpers.js";
6
+ import { assertCodeEqual, assertCodeLocations } from "./codeHelpers.js";
7
7
 
8
8
  describe("Origami parser", () => {
9
9
  test("additiveExpression", () => {
@@ -1537,19 +1537,6 @@ Body text`,
1537
1537
  assertParse("uriScheme", "https:", [markers.global, "https:"]);
1538
1538
  });
1539
1539
 
1540
- test("whitespace block", () => {
1541
- assertParse(
1542
- "__",
1543
- `
1544
- // First comment
1545
- // Second comment
1546
- `,
1547
- null,
1548
- "jse",
1549
- false
1550
- );
1551
- });
1552
-
1553
1540
  test("unaryExpression", () => {
1554
1541
  assertParse("unaryExpression", "!true", [
1555
1542
  ops.logicalNot,
@@ -1566,6 +1553,19 @@ Body text`,
1566
1553
  assertParse("unaryOperator", "-", "-");
1567
1554
  assertParse("unaryOperator", "~", "~");
1568
1555
  });
1556
+
1557
+ test("whitespace block", () => {
1558
+ assertParse(
1559
+ "__",
1560
+ `
1561
+ // First comment
1562
+ // Second comment
1563
+ `,
1564
+ null,
1565
+ "jse",
1566
+ false
1567
+ );
1568
+ });
1569
1569
  });
1570
1570
 
1571
1571
  function assertParse(
@@ -1596,16 +1596,8 @@ function assertParse(
1596
1596
  assertCodeEqual(code, expected);
1597
1597
  }
1598
1598
 
1599
- function assertCodeLocations(code) {
1600
- assert(code.location, "no location");
1601
- for (const item of code) {
1602
- if (Array.isArray(item)) {
1603
- assertCodeLocations(item);
1604
- }
1605
- }
1606
- }
1607
-
1608
1599
  function assertThrows(startRule, source, message, position, mode = "shell") {
1600
+ // @ts-ignore We declare this so we can inspect it in debugger
1609
1601
  let code;
1610
1602
  try {
1611
1603
  code = parse(source, {
@@ -54,7 +54,7 @@ describe("expressionObject", () => {
54
54
  test("returned object values can be unpacked", async () => {
55
55
  const entries = [["data.json", `{ "a": 1 }`]];
56
56
  const parent = new ObjectTree({});
57
- parent.handlers = {
57
+ /** @type {any} */ (parent).handlers = {
58
58
  "json.handler": {
59
59
  unpack: JSON.parse,
60
60
  },
@@ -358,7 +358,7 @@ describe("ops", () => {
358
358
  const a = await tree.get("a");
359
359
  const b = await a.get("b");
360
360
  const scope = await ops.scope.call(b);
361
- assert.equal(await scope.get("c"), 1);
361
+ assert.equal(await scope?.get("c"), 1);
362
362
  });
363
363
 
364
364
  test("accepts an optional context", async () => {
@@ -372,7 +372,7 @@ describe("ops", () => {
372
372
  const a = await tree.get("a");
373
373
  const b = await a.get("b");
374
374
  const scope = await ops.scope.call(b, tree);
375
- assert.equal(await scope.get("c"), 1);
375
+ assert.equal(await scope?.get("c"), 1);
376
376
  });
377
377
  });
378
378