Skip to content

Commit 25966a1

Browse files
lahmaadams85
andauthored
Add support for using and await using (#23)
* update to latest test suite * create experimental flags * port parsing logic * Update src/Acornima/ExperimentalESFeatures.cs * add configuration to allow top-level using * fix line break test * fix scope * use localized messages * Adjust IsLet * Simplify IsUsingKeyword usage by removing redundant calls * Update TryGetInternedString * Update documentation of VariableDeclarator.Id * Fix source gen tests * Correct async function and await using lookaheads * Disallow explicit resource management for ES versions not supporting async/await * Improve AST to JSON conversion + remove the each property of for-of statements * Port tests from acornjs * Adjust implementation to match the error reporting behavior of V8 * Add tests for some edge cases + AllowTopLevelUsing * Improve documentation of AllowTopLevelUsing --------- Co-authored-by: adams85 <[email protected]> Co-authored-by: Adam Simon <[email protected]>
1 parent 6e3040a commit 25966a1

File tree

248 files changed

+9100
-110
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

248 files changed

+9100
-110
lines changed

src/Acornima.Extras/AstToJsonConverter.cs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,16 +152,41 @@ protected void Member(string name, int value)
152152
_writer.Number(value);
153153
}
154154

155-
private static readonly ConditionalWeakTable<Type, IDictionary> s_enumMap = new();
155+
protected void Member(string name, SourceType sourceType)
156+
{
157+
var value = sourceType switch
158+
{
159+
SourceType.Script => "script",
160+
SourceType.Module => "module",
161+
_ => "unknown"
162+
};
163+
164+
Member(name, value);
165+
}
166+
167+
protected void Member(string name, PropertyKind propertyKind)
168+
{
169+
var value = propertyKind switch
170+
{
171+
PropertyKind.Init => "init",
172+
PropertyKind.Get => "get",
173+
PropertyKind.Set => "set",
174+
PropertyKind.Constructor => "constructor",
175+
PropertyKind.Method => "method",
176+
PropertyKind.Property => "property",
177+
_ => "unknown"
178+
};
179+
180+
Member(name, value);
181+
}
156182

157-
protected void Member<T>(string name, T value) where T : struct, Enum
183+
protected void Member(string name, VariableDeclarationKind declarationKind)
158184
{
159-
var map = (Dictionary<T, string>)s_enumMap.GetValue(value.GetType(), t =>
160-
t.GetRuntimeFields()
161-
.Where(f => f.IsStatic)
162-
.ToDictionary(f => (T)f.GetValue(null)!, f => f.Name.ToLowerInvariant()));
185+
var value = declarationKind is >= VariableDeclarationKind.Var and <= VariableDeclarationKind.AwaitUsing
186+
? VariableDeclaration.GetVariableDeclarationKindToken(declarationKind)
187+
: "unknown";
163188

164-
Member(name, map[value]);
189+
Member(name, value);
165190
}
166191

167192
protected void Member<T>(string name, in NodeList<T> nodes) where T : Node?
@@ -514,7 +539,6 @@ private IClass VisitClass(IClass node)
514539
Member("left", node.Left);
515540
Member("right", node.Right);
516541
Member("body", node.Body);
517-
Member("each", false);
518542
}
519543

520544
return node;

src/Acornima/Ast/Property.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ private protected Property(PropertyKind kind, Expression key, Node value, bool c
2121
public Expression Key { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; }
2222

2323
/// <remarks>
24-
/// When property of an object literal: <see cref="Expression"/> (incl. <see cref="SpreadElement"/> and <see cref="FunctionExpression"/> for getters/setters/methods) <br />
24+
/// When property of an object literal: <see cref="Expression"/> (incl. <see cref="SpreadElement"/> and <see cref="FunctionExpression"/> for getters/setters/methods)<br />
2525
/// When property of an object pattern: <see cref="Identifier"/> | <see cref="MemberExpression"/> (in assignment contexts only) | <see cref="ArrayPattern"/> | <see cref="ObjectPattern"/> | <see cref="AssignmentPattern"/> | <see cref="RestElement"/>
2626
/// </remarks>
2727
public Node Value { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; }

src/Acornima/Ast/VariableDeclaration.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ public static string GetVariableDeclarationKindToken(VariableDeclarationKind kin
1515
VariableDeclarationKind.Var => "var",
1616
VariableDeclarationKind.Let => "let",
1717
VariableDeclarationKind.Const => "const",
18+
VariableDeclarationKind.Using => "using",
19+
VariableDeclarationKind.AwaitUsing => "await using",
1820
_ => ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString(), null)
1921
};
2022
}

src/Acornima/Ast/VariableDeclarationKind.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ public enum VariableDeclarationKind
55
Unknown,
66
Var,
77
Let,
8-
Const
8+
Const,
9+
Using,
10+
AwaitUsing
911
}

src/Acornima/Ast/VariableDeclarator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ public VariableDeclarator(Node id, Expression? init)
1313
}
1414

1515
/// <remarks>
16-
/// <see cref="Identifier"/> | <see cref="ArrayPattern"/> | <see cref="ObjectPattern"/>
16+
/// In the case of var, let or const variable declarations: <see cref="Identifier"/> | <see cref="ArrayPattern"/> | <see cref="ObjectPattern"/><br />
17+
/// In the case of using and await using const variable declarations: <see cref="Identifier"/>
1718
/// </remarks>
1819
public Node Id { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; }
1920
public Expression? Init { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; }

src/Acornima/ExperimentalESFeatures.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,10 @@ public enum ExperimentalESFeatures
2222
/// </summary>
2323
RegExpDuplicateNamedCapturingGroups = 1 << 2,
2424

25-
All = Decorators | ImportAttributes | RegExpDuplicateNamedCapturingGroups
25+
/// <summary>
26+
/// Explicit resource management feature as specified by this <seealso href="https://github.com/tc39/proposal-explicit-resource-management">proposal</seealso>. Available only when <see cref="ParserOptions.EcmaVersion"/> >= ES2017.
27+
/// </summary>
28+
ExplicitResourceManagement = 1 << 3,
29+
30+
All = Decorators | ImportAttributes | RegExpDuplicateNamedCapturingGroups | ExplicitResourceManagement
2631
}

src/Acornima/Parser.State.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,18 @@ private bool AllowNewDotTarget
309309
|| (CurrentThisScope._flags & (ScopeFlags.Function | ScopeFlags.ClassStaticBlock | ScopeFlags.InClassFieldInit)) != 0;
310310
}
311311

312+
private bool AllowUsing
313+
{
314+
// https://github.com/acornjs/acorn/blob/8.11.3/acorn/src/state.js > `get allowUsing`
315+
316+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
317+
get
318+
{
319+
var flags = CurrentScope._flags;
320+
return (flags & ScopeFlags.Switch) == 0 && (_inModule || (flags & ScopeFlags.Top) == 0 || _options._allowTopLevelUsing);
321+
}
322+
}
323+
312324
private bool InClassStaticBlock
313325
{
314326
// https://github.com/acornjs/acorn/blob/8.11.3/acorn/src/state.js > `get inClassStaticBlock`

0 commit comments

Comments
 (0)