Engine.cs 12 KB

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