浏览代码

Applying strict mode declarative

Sebastien Ros 12 年之前
父节点
当前提交
00c55e2006

+ 1 - 1
Jint/Native/Array/ArrayConstructor.cs

@@ -9,7 +9,7 @@ namespace Jint.Native.Array
     {
         private readonly Engine _engine;
 
-        public ArrayConstructor(Engine engine) :  base(engine, new ObjectInstance(engine.RootFunction), null, null)
+        public ArrayConstructor(Engine engine) :  base(engine, new ObjectInstance(engine.RootFunction), null, null, false)
         {
             _engine = engine;
 

+ 1 - 1
Jint/Native/Boolean/BooleanConstructor.cs

@@ -10,7 +10,7 @@ namespace Jint.Native.Boolean
         private readonly Engine _engine;
 
         public BooleanConstructor(Engine engine)
-            : base(engine, new ObjectInstance(engine.Object), null, null)
+            : base(engine, new ObjectInstance(engine.Object), null, null, false)
         {
             _engine = engine;
 

+ 1 - 1
Jint/Native/Date/DateConstructor.cs

@@ -11,7 +11,7 @@ namespace Jint.Native.Date
         private readonly Engine _engine;
 
         public DateConstructor(Engine engine)
-            : base(engine, new ObjectInstance(engine.Object), null, null)
+            : base(engine, new ObjectInstance(engine.Object), null, null, false)
         {
             _engine = engine;
 

+ 1 - 1
Jint/Native/Function/FunctionConstructor.cs

@@ -14,7 +14,7 @@ namespace Jint.Native.Function
         private readonly IEnumerable<Identifier> _parameters;
 
         public FunctionConstructor(Engine engine)
-            : base(engine, engine.RootFunction, null, null)
+            : base(engine, engine.RootFunction, null, null, false)
         {
             _engine = engine;
             // http://www.ecma-international.org/ecma-262/5.1/#sec-13.2

+ 35 - 4
Jint/Native/Function/FunctionInstance.cs

@@ -1,4 +1,5 @@
-using Jint.Native.Object;
+using Jint.Native.Errors;
+using Jint.Native.Object;
 using Jint.Parser.Ast;
 using Jint.Runtime.Environments;
 
@@ -8,11 +9,12 @@ namespace Jint.Native.Function
     {
         private readonly Engine _engine;
 
-        protected FunctionInstance(Engine engine, ObjectInstance prototype, Identifier[] parameters, LexicalEnvironment scope) : base(prototype)
+        protected FunctionInstance(Engine engine, ObjectInstance prototype, Identifier[] parameters, LexicalEnvironment scope, bool strict) : base(prototype)
         {
             _engine = engine;
-            Parameters = parameters;
+            FormalParameters = parameters;
             Scope = scope;
+            Strict = strict;
         }
 
         /// <summary>
@@ -24,7 +26,18 @@ namespace Jint.Native.Function
         public abstract object Call(object thisObject, object[] arguments);
 
         public LexicalEnvironment Scope { get; private set; }
-        public Identifier[] Parameters { get; private set; }
+        
+        public Identifier[] FormalParameters { get; private set; }
+        public bool Strict { get; private set; }
+
+        // todo: implement
+        public object TargetFunction { get; set; }
+
+        // todo: implement
+        public object BoundThis { get; set; }
+
+        // todo: implement
+        public object BoundArgs { get; set; }
 
         public bool HasInstance(object instance)
         {
@@ -58,5 +71,23 @@ namespace Jint.Native.Function
                 return "Function";
             }
         }
+
+        /// <summary>
+        /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5.4
+        /// </summary>
+        /// <param name="propertyName"></param>
+        /// <returns></returns>
+        public override object Get(string propertyName)
+        {
+            var v = base.Get(propertyName);
+
+            var f = v as FunctionInstance;
+            if (propertyName == "caller" && f != null && f.Strict)
+            {
+                throw new TypeError();
+            }
+
+            return v;
+        }
     }
 }

+ 1 - 1
Jint/Native/Function/FunctionShim.cs

@@ -8,7 +8,7 @@ namespace Jint.Native.Function
     {
         private readonly Engine _engine;
 
-        public FunctionShim(Engine engine, ObjectInstance prototype, Identifier[] parameters, LexicalEnvironment scope) : base(engine, prototype, parameters, scope)
+        public FunctionShim(Engine engine, ObjectInstance prototype, Identifier[] parameters, LexicalEnvironment scope) : base(engine, prototype, parameters, scope, false)
         {
             _engine = engine;
         }

+ 26 - 10
Jint/Native/Function/ScriptFunctionInstance.cs

@@ -1,7 +1,9 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
 using Jint.Native.Object;
 using Jint.Parser.Ast;
+using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Environments;
 
@@ -16,8 +18,8 @@ namespace Jint.Native.Function
         private readonly Statement _body;
         private readonly IEnumerable<Identifier> _parameters;
         
-        public ScriptFunctionInstance(Engine engine, Statement body, string name, Identifier[] parameters, ObjectInstance instancePrototype, ObjectInstance functionPrototype, LexicalEnvironment scope)
-            : base(engine, instancePrototype, parameters, scope)
+        public ScriptFunctionInstance(Engine engine, Statement body, string name, Identifier[] parameters, ObjectInstance instancePrototype, ObjectInstance functionPrototype, LexicalEnvironment scope, bool strict)
+            : base(engine, instancePrototype, parameters, scope, strict)
         {
             // http://www.ecma-international.org/ecma-262/5.1/#sec-13.2
 
@@ -33,23 +35,37 @@ namespace Jint.Native.Function
             DefineOwnProperty("prototype", new DataDescriptor(functionPrototype) { Writable = true, Enumerable = true, Configurable = true }, false);
         }
 
+        /// <summary>
+        /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.1
+        /// </summary>
+        /// <param name="thisObject"></param>
+        /// <param name="arguments"></param>
+        /// <returns></returns>
         public override object Call(object thisObject, object[] arguments)
         {
-            // todo: http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.1
+            object thisBinding;
 
             // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3
-            var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(Scope);
-            object thisArg;
-            if (thisObject == Undefined.Instance || thisObject == Null.Instance)
+            if (_engine.Options.IsStrict())
+            {
+                thisBinding = thisObject;
+            }
+            else if (thisObject == Undefined.Instance || thisObject == Null.Instance)
             {
-                thisArg = _engine.Global;
+                thisBinding = _engine.Global;
+            }
+            else if (TypeConverter.GetType(thisObject) != TypeCode.Object)
+            {
+                thisBinding = TypeConverter.ToObject(_engine, thisObject);
             }
             else
             {
-                thisArg = thisObject;
+                thisBinding = thisObject;
             }
 
-            _engine.EnterExecutionContext(localEnv, localEnv, thisArg);
+            var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(Scope);
+            
+            _engine.EnterExecutionContext(localEnv, localEnv, thisBinding);
 
             var env = localEnv.Record;
 

+ 1 - 1
Jint/Native/Number/NumberConstructor.cs

@@ -11,7 +11,7 @@ namespace Jint.Native.Number
         private readonly Engine _engine;
 
         public NumberConstructor(Engine engine)
-            : base(engine, new ObjectInstance(engine.Object), null, null)
+            : base(engine, new ObjectInstance(engine.Object), null, null, false)
         {
             _engine = engine;
 

+ 1 - 1
Jint/Native/Object/ObjectConstructor.cs

@@ -9,7 +9,7 @@ namespace Jint.Native.Object
     {
         private readonly Engine _engine;
 
-        public ObjectConstructor(Engine engine) : base(engine, engine.RootFunction, null, null)
+        public ObjectConstructor(Engine engine) : base(engine, engine.RootFunction, null, null, false)
         {
             _engine = engine;
             engine.RootFunction.DefineOwnProperty("hasOwnProperty", new ClrDataDescriptor<ObjectInstance, bool>(engine, HasOwnProperty), false);

+ 1 - 1
Jint/Native/Object/ObjectInstance.cs

@@ -46,7 +46,7 @@ namespace Jint.Native.Object
         /// </summary>
         /// <param name="propertyName"></param>
         /// <returns></returns>
-        public object Get(string propertyName)
+        public virtual object Get(string propertyName)
         {
             var desc = GetProperty(propertyName);
 

+ 1 - 1
Jint/Native/String/StringConstructor.cs

@@ -10,7 +10,7 @@ namespace Jint.Native.String
         private readonly Engine _engine;
 
         public StringConstructor(Engine engine)
-            : base(engine, new ObjectInstance(engine.Object), null, null)
+            : base(engine, new ObjectInstance(engine.Object), null, null, false)
         {
             _engine = engine;
 

+ 1 - 0
Jint/Parser/Ast/FunctionDeclaration.cs

@@ -12,6 +12,7 @@ namespace Jint.Parser.Ast
         public Identifier Id;
         public IEnumerable<Identifier> Parameters;
         public Statement Body;
+        public bool Strict;
 
         public IList<VariableDeclaration> VariableDeclarations { get; set; }
 

+ 1 - 0
Jint/Parser/Ast/FunctionExpression.cs

@@ -12,6 +12,7 @@ namespace Jint.Parser.Ast
         public Identifier Id;
         public IEnumerable<Identifier> Parameters;
         public Statement Body;
+        public bool Strict;
 
         public IList<VariableDeclaration> VariableDeclarations { get; set; }
 

+ 1 - 0
Jint/Parser/Ast/Program.cs

@@ -13,6 +13,7 @@ namespace Jint.Parser.Ast
         public List<Comment> Comments;
         public List<Token> Tokens;
         public List<ParserError> Errors;
+        public bool Strict;
 
         public IList<VariableDeclaration> VariableDeclarations { get; set; }
     }

+ 13 - 7
Jint/Parser/JavascriptParser.cs

@@ -1485,7 +1485,7 @@ namespace Jint.Parser
         }
 
         public FunctionDeclaration CreateFunctionDeclaration(Identifier id, IEnumerable<Identifier> parameters,
-                                                             IEnumerable<Expression> defaults, Statement body)
+                                                             IEnumerable<Expression> defaults, Statement body, bool strict)
         {
             return new FunctionDeclaration
                 {
@@ -1494,6 +1494,7 @@ namespace Jint.Parser
                     Parameters = parameters,
                     Defaults = defaults,
                     Body = body,
+                    Strict = strict,
                     Rest = null,
                     Generator = false,
                     Expression = false,
@@ -1502,7 +1503,7 @@ namespace Jint.Parser
         }
 
         public FunctionExpression CreateFunctionExpression(Identifier id, IEnumerable<Identifier> parameters,
-                                                           IEnumerable<Expression> defaults, Statement body)
+                                                           IEnumerable<Expression> defaults, Statement body, bool strict)
         {
             return new FunctionExpression
                 {
@@ -1511,6 +1512,7 @@ namespace Jint.Parser
                     Parameters = parameters,
                     Defaults = defaults,
                     Body = body,
+                    Strict = strict,
                     Rest = null,
                     Generator = false,
                     Expression = false,
@@ -1599,12 +1601,13 @@ namespace Jint.Parser
                 };
         }
 
-        public Program CreateProgram(ICollection<Statement> body)
+        public Program CreateProgram(ICollection<Statement> body, bool strict)
         {
             return new Program
                 {
                     Type = SyntaxNodes.Program,
                     Body = body,
+                    Strict = strict,
                     VariableDeclarations = LeaveVariableScope()
                 };
         }
@@ -2001,8 +2004,9 @@ namespace Jint.Parser
             {
                 ThrowErrorTolerant(first, Messages.StrictParamName);
             }
+            bool functionStrict = _strict;
             _strict = previousStrict;
-            return MarkEnd(CreateFunctionExpression(null, parameters, new Expression[0], body));
+            return MarkEnd(CreateFunctionExpression(null, parameters, new Expression[0], body, functionStrict));
         }
 
         private IPropertyKeyExpression ParseObjectPropertyKey()
@@ -3618,9 +3622,10 @@ namespace Jint.Parser
             {
                 ThrowErrorTolerant(stricted, message);
             }
+            bool functionStrict = _strict;
             _strict = previousStrict;
 
-            return MarkEnd(CreateFunctionDeclaration(id, parameters, new Expression[0], body));
+            return MarkEnd(CreateFunctionDeclaration(id, parameters, new Expression[0], body, functionStrict));
         }
 
         private void EnterVariableScope()
@@ -3688,9 +3693,10 @@ namespace Jint.Parser
             {
                 ThrowErrorTolerant(stricted, message);
             }
+            bool functionStrict = _strict;
             _strict = previousStrict;
 
-            return MarkEnd(CreateFunctionExpression(id, parameters, new Expression[0], body));
+            return MarkEnd(CreateFunctionExpression(id, parameters, new Expression[0], body, functionStrict));
         }
 
         // 14 Program
@@ -3780,7 +3786,7 @@ namespace Jint.Parser
             _strict = false;
             Peek();
             ICollection<Statement> body = ParseSourceElements();
-            return MarkEnd(CreateProgram(body));
+            return MarkEnd(CreateProgram(body, _strict));
         }
 
         private LocationMarker CreateLocationMarker()

+ 31 - 9
Jint/Runtime/ExpressionIntepreter.cs

@@ -388,7 +388,8 @@ namespace Jint.Runtime
                 functionExpression.Parameters.ToArray(), 
                 _engine.Function.Prototype,
                 _engine.Object.Construct(Arguments.Empty),
-                LexicalEnvironment.NewDeclarativeEnvironment(_engine.ExecutionContext.LexicalEnvironment)
+                LexicalEnvironment.NewDeclarativeEnvironment(_engine.ExecutionContext.LexicalEnvironment),
+                functionExpression.Strict
                 );
         }
 
@@ -396,22 +397,43 @@ namespace Jint.Runtime
         {
             /// todo: read the spec as this is made up
             
+            var callee = EvaluateExpression(callExpression.Callee);
+            var func = _engine.GetValue(callee);
+            object thisObject;
+
+            // todo: implement as in http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.4
             var arguments = callExpression.Arguments.Select(EvaluateExpression).Select(_engine.GetValue).ToArray();
-            var result = EvaluateExpression(callExpression.Callee);
-            var r = result as Reference;
+
+            if (TypeConverter.GetType(func) != TypeCode.Object)
+            {
+                throw new TypeError();
+            }
+
+            var callable = func as ICallable;
+            if (callable == null)
+            {
+                throw new TypeError();
+            }
+
+            var r = callee as Reference;
             if (r != null)
             {
-                // x.hasOwnProperty
-                var callee = (FunctionInstance)_engine.GetValue(r);
-                return callee.Call(r.GetBase(), arguments);
+                if (r.IsPropertyReference())
+                {
+                    thisObject = r.GetBase();
+                }
+                else
+                {
+                    var env = r.GetBase() as EnvironmentRecord;
+                    thisObject = env.ImplicitThisValue();
+                }
             }
             else
             {
-                // assert(...)
-                var callee = (FunctionInstance)_engine.GetValue(result);
-                return callee.Call(_engine.ExecutionContext.ThisBinding, arguments);
+                thisObject = Undefined.Instance;
             }
 
+            return callable.Call(thisObject, arguments);
         }
 
         public object EvaluateSequenceExpression(SequenceExpression sequenceExpression)

+ 1 - 1
Jint/Runtime/Interop/ClrFunctionInstance.cs

@@ -13,7 +13,7 @@ namespace Jint.Runtime.Interop
         private readonly Func<TObject, object[], TResult> _func;
 
         public ClrFunctionInstance(Engine engine, Func<TObject, object[], TResult> func)
-            : base(engine, null, null, null)
+            : base(engine, null, null, null, false)
         {
             _engine = engine;
             _func = func;

+ 1 - 1
Jint/Runtime/Interop/DelegateWrapper.cs

@@ -13,7 +13,7 @@ namespace Jint.Runtime.Interop
         private readonly Engine _engine;
         private readonly Delegate _d;
 
-        public DelegateWrapper(Engine engine, Delegate d) : base(engine, null, null, null)
+        public DelegateWrapper(Engine engine, Delegate d) : base(engine, null, null, null, false)
         {
             _engine = engine;
             _d = d;

+ 1 - 1
Jint/Runtime/Interop/GetterFunctionInstance.cs

@@ -11,7 +11,7 @@ namespace Jint.Runtime.Interop
         private readonly Func<T, object> _getter;
 
         public GetterFunctionInstance(Engine engine, Func<T, object> getter)
-            : base(engine, null, null, null)
+            : base(engine, null, null, null, false)
         {
             _getter = getter;
         }

+ 1 - 1
Jint/Runtime/Interop/SetterFunctionInstance.cs

@@ -12,7 +12,7 @@ namespace Jint.Runtime.Interop
         private readonly Action<T, object> _setter;
 
         public SetterFunctionInstance(Engine engine, Action<T, object> setter)
-            : base(engine, null, null, null)
+            : base(engine, null, null, null, false)
         {
             _setter = setter;
         }

+ 7 - 1
Jint/Runtime/StatementInterpreter.cs

@@ -460,6 +460,11 @@ namespace Jint.Runtime
 
         public Completion ExecuteProgram(Program program)
         {
+            if (program.Strict)
+            {
+                _engine.Options.Strict();
+            }
+
             EvaluateVariableScope(program);
             return ExecuteStatementList(program.Body);
         }
@@ -516,7 +521,8 @@ namespace Jint.Runtime
                     functionDeclaration.Parameters.ToArray(),
                     _engine.Function.Prototype,
                     _engine.Object.Construct(Arguments.Empty),
-                    LexicalEnvironment.NewDeclarativeEnvironment(_engine.ExecutionContext.LexicalEnvironment)
+                    LexicalEnvironment.NewDeclarativeEnvironment(_engine.ExecutionContext.LexicalEnvironment),
+                    functionDeclaration.Strict
                 )
             );