Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Esprima 3.0.0-beta-7 #1289

Merged
merged 1 commit into from
Sep 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 20 additions & 5 deletions Jint.Benchmark/DromaeoBenchmark.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using BenchmarkDotNet.Attributes;
using Esprima.Ast;

namespace Jint.Benchmark;

[MemoryDiagnoser]
public class DromaeoBenchmark
{
public static readonly Dictionary<string, string> files = new Dictionary<string, string>
private static readonly Dictionary<string, string> _files = new()
{
{"dromaeo-3d-cube", null},
{"dromaeo-core-eval", null},
Expand All @@ -15,14 +16,18 @@ public class DromaeoBenchmark
{"dromaeo-string-base64", null}
};

private Dictionary<string, Script> _prepared = new();

private Engine engine;

[GlobalSetup]
public void Setup()
{
foreach (var fileName in files.Keys.ToList())
foreach (var fileName in _files.Keys)
{
files[fileName] = File.ReadAllText($"Scripts/{fileName}.js");
var script = File.ReadAllText($"Scripts/{fileName}.js");
_files[fileName] = script;
_prepared[fileName] = Engine.PrepareScript(script);
}

engine = new Engine()
Expand All @@ -40,9 +45,12 @@ public void Setup()
[ParamsSource(nameof(FileNames))]
public string FileName { get; set; }

[Params(true, false)]
public bool Prepared { get; set; }

public IEnumerable<string> FileNames()
{
foreach (var entry in files)
foreach (var entry in _files)
{
yield return entry.Key;
}
Expand All @@ -51,6 +59,13 @@ public IEnumerable<string> FileNames()
[Benchmark]
public void Run()
{
engine.Execute(files[FileName]);
if (Prepared)
{
engine.Execute(_prepared[FileName]);
}
else
{
engine.Execute(_files[FileName]);
}
}
}
3 changes: 1 addition & 2 deletions Jint.Benchmark/SingleScriptBenchmark.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using BenchmarkDotNet.Attributes;
using Esprima;
using Esprima.Ast;

namespace Jint.Benchmark;
Expand All @@ -16,7 +15,7 @@ public abstract class SingleScriptBenchmark
public void Setup()
{
_script = File.ReadAllText($"Scripts/{FileName}");
_parsedScript = new JavaScriptParser().ParseScript(_script);
_parsedScript = Engine.PrepareScript(_script);
}

[Benchmark]
Expand Down
5 changes: 2 additions & 3 deletions Jint.Tests.Test262/TestHarness.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using Esprima;

namespace Jint.Tests.Test262;

/// <summary>
Expand All @@ -12,7 +10,8 @@ public partial class TestHarness
foreach (var file in State.HarnessFiles)
{
var source = file.Program;
State.Sources[Path.GetFileName(file.FileName)] = new JavaScriptParser().ParseScript(source, source: file.FileName);
var script = Engine.PrepareScript(source, source: file.FileName);
State.Sources[Path.GetFileName(file.FileName)] = script;
}

return Task.CompletedTask;
Expand Down
2 changes: 1 addition & 1 deletion Jint.Tests/Runtime/EngineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1050,7 +1050,7 @@ public void ShouldGetParseErrorLocation()
{
Assert.Equal(1, e.LineNumber);
Assert.Equal(9, e.Column);
Assert.Equal("jQuery.js", e.SourceText);
Assert.Equal("jQuery.js", e.SourceLocation);
}
}
#region DateParsingAndStrings
Expand Down
58 changes: 58 additions & 0 deletions Jint/Engine.Ast.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using Esprima;
using Esprima.Ast;
using Jint.Runtime.Environments;
using Jint.Runtime.Interpreter;
using Jint.Runtime.Interpreter.Expressions;

namespace Jint;

public partial class Engine
{

/// <summary>
/// Prepares a script for the engine that includes static analysis data to speed up execution during run-time.
/// </summary>
/// <remarks>
/// Returned instance is reusable and thread-safe. You should prepare scripts only once and then reuse them.
/// </remarks>
public static Script PrepareScript(string script, string? source = null)
{
var astAnalyzer = new AstAnalyzer();
var options = ParserOptions.Default with { OnNodeCreated = astAnalyzer.NodeVisitor };

return new JavaScriptParser(options).ParseScript(script, source);
}

private sealed class AstAnalyzer
{
private readonly Dictionary<string, EnvironmentRecord.BindingName> _bindingNames = new();

public void NodeVisitor(Node node)
{
switch (node.Type)
{
case Nodes.Identifier:
{
var name = ((Identifier) node).Name;

if (!_bindingNames.TryGetValue(name, out var bindingName))
{
_bindingNames[name] = bindingName = new EnvironmentRecord.BindingName(name);
}

node.AssociatedData = bindingName;
break;
}
case Nodes.Literal:
node.AssociatedData = JintLiteralExpression.ConvertToJsValue((Literal) node);
break;
case Nodes.ArrowFunctionExpression:
case Nodes.FunctionDeclaration:
case Nodes.FunctionExpression:
var function = (IFunction) node;
node.AssociatedData = JintFunctionDefinition.BuildState(function);
break;
}
}
}
}
8 changes: 4 additions & 4 deletions Jint/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@ internal JsValue ResolveThisBinding()
}

declaredFunctionNames.Add(fn);
functionToInitialize.AddFirst(new JintFunctionDefinition(this, d));
functionToInitialize.AddFirst(new JintFunctionDefinition(d));
}
}
}
Expand Down Expand Up @@ -931,7 +931,7 @@ internal JsValue ResolveThisBinding()
var env = (FunctionEnvironmentRecord) ExecutionContext.LexicalEnvironment;
var strict = _isStrict || StrictModeScope.IsStrictModeCode;

var configuration = func.Initialize(functionInstance);
var configuration = func.Initialize();
var parameterNames = configuration.ParameterNames;
var hasDuplicates = configuration.HasDuplicates;
var simpleParameterList = configuration.IsSimpleParameterList;
Expand All @@ -942,7 +942,7 @@ internal JsValue ResolveThisBinding()
env.InitializeParameters(parameterNames, hasDuplicates, arguments);

ArgumentsInstance? ao = null;
if (configuration.ArgumentsObjectNeeded)
if (configuration.ArgumentsObjectNeeded || _isDebugMode)
{
if (strict || !simpleParameterList)
{
Expand Down Expand Up @@ -1153,7 +1153,7 @@ private ArgumentsInstance CreateUnmappedArgumentsObject(JsValue[] argumentsList)
}

declaredFunctionNames.Add(fn);
functionsToInitialize.AddFirst(new JintFunctionDefinition(this, d));
functionsToInitialize.AddFirst(new JintFunctionDefinition(d));
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Jint/EsprimaExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ internal static void GetBoundNames(this Node? parameter, List<string> target)
ExceptionHelper.ThrowSyntaxError(engine.Realm);
}

var definition = new JintFunctionDefinition(engine, function);
var definition = new JintFunctionDefinition(function);
var closure = intrinsics.Function.OrdinaryFunctionCreate(prototype, definition, definition.ThisMode, scope, privateScope);
closure.MakeMethod(obj);

Expand Down
16 changes: 6 additions & 10 deletions Jint/HoistingScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Jint
{
internal readonly struct HoistingScope
internal sealed class HoistingScope
{
internal readonly List<FunctionDeclaration>? _functionDeclarations;

Expand All @@ -14,7 +14,8 @@ namespace Jint
internal readonly List<string>? _lexicalNames;
internal readonly bool _hasArgumentsReference;

private HoistingScope(List<FunctionDeclaration>? functionDeclarations,
private HoistingScope(
List<FunctionDeclaration>? functionDeclarations,
List<Key>? varNames,
List<VariableDeclaration>? variableDeclarations,
List<Declaration>? lexicalDeclarations,
Expand Down Expand Up @@ -46,17 +47,12 @@ namespace Jint
false);
}

public static HoistingScope GetFunctionLevelDeclarations(
bool strict,
IFunction node,
bool collectVarNames = false,
bool collectLexicalNames = false,
bool checkArgumentsReference = false)
public static HoistingScope GetFunctionLevelDeclarations(bool strict, IFunction node)
{
var treeWalker = new ScriptWalker(strict, collectVarNames, collectLexicalNames, checkArgumentsReference);
var treeWalker = new ScriptWalker(strict, collectVarNames: true, collectLexicalNames: true, checkArgumentsReference: true);
treeWalker.Visit(node.Body, null);

if (checkArgumentsReference && !treeWalker._hasArgumentsReference)
if (!treeWalker._hasArgumentsReference)
{
ref readonly var parameters = ref node.Params;
for (var i = 0; i < parameters.Count; ++i)
Expand Down
2 changes: 1 addition & 1 deletion Jint/Jint.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Esprima" Version="3.0.0-beta-6" />
<PackageReference Include="Esprima" Version="3.0.0-beta-7" />
<PackageReference Include="IsExternalInit" Version="1.0.2" PrivateAssets="all" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all" />
<PackageReference Include="Nullable" Version="1.3.0" PrivateAssets="all" />
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/Function/FunctionConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ private ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
var scope = realmF.GlobalEnv;
PrivateEnvironmentRecord? privateScope = null;

var definition = new JintFunctionDefinition(_engine, function);
var definition = new JintFunctionDefinition(function);
FunctionInstance F = OrdinaryFunctionCreate(proto, definition, function.Strict ? FunctionThisMode.Strict : FunctionThisMode.Global, scope, privateScope);
F.SetFunctionName(_functionNameAnonymous, force: true);

Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/Function/FunctionInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public abstract class FunctionInstance : ObjectInstance, ICallable
Engine engine,
Realm realm,
JsString? name)
: this(engine, realm, name, FunctionThisMode.Global, ObjectClass.Function)
: this(engine, realm, name, FunctionThisMode.Global)
{
}

Expand Down
4 changes: 2 additions & 2 deletions Jint/Native/Function/ScriptFunctionInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public sealed class ScriptFunctionInstance : FunctionInstance, IConstructor
ObjectInstance? proto = null)
: this(
engine,
new JintFunctionDefinition(engine, functionDeclaration),
new JintFunctionDefinition(functionDeclaration),
scope,
strict ? FunctionThisMode.Strict : FunctionThisMode.Global,
proto)
Expand All @@ -39,7 +39,7 @@ public sealed class ScriptFunctionInstance : FunctionInstance, IConstructor
: base(engine, engine.Realm, function, scope, thisMode)
{
_prototype = proto ?? _engine.Realm.Intrinsics.Function.PrototypeObject;
_length = new LazyPropertyDescriptor(null, _ => JsNumber.Create(function.Initialize(this).Length), PropertyFlag.Configurable);
_length = new LazyPropertyDescriptor(null, _ => JsNumber.Create(function.Initialize().Length), PropertyFlag.Configurable);

if (!function.Strict
&& !engine._isStrict
Expand Down
8 changes: 4 additions & 4 deletions Jint/Native/JsNumber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ internal static JsNumber Create(object value)
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static JsNumber Create(double value)
public static JsNumber Create(double value)
{
// we expect zero to be on the fast path of integer mostly
var temp = _intToJsValue;
Expand Down Expand Up @@ -136,7 +136,7 @@ private static JsNumber CreateNumberUnlikely(double value)
return new JsNumber(value);
}

internal static JsNumber Create(byte value)
public static JsNumber Create(byte value)
{
return _intToJsValue[value];
}
Expand All @@ -151,7 +151,7 @@ internal static JsNumber Create(sbyte value)
return new JsNumber(value);
}

internal static JsNumber Create(int value)
public static JsNumber Create(int value)
{
var temp = _intToJsValue;
if ((uint) value < (uint) temp.Length)
Expand Down Expand Up @@ -188,7 +188,7 @@ internal static JsNumber Create(ulong value)
return new JsNumber(value);
}

internal static JsNumber Create(long value)
public static JsNumber Create(long value)
{
if ((ulong) value < (ulong) _intToJsValue.Length)
{
Expand Down
6 changes: 3 additions & 3 deletions Jint/Native/RegExp/RegExpConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ private ObjectInstance RegExpInitialize(RegExpInstance r, JsValue pattern, JsVal

try
{
var parserOptions = new ParserOptions();
var scanner = new Scanner("/" + p + "/" + flags, parserOptions);
var options = new ScannerOptions();
var scanner = new Scanner("/" + p + "/" + flags, options);

// seems valid
r.Value = scanner.ParseRegex(p, f, parserOptions.RegexTimeout);
r.Value = scanner.ParseRegex(p, f, options.RegexTimeout);

var timeout = _engine.Options.Constraints.RegexTimeout;
if (timeout.Ticks > 0)
Expand Down
6 changes: 3 additions & 3 deletions Jint/Runtime/Environments/DeclarativeEnvironmentRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ public sealed override bool HasBinding(string name)
return _dictionary is not null && _dictionary.ContainsKey(name);
}

internal sealed override bool HasBinding(in BindingName name)
internal sealed override bool HasBinding(BindingName name)
{
return _dictionary is not null &&_dictionary.ContainsKey(name.Key);
}

internal override bool TryGetBinding(
in BindingName name,
BindingName name,
bool strict,
out Binding binding,
[NotNullWhen(true)] out JsValue? value)
Expand Down Expand Up @@ -71,7 +71,7 @@ public sealed override void InitializeBinding(string name, JsValue value)
_dictionary.SetOrUpdateValue(name, static (current, value) => current.ChangeValue(value), value);
}

internal sealed override void SetMutableBinding(in BindingName name, JsValue value, bool strict)
internal sealed override void SetMutableBinding(BindingName name, JsValue value, bool strict)
{
SetMutableBinding(name.Key.Name, value, strict);
}
Expand Down