Browse Source

Upgrade to Esprima 3.0.0-rc-03 (#1596)

Co-authored-by: adams85 <[email protected]>
Marko Lahma 2 years ago
parent
commit
ac1cec85dc

+ 1 - 1
Jint.Repl/Program.cs

@@ -48,7 +48,7 @@ namespace Jint.Repl
             var parserOptions = new ParserOptions
             {
                 Tolerant = true,
-                AdaptRegexp = true
+                RegExpParseMode = RegExpParseMode.AdaptToInterpreted
             };
 
             var serializer = new JsonSerializer(engine);

+ 13 - 36
Jint.Tests.Test262/Test262Harness.settings.json

@@ -30,26 +30,20 @@
     "intl402"
   ],
   "ExcludedFiles": [
-    // Esprima problem for regex, https://github.com/sebastienros/esprima-dotnet/pull/364
-    "built-ins/RegExp/S15.10.4.1_A9_T3.js",
 
     // Currently quite impossible to detect if assignment target is CoverParenthesizedExpression
     "language/expressions/assignment/fn-name-lhs-cover.js",
 
-    // Unicode support not built-in to .NET the same way, requires more work
-    "built-ins/RegExp/prototype/Symbol.match/builtin-infer-unicode.js",
-    "built-ins/RegExp/prototype/Symbol.search/u-lastindex-advance.js",
-    "built-ins/RegExp/prototype/exec/u-lastindex-adv.js",
-    "built-ins/RegExp/unicode_character_class_backspace_escape.js",
-    "built-ins/RegExp/unicode_restricted_identity_escape_alpha.js",
-    "built-ins/RegExp/unicode_restricted_identity_escape_c.js",
-    "built-ins/RegExp/unicode_restricted_identity_escape_u.js",
-    "built-ins/RegExp/unicode_restricted_identity_escape_x.js",
-    "language/literals/regexp/u-astral-char-class-invert.js",
-    "language/literals/regexp/u-astral.js",
-    "language/literals/regexp/u-case-mapping.js",
+    // RegExp conversion limitations
+    "built-ins/RegExp/S15.10.2.11_A1_T5.js",
+    "built-ins/RegExp/S15.10.2.11_A1_T7.js",
+    "built-ins/RegExp/S15.10.2.5_A1_T4.js",
+    "built-ins/RegExp/named-groups/non-unicode-references.js",
+    "built-ins/RegExp/named-groups/unicode-references.js",
+    "built-ins/RegExp/quantifier-integer-limit.js",
+    "language/literals/regexp/named-groups/forward-reference.js",
 
-    // cannot have characters like 𝒜 as group name or something starting with $ in .NET, other .NET limitations
+    // RegExp handling problems
     "built-ins/RegExp/match-indices/indices-array-unicode-property-names.js",
     "built-ins/RegExp/named-groups/non-unicode-match.js",
     "built-ins/RegExp/named-groups/non-unicode-property-names-valid.js",
@@ -58,17 +52,10 @@
     "built-ins/RegExp/named-groups/unicode-property-names-valid.js",
     "built-ins/RegExp/named-groups/unicode-property-names.js",
     "built-ins/RegExp/prototype/Symbol.replace/named-groups.js",
-    "built-ins/RegExp/quantifier-integer-limit.js",
-
-    // more validation and cleanup needed
-    "built-ins/RegExp/S15.10.2.13_A1_T1.js",
-    "built-ins/RegExp/S15.10.2.13_A1_T2.js",
-    "built-ins/RegExp/character-class-escape-non-whitespace.js",
-    "built-ins/RegExp/unicode_character_class_backspace_escape.js",
-    "built-ins/RegExp/unicode_identity_escape.js",
-    "built-ins/RegExp/unicode_restricted_character_class_escape.js",
-    "built-ins/RegExp/unicode_restricted_identity_escape.js",
-    "built-ins/RegExp/unicode_restricted_quantifiable_assertion.js",
+    "built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T6.js",
+    "built-ins/String/prototype/split/separator-regexp.js",
+    "language/literals/regexp/u-case-mapping.js",
+    "language/literals/regexp/u-surrogate-pairs-atom-escape-decimal.js",
 
     // requires investigation how to process complex function name evaluation for property
     "built-ins/Function/prototype/toString/method-computed-property-name.js",
@@ -77,13 +64,6 @@
     // http://www.ecma-international.org/ecma-262/#sec-block-level-function-declarations-web-legacy-compatibility-semantics not implemented (block level functions)
     "language/statements/let/block-local-closure-set-before-initialization.js",
 
-    // Logic difference in .NET RegExp / skipped in ECMA tests too
-    "built-ins/RegExp/S15.10.2.11_A1_T5.js",
-    "built-ins/RegExp/S15.10.2.11_A1_T7.js",
-    "built-ins/RegExp/S15.10.4.1_A8_T2.js",
-    "built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T6.js",
-    "built-ins/RegExp/S15.10.2.5_A1_T4.js",
-
     // Windows line ending differences
     "built-ins/String/raw/special-characters.js",
 
@@ -128,14 +108,11 @@
     "language/module-code/instn-local-bndng-export-gen.js",
 
      // Esprima problem
-     "built-ins/String/prototype/split/separator-regexp.js",
     "language/expressions/object/let-non-strict-access.js",
     "language/expressions/object/let-non-strict-syntax.js",
     "language/expressions/object/yield-non-strict-access.js",
     "language/expressions/object/yield-non-strict-syntax.js",
     "language/expressions/tagged-template/invalid-escape-sequences.js",
-    "language/literals/regexp/u-surrogate-pairs-atom-escape-decimal.js",
-    "language/literals/regexp/u-unicode-esc.js",
     "language/statements/for-of/dstr-obj-id-identifier-yield-ident-valid.js",
     "language/statements/for/head-lhs-let.js",
 

+ 1 - 1
Jint.Tests.Test262/Test262ModuleLoader.cs

@@ -39,7 +39,7 @@ internal sealed class Test262ModuleLoader : IModuleLoader
 
             var parserOptions = new ParserOptions
             {
-                AdaptRegexp = true,
+                RegExpParseMode = RegExpParseMode.AdaptToInterpreted,
                 Tolerant = true
             };
 

+ 1 - 1
Jint.Tests.Test262/Test262Test.cs

@@ -38,7 +38,7 @@ public abstract partial class Test262Test
                     throw new Exception("only script parsing supported");
                 }
 
-                var options = new ParserOptions { AdaptRegexp = true, Tolerant = false };
+                var options = new ParserOptions { RegExpParseMode = RegExpParseMode.AdaptToInterpreted, Tolerant = false };
                 var parser = new JavaScriptParser(options);
                 var script = parser.ParseScript(args.At(0).AsString());
 

+ 2 - 2
Jint.Tests/Runtime/ErrorTests.cs

@@ -297,7 +297,7 @@ var x = b(7);";
 
             var parserOptions = new ParserOptions
             {
-                AdaptRegexp = true,
+                RegExpParseMode = RegExpParseMode.AdaptToInterpreted,
                 Tolerant = true
             };
             var ex = Assert.Throws<JavaScriptException>(() => engine.Execute(script, "get-item.js", parserOptions));
@@ -388,7 +388,7 @@ try {
             {
                 return new ParserOptions
                 {
-                    AdaptRegexp = true,
+                    RegExpParseMode = RegExpParseMode.AdaptToInterpreted,
                     Tolerant = true
                 };
             }

+ 10 - 5
Jint/Engine.cs

@@ -26,11 +26,8 @@ namespace Jint
     /// </summary>
     public sealed partial class Engine : IDisposable
     {
-        private static readonly ParserOptions _defaultParserOptions = ParserOptions.Default with
-        {
-            AllowReturnOutsideFunction = true
-        };
-        private readonly JavaScriptParser _defaultParser = new(_defaultParserOptions);
+        private readonly ParserOptions _defaultParserOptions;
+        private readonly JavaScriptParser _defaultParser;
 
         internal readonly ExecutionContextStack _executionContexts;
         private JsValue _completionValue = JsValue.Undefined;
@@ -131,6 +128,14 @@ namespace Jint
 
             CallStack = new JintCallStack(Options.Constraints.MaxRecursionDepth >= 0);
             _stackGuard = new StackGuard(this);
+
+            _defaultParserOptions = ParserOptions.Default with
+            {
+                AllowReturnOutsideFunction = true,
+                RegexTimeout = Options.Constraints.RegexTimeout
+            };
+
+            _defaultParser = new JavaScriptParser(_defaultParserOptions);
         }
 
         private void Reset()

+ 1 - 1
Jint/Jint.csproj

@@ -16,7 +16,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Esprima" Version="3.0.0-rc-02" />
+    <PackageReference Include="Esprima" Version="3.0.0-rc-03" />
     <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all" />
     <PackageReference Include="Nullable" Version="1.3.1" PrivateAssets="all" />
     <PackageReference Include="PolySharp" Version="1.13.1">

+ 4 - 1
Jint/ModuleBuilder.cs

@@ -20,7 +20,10 @@ public sealed class ModuleBuilder
     {
         _engine = engine;
         _specifier = specifier;
-        _options = new ParserOptions();
+        _options = new ParserOptions
+        {
+            RegexTimeout = engine.Options.Constraints.RegexTimeout
+        };
     }
 
     public ModuleBuilder AddSource(string code)

+ 5 - 1
Jint/Native/Function/FunctionInstance.Dynamic.cs

@@ -138,7 +138,11 @@ public partial class FunctionInstance
                 }
             }
 
-            JavaScriptParser parser = new(new ParserOptions { Tolerant = false });
+            JavaScriptParser parser = new(new ParserOptions
+            {
+                Tolerant = false,
+                RegexTimeout = _engine.Options.Constraints.RegexTimeout
+            });
             function = (IFunction) parser.ParseScript(functionExpression, source: null, _engine._isStrict).Body[0];
         }
         catch (ParserException ex)

+ 8 - 22
Jint/Native/RegExp/RegExpConstructor.cs

@@ -104,17 +104,14 @@ namespace Jint.Native.RegExp
 
             try
             {
-                var options = new ScannerOptions();
-                var scanner = new Scanner("/" + p + "/" + flags, options);
+                var regExp = Scanner.AdaptRegExp(p, f, compiled: false, _engine.Options.Constraints.RegexTimeout);
 
-                // seems valid
-                r.Value = scanner.ParseRegex(p, f, options.RegexTimeout);
-
-                var timeout = _engine.Options.Constraints.RegexTimeout;
-                if (timeout.Ticks > 0)
+                if (regExp is null)
                 {
-                    r.Value = new Regex(r.Value.ToString(), r.Value.Options, timeout);
+                    ExceptionHelper.ThrowSyntaxError(_realm, $"Unsupported regular expression: '/{p}/{flags}'");
                 }
+
+                r.Value = regExp;
             }
             catch (Exception ex)
             {
@@ -140,21 +137,10 @@ namespace Jint.Native.RegExp
 
         public JsRegExp Construct(Regex regExp, string source, string flags)
         {
-            var r = new JsRegExp(Engine);
-            r._prototype = PrototypeObject;
-
-            r.Flags = flags;
+            var r = RegExpAlloc(this);
+            r.Value = regExp;
             r.Source = source;
-
-            var timeout = _engine.Options.Constraints.RegexTimeout;
-            if (timeout.Ticks > 0)
-            {
-                r.Value = new Regex(regExp.ToString(), regExp.Options, timeout);
-            }
-            else
-            {
-                r.Value = regExp;
-            }
+            r.Flags = flags;
 
             RegExpInitialize(r);
 

+ 6 - 1
Jint/Native/ShadowRealm/ShadowRealm.cs

@@ -17,12 +17,17 @@ namespace Jint.Native.ShadowRealm;
 /// </summary>
 public sealed class ShadowRealm : ObjectInstance
 {
-    private readonly JavaScriptParser _parser = new(new ParserOptions { Tolerant = false });
+    private readonly JavaScriptParser _parser;
     internal readonly Realm _shadowRealm;
     private readonly ExecutionContext _executionContext;
 
     internal ShadowRealm(Engine engine, ExecutionContext executionContext, Realm shadowRealm) : base(engine)
     {
+        _parser = new(new ParserOptions
+        {
+            Tolerant = false,
+            RegexTimeout = engine.Options.Constraints.RegexTimeout
+        });
         _executionContext = executionContext;
         _shadowRealm = shadowRealm;
     }

+ 6 - 1
Jint/Runtime/Interpreter/Expressions/JintLiteralExpression.cs

@@ -76,7 +76,12 @@ namespace Jint.Runtime.Interpreter.Expressions
             if (expression.TokenType == TokenType.RegularExpression)
             {
                 var regExpLiteral = (RegExpLiteral) _expression;
-                return context.Engine.Realm.Intrinsics.RegExp.Construct((System.Text.RegularExpressions.Regex) regExpLiteral.Value!, regExpLiteral.Regex.Pattern, regExpLiteral.Regex.Flags);
+                if (regExpLiteral.Value is System.Text.RegularExpressions.Regex regex)
+                {
+                    return context.Engine.Realm.Intrinsics.RegExp.Construct(regex, regExpLiteral.Regex.Pattern, regExpLiteral.Regex.Flags);
+                }
+
+                ExceptionHelper.ThrowSyntaxError(context.Engine.Realm, $"Unsupported regular expression: '{regExpLiteral.Regex.Pattern}/{regExpLiteral.Regex.Flags}'");
             }
 
             return JsValue.FromObject(context.Engine, expression.Value);