Engine.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. using System;
  2. using System.Collections.Generic;
  3. using Jint.Native.Array;
  4. using Jint.Native.Boolean;
  5. using Jint.Native.Date;
  6. using Jint.Native.Errors;
  7. using Jint.Native.Function;
  8. using Jint.Native.Global;
  9. using Jint.Native.Math;
  10. using Jint.Native.Number;
  11. using Jint.Native.Object;
  12. using Jint.Native.String;
  13. using Jint.Parser;
  14. using Jint.Parser.Ast;
  15. using Jint.Runtime;
  16. using Jint.Runtime.Descriptors;
  17. using Jint.Runtime.Environments;
  18. using Jint.Runtime.Interop;
  19. using Jint.Runtime.References;
  20. namespace Jint
  21. {
  22. public class Engine
  23. {
  24. private readonly ExpressionInterpreter _expressions;
  25. private readonly StatementInterpreter _statements;
  26. private readonly LexicalEnvironment _globalEnvironment;
  27. private readonly Stack<ExecutionContext> _executionContexts;
  28. public Engine() : this(null)
  29. {
  30. }
  31. public Engine(Action<Options> options)
  32. {
  33. _executionContexts = new Stack<ExecutionContext>();
  34. RootObject = new ObjectInstance(null);
  35. RootFunction = new FunctionShim(this, RootObject, null, null);
  36. Object = new ObjectConstructor(this);
  37. Global = GlobalObject.CreateGlobalObject(this, Object);
  38. Function = new FunctionConstructor(this);
  39. Array = new ArrayConstructor(this);
  40. String = new StringConstructor(this);
  41. Number = new NumberConstructor(this);
  42. Boolean = new BooleanConstructor(this);
  43. Date = new DateConstructor(this);
  44. Math = MathInstance.CreateMathObject(this, RootObject);
  45. Global.Set("Object", Object);
  46. Global.Set("Function", Function);
  47. Global.Set("Array", Array);
  48. Global.Set("String", String);
  49. Global.Set("Number", Number);
  50. Global.Set("Boolean", Boolean);
  51. Global.Set("Date", Date);
  52. Global.Set("Math", Math);
  53. // create the global environment http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.3
  54. _globalEnvironment = LexicalEnvironment.NewObjectEnvironment(Global, null);
  55. // create the global execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1
  56. EnterExecutionContext(_globalEnvironment, _globalEnvironment, Global);
  57. Options = new Options();
  58. if (options != null)
  59. {
  60. options(Options);
  61. }
  62. if (options != null)
  63. {
  64. foreach (var entry in Options.GetDelegates())
  65. {
  66. Global.DefineOwnProperty(entry.Key, new DataDescriptor(new DelegateWrapper(this, entry.Value)), false);
  67. }
  68. }
  69. _statements = new StatementInterpreter(this);
  70. _expressions = new ExpressionInterpreter(this);
  71. }
  72. public ObjectInstance RootObject { get; private set; }
  73. public FunctionInstance RootFunction { get; private set; }
  74. public ObjectInstance Global { get; private set; }
  75. public ObjectConstructor Object { get; private set; }
  76. public FunctionConstructor Function { get; private set; }
  77. public ArrayConstructor Array { get; private set; }
  78. public StringConstructor String { get; private set; }
  79. public BooleanConstructor Boolean { get; private set; }
  80. public NumberConstructor Number { get; private set; }
  81. public DateConstructor Date { get; private set; }
  82. public MathInstance Math { get; private set; }
  83. public ExecutionContext ExecutionContext { get { return _executionContexts.Peek(); } }
  84. public Options Options { get; private set; }
  85. public ExecutionContext EnterExecutionContext(LexicalEnvironment lexicalEnvironment, LexicalEnvironment variableEnvironment, object thisBinding)
  86. {
  87. var executionContext = new ExecutionContext
  88. {
  89. LexicalEnvironment = lexicalEnvironment,
  90. VariableEnvironment = variableEnvironment,
  91. ThisBinding = thisBinding
  92. };
  93. _executionContexts.Push(executionContext);
  94. return executionContext;
  95. }
  96. public void LeaveExecutionContext()
  97. {
  98. _executionContexts.Pop();
  99. }
  100. public Completion Execute(string source)
  101. {
  102. var parser = new JavascriptParser();
  103. return Execute(parser.Parse(source));
  104. }
  105. public Completion Execute(Program program)
  106. {
  107. return ExecuteStatement(program);
  108. }
  109. public Completion ExecuteStatement(Statement statement)
  110. {
  111. switch (statement.Type)
  112. {
  113. case SyntaxNodes.BlockStatement:
  114. return _statements.ExecuteBlockStatement(statement.As<BlockStatement>());
  115. case SyntaxNodes.BreakStatement:
  116. return _statements.ExecuteBreakStatement(statement.As<BreakStatement>());
  117. case SyntaxNodes.ContinueStatement:
  118. return _statements.ExecuteContinueStatement(statement.As<ContinueStatement>());
  119. case SyntaxNodes.DoWhileStatement:
  120. return _statements.ExecuteDoWhileStatement(statement.As<DoWhileStatement>());
  121. case SyntaxNodes.DebuggerStatement:
  122. return _statements.ExecuteDebuggerStatement(statement.As<DebuggerStatement>());
  123. case SyntaxNodes.EmptyStatement:
  124. return _statements.ExecuteEmptyStatement(statement.As<EmptyStatement>());
  125. case SyntaxNodes.ExpressionStatement:
  126. return _statements.ExecuteExpressionStatement(statement.As<ExpressionStatement>());
  127. case SyntaxNodes.ForStatement:
  128. return _statements.ExecuteForStatement(statement.As<ForStatement>());
  129. case SyntaxNodes.ForInStatement:
  130. return _statements.ForInStatement(statement.As<ForInStatement>());
  131. case SyntaxNodes.FunctionDeclaration:
  132. return _statements.ExecuteFunctionDeclaration(statement.As<FunctionDeclaration>());
  133. case SyntaxNodes.IfStatement:
  134. return _statements.ExecuteIfStatement(statement.As<IfStatement>());
  135. case SyntaxNodes.LabeledStatement:
  136. return null;
  137. case SyntaxNodes.ReturnStatement:
  138. return _statements.ExecuteReturnStatement(statement.As<ReturnStatement>());
  139. case SyntaxNodes.SwitchStatement:
  140. return _statements.ExecuteSwitchStatement(statement.As<SwitchStatement>());
  141. case SyntaxNodes.ThrowStatement:
  142. return _statements.ExecuteThrowStatement(statement.As<ThrowStatement>());
  143. case SyntaxNodes.TryStatement:
  144. return _statements.ExecuteTryStatement(statement.As<TryStatement>());
  145. case SyntaxNodes.VariableDeclaration:
  146. return _statements.ExecuteVariableDeclaration(statement.As<VariableDeclaration>(), true);
  147. case SyntaxNodes.WhileStatement:
  148. return _statements.ExecuteWhileStatement(statement.As<WhileStatement>());
  149. case SyntaxNodes.WithStatement:
  150. return _statements.ExecuteWithStatement(statement.As<WithStatement>());
  151. case SyntaxNodes.Program:
  152. return _statements.ExecuteProgram(statement.As<Program>());
  153. default:
  154. throw new ArgumentOutOfRangeException();
  155. }
  156. return null;
  157. }
  158. public object EvaluateExpression(Expression expression)
  159. {
  160. switch (expression.Type)
  161. {
  162. case SyntaxNodes.AssignmentExpression:
  163. return _expressions.EvaluateAssignmentExpression(expression.As<AssignmentExpression>());
  164. case SyntaxNodes.ArrayExpression:
  165. return _expressions.EvaluateArrayExpression(expression.As<ArrayExpression>());
  166. case SyntaxNodes.BinaryExpression:
  167. return _expressions.EvaluateBinaryExpression(expression.As<BinaryExpression>());
  168. case SyntaxNodes.CallExpression:
  169. return _expressions.EvaluateCallExpression(expression.As<CallExpression>());
  170. case SyntaxNodes.ConditionalExpression:
  171. return _expressions.EvaluateConditionalExpression(expression.As<ConditionalExpression>());
  172. case SyntaxNodes.FunctionExpression:
  173. return _expressions.EvaluateFunctionExpression(expression.As<FunctionExpression>());
  174. case SyntaxNodes.Identifier:
  175. return _expressions.EvaluateIdentifier(expression.As<Identifier>());
  176. case SyntaxNodes.Literal:
  177. return _expressions.EvaluateLiteral(expression.As<Literal>());
  178. case SyntaxNodes.LogicalExpression:
  179. return null;
  180. case SyntaxNodes.MemberExpression:
  181. return _expressions.EvaluateMemberExpression(expression.As<MemberExpression>());
  182. case SyntaxNodes.NewExpression:
  183. return _expressions.EvaluateNewExpression(expression.As<NewExpression>());
  184. case SyntaxNodes.ObjectExpression:
  185. return _expressions.EvaluateObjectExpression(expression.As<ObjectExpression>());
  186. case SyntaxNodes.SequenceExpression:
  187. return _expressions.EvaluateSequenceExpression(expression.As<SequenceExpression>());
  188. case SyntaxNodes.ThisExpression:
  189. return _expressions.EvaluateThisExpression(expression.As<ThisExpression>());
  190. case SyntaxNodes.UpdateExpression:
  191. return _expressions.EvaluateUpdateExpression(expression.As<UpdateExpression>());
  192. case SyntaxNodes.UnaryExpression:
  193. return _expressions.EvaluateUnaryExpression(expression.As<UnaryExpression>());
  194. default:
  195. throw new ArgumentOutOfRangeException();
  196. }
  197. }
  198. /// <summary>
  199. /// http://www.ecma-international.org/ecma-262/5.1/#sec-8.7.1
  200. /// </summary>
  201. /// <param name="value"></param>
  202. /// <returns></returns>
  203. public object GetValue(object value)
  204. {
  205. var reference = value as Reference;
  206. if (reference == null)
  207. {
  208. var completion = value as Completion;
  209. if (completion != null)
  210. {
  211. return GetValue(completion.Value);
  212. }
  213. return value;
  214. }
  215. if (reference.IsUnresolvableReference())
  216. {
  217. throw new ReferenceError();
  218. }
  219. var baseValue = reference.GetBase();
  220. var record = baseValue as EnvironmentRecord;
  221. if (record != null)
  222. {
  223. return record.GetBindingValue(reference.GetReferencedName(), reference.IsStrict());
  224. }
  225. var o = TypeConverter.ToObject(this, baseValue);
  226. return o.Get(reference.GetReferencedName());
  227. }
  228. public void SetValue(Reference reference, object value)
  229. {
  230. if (reference.IsUnresolvableReference())
  231. {
  232. if (reference.IsStrict())
  233. {
  234. throw new ReferenceError();
  235. }
  236. Global.Set(reference.GetReferencedName(), value);
  237. }
  238. else
  239. {
  240. var baseValue = reference.GetBase();
  241. var record = baseValue as EnvironmentRecord;
  242. if (record != null)
  243. {
  244. record.SetMutableBinding(reference.GetReferencedName(), value, reference.IsStrict());
  245. return;
  246. }
  247. ((ObjectInstance)baseValue).Set(reference.GetReferencedName(), value);
  248. }
  249. }
  250. public object GetGlobalValue(string propertyName)
  251. {
  252. if (System.String.IsNullOrEmpty(propertyName))
  253. {
  254. throw new ArgumentException("propertyName");
  255. }
  256. return GetValue(Global.Get(propertyName));
  257. }
  258. }
  259. }