123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- using Esprima.Ast;
- using Jint.Runtime.Modules;
- namespace Jint
- {
- internal sealed class HoistingScope
- {
- internal readonly List<FunctionDeclaration>? _functionDeclarations;
- internal readonly List<VariableDeclaration>? _variablesDeclarations;
- internal readonly List<Key>? _varNames;
- internal readonly List<Declaration>? _lexicalDeclarations;
- internal readonly List<string>? _lexicalNames;
- internal readonly bool _hasArgumentsReference;
- private HoistingScope(
- List<FunctionDeclaration>? functionDeclarations,
- List<Key>? varNames,
- List<VariableDeclaration>? variableDeclarations,
- List<Declaration>? lexicalDeclarations,
- List<string>? lexicalNames,
- bool hasArgumentsReference)
- {
- _functionDeclarations = functionDeclarations;
- _varNames = varNames;
- _variablesDeclarations = variableDeclarations;
- _lexicalDeclarations = lexicalDeclarations;
- _lexicalNames = lexicalNames;
- _hasArgumentsReference = hasArgumentsReference;
- }
- public static HoistingScope GetProgramLevelDeclarations(
- bool strict,
- Program script,
- bool collectVarNames = false,
- bool collectLexicalNames = false)
- {
- var treeWalker = new ScriptWalker(strict, collectVarNames, collectLexicalNames, checkArgumentsReference: false);
- treeWalker.Visit(script, null);
- return new HoistingScope(
- treeWalker._functions,
- treeWalker._varNames,
- treeWalker._variableDeclarations,
- treeWalker._lexicalDeclarations,
- treeWalker._lexicalNames,
- false);
- }
- public static HoistingScope GetFunctionLevelDeclarations(bool strict, IFunction node)
- {
- var treeWalker = new ScriptWalker(strict, collectVarNames: true, collectLexicalNames: true, checkArgumentsReference: true);
- treeWalker.Visit(node.Body, null);
- if (!treeWalker._hasArgumentsReference)
- {
- ref readonly var parameters = ref node.Params;
- for (var i = 0; i < parameters.Count; ++i)
- {
- treeWalker.Visit(parameters[i], null);
- }
- }
- return new HoistingScope(
- treeWalker._functions,
- treeWalker._varNames,
- treeWalker._variableDeclarations,
- treeWalker._lexicalDeclarations,
- treeWalker._lexicalNames,
- treeWalker._hasArgumentsReference);
- }
- public static HoistingScope GetModuleLevelDeclarations(
- Module module,
- bool collectVarNames = false,
- bool collectLexicalNames = false)
- {
- //Modules area always strict
- var treeWalker = new ScriptWalker(strict: true, collectVarNames, collectLexicalNames, checkArgumentsReference: false);
- treeWalker.Visit(module, null);
- return new HoistingScope(
- treeWalker._functions,
- treeWalker._varNames,
- treeWalker._variableDeclarations,
- treeWalker._lexicalDeclarations,
- treeWalker._lexicalNames,
- false);
- }
- public static List<Declaration>? GetLexicalDeclarations(BlockStatement statement)
- {
- List<Declaration>? lexicalDeclarations = null;
- ref readonly var statementListItems = ref statement.Body;
- for (var i = 0; i < statementListItems.Count; i++)
- {
- var node = statementListItems[i];
- if (node.Type != Nodes.VariableDeclaration && node.Type != Nodes.FunctionDeclaration && node.Type != Nodes.ClassDeclaration)
- {
- continue;
- }
- if (node is VariableDeclaration { Kind: VariableDeclarationKind.Var })
- {
- continue;
- }
- lexicalDeclarations ??= new List<Declaration>();
- lexicalDeclarations.Add((Declaration)node);
- }
- return lexicalDeclarations;
- }
- public static List<Declaration>? GetLexicalDeclarations(SwitchCase statement)
- {
- List<Declaration>? lexicalDeclarations = null;
- ref readonly var statementListItems = ref statement.Consequent;
- for (var i = 0; i < statementListItems.Count; i++)
- {
- var node = statementListItems[i];
- if (node.Type != Nodes.VariableDeclaration)
- {
- continue;
- }
- var rootVariable = (VariableDeclaration)node;
- if (rootVariable.Kind == VariableDeclarationKind.Var)
- {
- continue;
- }
- lexicalDeclarations ??= new List<Declaration>();
- lexicalDeclarations.Add(rootVariable);
- }
- return lexicalDeclarations;
- }
- public static void GetImportsAndExports(
- Module module,
- out HashSet<string> requestedModules,
- out List<ImportEntry>? importEntries,
- out List<ExportEntry> localExportEntries,
- out List<ExportEntry> indirectExportEntries,
- out List<ExportEntry> starExportEntries)
- {
- var treeWalker = new ModuleWalker();
- treeWalker.Visit(module);
- importEntries = treeWalker._importEntries;
- requestedModules = treeWalker._requestedModules ?? new();
- var importedBoundNames = new HashSet<string>();
- if (importEntries != null)
- {
- for (var i = 0; i < importEntries.Count; i++)
- {
- var ie = importEntries[i];
- if (ie.LocalName is not null)
- {
- importedBoundNames.Add(ie.LocalName);
- }
- }
- }
- var exportEntries = treeWalker._exportEntries;
- localExportEntries = new();
- indirectExportEntries = new();
- starExportEntries = new();
- if (exportEntries != null)
- {
- for (var i = 0; i < exportEntries.Count; i++)
- {
- var ee = exportEntries[i];
- if (ee.ModuleRequest is null)
- {
- if (!importedBoundNames.Contains(ee.LocalName))
- {
- localExportEntries.Add(ee);
- }
- else
- {
- for (var j = 0; j < importEntries!.Count; j++)
- {
- var ie = importEntries[j];
- if (ie.LocalName == ee.LocalName)
- {
- if (ie.ImportName == "*")
- {
- localExportEntries.Add(ee);
- }
- else
- {
- indirectExportEntries.Add(new(ee.ExportName, ie.ModuleRequest, ie.ImportName, null));
- }
- break;
- }
- }
- }
- }
- else if (ee.ImportName == "*" && ee.ExportName is null)
- {
- starExportEntries.Add(ee);
- }
- else
- {
- indirectExportEntries.Add(ee);
- }
- }
- }
- }
- private sealed class ScriptWalker
- {
- internal List<FunctionDeclaration>? _functions;
- private readonly bool _strict;
- private readonly bool _collectVarNames;
- internal List<VariableDeclaration>? _variableDeclarations;
- internal List<Key>? _varNames;
- private readonly bool _collectLexicalNames;
- private readonly bool _checkArgumentsReference;
- internal List<Declaration>? _lexicalDeclarations;
- internal List<string>? _lexicalNames;
- internal bool _hasArgumentsReference;
- public ScriptWalker(bool strict, bool collectVarNames, bool collectLexicalNames, bool checkArgumentsReference)
- {
- _strict = strict;
- _collectVarNames = collectVarNames;
- _collectLexicalNames = collectLexicalNames;
- _checkArgumentsReference = checkArgumentsReference;
- }
- public void Visit(Node node, Node? parent)
- {
- foreach (var childNode in node.ChildNodes)
- {
- var childType = childNode.Type;
- if (_checkArgumentsReference && childType == Nodes.Identifier)
- {
- _hasArgumentsReference |= ((Identifier) childNode).Name == "arguments";
- }
- if (childType == Nodes.VariableDeclaration)
- {
- var variableDeclaration = (VariableDeclaration)childNode;
- if (variableDeclaration.Kind == VariableDeclarationKind.Var)
- {
- _variableDeclarations ??= new List<VariableDeclaration>();
- _variableDeclarations.Add(variableDeclaration);
- if (_collectVarNames)
- {
- _varNames ??= new List<Key>();
- ref readonly var nodeList = ref variableDeclaration.Declarations;
- foreach (var declaration in nodeList)
- {
- if (declaration.Id is Identifier identifier)
- {
- _varNames.Add(identifier.Name);
- }
- }
- }
- }
- if (parent is null or Module && variableDeclaration.Kind != VariableDeclarationKind.Var)
- {
- _lexicalDeclarations ??= new List<Declaration>();
- _lexicalDeclarations.Add(variableDeclaration);
- if (_collectLexicalNames)
- {
- _lexicalNames ??= new List<string>();
- ref readonly var nodeList = ref variableDeclaration.Declarations;
- foreach (var declaration in nodeList)
- {
- if (declaration.Id is Identifier identifier)
- {
- _lexicalNames.Add(identifier.Name);
- }
- }
- }
- }
- }
- else if (childType == Nodes.FunctionDeclaration
- // in strict mode cannot include function declarations directly under block or case clauses
- && (!_strict || parent is null || (node.Type != Nodes.BlockStatement && node.Type != Nodes.SwitchCase)))
- {
- _functions ??= new List<FunctionDeclaration>();
- _functions.Add((FunctionDeclaration)childNode);
- }
- else if (childType == Nodes.ClassDeclaration && parent is null or Module)
- {
- _lexicalDeclarations ??= new List<Declaration>();
- _lexicalDeclarations.Add((Declaration) childNode);
- }
- if (childType != Nodes.FunctionDeclaration
- && childType != Nodes.ArrowFunctionExpression
- && childType != Nodes.ArrowParameterPlaceHolder
- && childType != Nodes.FunctionExpression
- && !childNode.ChildNodes.IsEmpty())
- {
- Visit(childNode, node);
- }
- }
- }
- }
- private sealed class ModuleWalker
- {
- internal List<ImportEntry>? _importEntries;
- internal List<ExportEntry>? _exportEntries;
- internal HashSet<string>? _requestedModules;
- internal void Visit(Node node)
- {
- foreach (var childNode in node.ChildNodes)
- {
- if (childNode.Type == Nodes.ImportDeclaration)
- {
- _importEntries ??= new();
- _requestedModules ??= new();
- var import = (ImportDeclaration) childNode;
- import.GetImportEntries(_importEntries, _requestedModules);
- }
- else if (childNode.Type == Nodes.ExportAllDeclaration ||
- childNode.Type == Nodes.ExportDefaultDeclaration ||
- childNode.Type == Nodes.ExportNamedDeclaration)
- {
- _exportEntries ??= new();
- _requestedModules ??= new();
- var export = (ExportDeclaration) childNode;
- export.GetExportEntries(_exportEntries, _requestedModules);
- }
- if (!childNode.ChildNodes.IsEmpty())
- {
- Visit(childNode);
- }
- }
- }
- }
- }
- }
|