123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- using Jint.Native;
- using Jint.Runtime.Environments;
- using Jint.Runtime.Interpreter.Expressions;
- using Environment = Jint.Runtime.Environments.Environment;
- namespace Jint.Runtime.Interpreter.Statements
- {
- internal sealed class JintSwitchBlock
- {
- private readonly NodeList<SwitchCase> _switchBlock;
- private JintSwitchCase[] _jintSwitchBlock = Array.Empty<JintSwitchCase>();
- private bool _initialized;
- public JintSwitchBlock(NodeList<SwitchCase> switchBlock)
- {
- _switchBlock = switchBlock;
- }
- private void Initialize()
- {
- _jintSwitchBlock = new JintSwitchCase[_switchBlock.Count];
- for (var i = 0; i < _jintSwitchBlock.Length; i++)
- {
- _jintSwitchBlock[i] = new JintSwitchCase(_switchBlock[i]);
- }
- }
- public Completion Execute(EvaluationContext context, JsValue input)
- {
- if (!_initialized)
- {
- Initialize();
- _initialized = true;
- }
- var v = JsValue.Undefined;
- var l = context.LastSyntaxElement;
- var hit = false;
- var defaultCaseIndex = -1;
- var i = 0;
- Environment? oldEnv = null;
- var temp = _jintSwitchBlock;
- DeclarativeEnvironment? blockEnv = null;
- start:
- for (; i < temp.Length; i++)
- {
- var clause = temp[i];
- if (clause.LexicalDeclarations is not null && oldEnv is null)
- {
- oldEnv = context.Engine.ExecutionContext.LexicalEnvironment;
- blockEnv ??= JintEnvironment.NewDeclarativeEnvironment(context.Engine, oldEnv);
- blockEnv.Clear();
- JintStatementList.BlockDeclarationInstantiation(blockEnv, clause.LexicalDeclarations);
- context.Engine.UpdateLexicalEnvironment(blockEnv);
- }
- if (clause.Test == null)
- {
- defaultCaseIndex = i;
- if (!hit)
- {
- continue;
- }
- }
- var clauseSelector = clause.Test?.GetValue(context);
- if (clauseSelector == input)
- {
- hit = true;
- }
- if (!hit)
- {
- if (oldEnv is not null)
- {
- context.Engine.UpdateLexicalEnvironment(oldEnv);
- oldEnv = null;
- }
- continue;
- }
- var r = clause.Consequent.Execute(context);
- if (r.Type != CompletionType.Normal)
- {
- if (oldEnv is not null)
- {
- context.Engine.UpdateLexicalEnvironment(oldEnv);
- }
- return r.UpdateEmpty(v);
- }
- l = r._source;
- v = r.Value.IsUndefined() ? v : r.Value;
- }
- // do we need to execute the default case ?
- if (!hit && defaultCaseIndex != -1)
- {
- // jump back to loop and start from default case
- hit = true;
- i = defaultCaseIndex;
- goto start;
- }
- if (oldEnv is not null)
- {
- context.Engine.UpdateLexicalEnvironment(oldEnv);
- }
- return new Completion(CompletionType.Normal, v, l);
- }
- private sealed class JintSwitchCase
- {
- internal readonly JintStatementList Consequent;
- internal readonly JintExpression? Test;
- internal readonly List<Declaration>? LexicalDeclarations;
- public JintSwitchCase(SwitchCase switchCase)
- {
- Consequent = new JintStatementList(statement: null, switchCase.Consequent);
- LexicalDeclarations = HoistingScope.GetLexicalDeclarations(switchCase);
- if (switchCase.Test != null)
- {
- Test = JintExpression.Build(switchCase.Test);
- }
- }
- }
- }
- }
|