Forráskód Böngészése

Completing Lexical Environments

Sebastien Ros 12 éve
szülő
commit
97f97b764c

+ 1 - 0
Jint.Tests.Ecma/Ecma/10.2.1.1.3.cs

@@ -2,6 +2,7 @@ using Xunit;
 
 namespace Jint.Tests.Ecma
 {
+    [Trait("Category", "Pass")]
     public class Test_10_2_1_1_3 : EcmaTest
     {
         [Fact]

+ 1 - 0
Jint.Tests.Ecma/Ecma/10.2.1.cs

@@ -2,6 +2,7 @@ using Xunit;
 
 namespace Jint.Tests.Ecma
 {
+    [Trait("Category", "Pass")]
     public class Test_10_2_1 : EcmaTest
     {
         [Fact]

+ 1 - 0
Jint.Tests.Ecma/Ecma/10.2.2.cs

@@ -2,6 +2,7 @@ using Xunit;
 
 namespace Jint.Tests.Ecma
 {
+    [Trait("Category", "Pass")]
     public class Test_10_2_2 : EcmaTest
     {
         [Fact]

+ 1 - 0
Jint.Tests.Ecma/Ecma/10.2.3.cs

@@ -2,6 +2,7 @@ using Xunit;
 
 namespace Jint.Tests.Ecma
 {
+    [Trait("Category", "Pass")]
     public class Test_10_2_3 : EcmaTest
     {
         [Fact]

+ 2 - 1
Jint.Tests.Ecma/TestCases/ch10/10.2/10.2.1/10.2.1.1/10.2.1.1.3/10.2.1.1.3-4-16-s.js

@@ -9,7 +9,8 @@
 function testcase() {
         "use strict";
 
-        try {
+    try {
+        debugger;
             NaN = 12;
             return false;
         } catch (e) {

+ 10 - 7
Jint/Engine.cs

@@ -29,7 +29,7 @@ namespace Jint
         private readonly ExpressionInterpreter _expressions;
         private readonly StatementInterpreter _statements;
         private readonly Stack<ExecutionContext> _executionContexts;
-
+ 
         public Engine() : this(null)
         {
         }
@@ -115,7 +115,7 @@ namespace Jint
                 }
             }
 
-            Eval = new EvalFunctionInstance(this, new ObjectInstance(this), new string[0], LexicalEnvironment.NewDeclarativeEnvironment(this, ExecutionContext.LexicalEnvironment), Options.IsStrict());
+            Eval = new EvalFunctionInstance(this, new ObjectInstance(this), new string[0], LexicalEnvironment.NewDeclarativeEnvironment(this, ExecutionContext.LexicalEnvironment), StrictModeScope.IsStrictModeCode);
             Global.FastAddProperty("eval", Eval, true, false, true);
 
             _statements = new StatementInterpreter(this);
@@ -175,13 +175,16 @@ namespace Jint
 
         public object Execute(Program program)
         {
-            var result = _statements.ExecuteProgram(program);
-            if (result.Type == Completion.Throw)
+            using (new StrictModeScope(Options.IsStrict()))
             {
-                throw new JavaScriptException(result.Value);
-            }
+                var result = _statements.ExecuteProgram(program);
+                if (result.Type == Completion.Throw)
+                {
+                    throw new JavaScriptException(result.Value);
+                }
 
-            return GetValue(result.Value);
+                return GetValue(result.Value);
+            }
         }
 
         public Completion ExecuteStatement(Statement statement)

+ 1 - 0
Jint/Jint.csproj

@@ -161,6 +161,7 @@
     <Compile Include="Runtime\References\Reference.cs" />
     <Compile Include="Runtime\StatementInterpreter.cs" />
     <Compile Include="Runtime\TypeConverter.cs" />
+    <Compile Include="StrictModeScope.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

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

@@ -16,7 +16,7 @@ namespace Jint.Native.Function
 
         public override object Call(object thisObject, object[] arguments)
         {
-            if (Engine.Options.IsStrict())
+            if (StrictModeScope.IsStrictModeCode)
             {
                 throw new JavaScriptException(Engine.SyntaxError, "eval() is not allowed in strict mode.");
             }

+ 72 - 68
Jint/Native/Function/ScriptFunctionInstance.cs

@@ -58,93 +58,97 @@ namespace Jint.Native.Function
         public override object Call(object thisArg, object[] arguments)
         {
             object thisBinding;
-
-            // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3
-            if (this.Strict || Engine.Options.IsStrict())
-            {
-                thisBinding = thisArg;
-            }
-            else if (thisArg == Undefined.Instance || thisArg == Null.Instance)
+            using (new StrictModeScope(Strict))
             {
-                thisBinding = Engine.Global;
-            }
-            else if (TypeConverter.GetType(thisArg) != Types.Object)
-            {
-                thisBinding = TypeConverter.ToObject(Engine, thisArg);
-            }
-            else
-            {
-                thisBinding = thisArg;
-            }
-
-            var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(Engine, Scope);
-            
-            Engine.EnterExecutionContext(localEnv, localEnv, thisBinding);
-
-            // Declaration Binding Instantiation http://www.ecma-international.org/ecma-262/5.1/#sec-10.5
-            var env = localEnv.Record;
-            var configurableBindings = false;
-
-            //if (/* todo: if code is eval code */)
-            //{
-            //    configurableBindings = true;
-            //}
-
-            var argCount = arguments.Length;
-            var n = 0;
-            foreach (var argName in FormalParameters)
-            {
-                n++;
-                var v = n > argCount ? Undefined.Instance : arguments[n-1];
-                var argAlreadyDeclared = env.HasBinding(argName);
-                if (!argAlreadyDeclared)
+                // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3
+                if (StrictModeScope.IsStrictModeCode)
+                {
+                    thisBinding = thisArg;
+                }
+                else if (thisArg == Undefined.Instance || thisArg == Null.Instance)
+                {
+                    thisBinding = Engine.Global;
+                }
+                else if (TypeConverter.GetType(thisArg) != Types.Object)
+                {
+                    thisBinding = TypeConverter.ToObject(Engine, thisArg);
+                }
+                else
                 {
-                    env.CreateMutableBinding(argName);
+                    thisBinding = thisArg;
                 }
 
-                env.SetMutableBinding(argName, v, Strict);
-            }
+                var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(Engine, Scope);
 
-            Engine.FunctionDeclarationBindings(_functionDeclaration, localEnv, true, Strict);
+                Engine.EnterExecutionContext(localEnv, localEnv, thisBinding);
 
-            var argumentsAlreadyDeclared = env.HasBinding("arguments");
+                // Declaration Binding Instantiation http://www.ecma-international.org/ecma-262/5.1/#sec-10.5
+                var env = localEnv.Record;
+                var configurableBindings = false;
 
-            if (!argumentsAlreadyDeclared)
-            {
-                var argsObj = ArgumentsInstance.CreateArgumentsObject(Engine, this, FormalParameters, arguments, env, Strict);
+                //if (/* todo: if code is eval code */)
+                //{
+                //    configurableBindings = true;
+                //}
 
-                if (Strict)
+                var argCount = arguments.Length;
+                var n = 0;
+                foreach (var argName in FormalParameters)
                 {
-                    var declEnv = env as DeclarativeEnvironmentRecord;
-                    
-                    if (declEnv == null)
+                    n++;
+                    var v = n > argCount ? Undefined.Instance : arguments[n - 1];
+                    var argAlreadyDeclared = env.HasBinding(argName);
+                    if (!argAlreadyDeclared)
                     {
-                        throw new ArgumentException();
+                        env.CreateMutableBinding(argName);
                     }
 
-                    declEnv.CreateImmutableBinding("arguments");
-                    declEnv.InitializeImmutableBinding("arguments", argsObj);
+                    env.SetMutableBinding(argName, v, Strict);
                 }
-                else
+
+                Engine.FunctionDeclarationBindings(_functionDeclaration, localEnv, true, Strict);
+
+                var argumentsAlreadyDeclared = env.HasBinding("arguments");
+
+                if (!argumentsAlreadyDeclared)
                 {
-                    env.CreateMutableBinding("arguments");
-                    env.SetMutableBinding("arguments", argsObj, false);
+                    var argsObj = ArgumentsInstance.CreateArgumentsObject(Engine, this, FormalParameters, arguments, env,
+                        Strict);
+
+                    if (Strict)
+                    {
+                        var declEnv = env as DeclarativeEnvironmentRecord;
+
+                        if (declEnv == null)
+                        {
+                            throw new ArgumentException();
+                        }
+
+                        declEnv.CreateImmutableBinding("arguments");
+                        declEnv.InitializeImmutableBinding("arguments", argsObj);
+                    }
+                    else
+                    {
+                        env.CreateMutableBinding("arguments");
+                        env.SetMutableBinding("arguments", argsObj, false);
+                    }
                 }
-            }
 
-            // process all variable declarations in the current parser scope
-            Engine.VariableDeclarationBinding(_functionDeclaration.VariableDeclarations, env, configurableBindings, Strict);
+                // process all variable declarations in the current parser scope
+                Engine.VariableDeclarationBinding(_functionDeclaration.VariableDeclarations, env, configurableBindings,
+                    Strict);
 
-            var result = Engine.ExecuteStatement(_functionDeclaration.Body);
-            
-            Engine.LeaveExecutionContext();
+                var result = Engine.ExecuteStatement(_functionDeclaration.Body);
 
-            if (result.Type == Completion.Throw)
-            {
-                throw new JavaScriptException(result.Value);
-            }
+                Engine.LeaveExecutionContext();
 
-            return result.Value ?? Undefined.Instance;
+                if (result.Type == Completion.Throw)
+                {
+                    throw new JavaScriptException(result.Value);
+                }
+
+                return result.Value ?? Undefined.Instance;
+            }
         }
 
         /// <summary>

+ 23 - 15
Jint/Runtime/ExpressionIntepreter.cs

@@ -603,7 +603,7 @@ namespace Jint.Runtime
 
         public object EvaluateIdentifier(Identifier identifier)
         {
-            return _engine.ExecutionContext.LexicalEnvironment.GetIdentifierReference(identifier.Name, _engine.Options.IsStrict());
+            return _engine.ExecutionContext.LexicalEnvironment.GetIdentifierReference(identifier.Name, StrictModeScope.IsStrictModeCode);
         }
 
         public object EvaluateLiteral(Literal literal)
@@ -638,12 +638,16 @@ namespace Jint.Runtime
                             throw new JavaScriptException(_engine.SyntaxError);
                         }
 
-                        var get = new ScriptFunctionInstance(
-                            _engine,
-                            getter,
-                            _engine.ExecutionContext.LexicalEnvironment,
-                            getter.Strict || _engine.Options.IsStrict()
+                        ScriptFunctionInstance get; 
+                        using (new StrictModeScope(getter.Strict))
+                        {
+                            get = new ScriptFunctionInstance(
+                                _engine,
+                                getter,
+                                _engine.ExecutionContext.LexicalEnvironment, 
+                                StrictModeScope.IsStrictModeCode
                             );
+                        }
 
                         propDesc = new AccessorDescriptor(get) { Enumerable = true, Configurable = true};
                         break;
@@ -656,13 +660,17 @@ namespace Jint.Runtime
                             throw new JavaScriptException(_engine.SyntaxError);
                         }
 
-                        var set = new ScriptFunctionInstance(
-                            _engine,
-                            setter,
-                            _engine.ExecutionContext.LexicalEnvironment,
-                            setter.Strict || _engine.Options.IsStrict()
-                            );
-
+                        ScriptFunctionInstance set;
+                        using (new StrictModeScope(setter.Strict))
+                        {
+                            
+                            set = new ScriptFunctionInstance(
+                                _engine,
+                                setter,
+                                _engine.ExecutionContext.LexicalEnvironment,
+                                StrictModeScope.IsStrictModeCode
+                                );
+                        }
                         propDesc = new AccessorDescriptor(null, set) { Enumerable = true, Configurable = true};
                         break;
 
@@ -677,7 +685,7 @@ namespace Jint.Runtime
                     var propIsData = propDesc.IsDataDescriptor();
                     var propIsAccessor = propDesc.IsAccessorDescriptor();
 
-                    if (_engine.Options.IsStrict() && previousIsData && propIsData)
+                    if (StrictModeScope.IsStrictModeCode && previousIsData && propIsData)
                     {
                         throw new JavaScriptException(_engine.SyntaxError);
                     }
@@ -753,7 +761,7 @@ namespace Jint.Runtime
                 propertyNameString = TypeConverter.ToString(propertyNameValue);
             }
 
-            return new Reference(baseValue, propertyNameString, _engine.Options.IsStrict());
+            return new Reference(baseValue, propertyNameString, StrictModeScope.IsStrictModeCode);
         }
 
         public object EvaluateFunctionExpression(FunctionExpression functionExpression)

+ 1 - 1
Jint/Runtime/StatementInterpreter.cs

@@ -485,7 +485,7 @@ namespace Jint.Runtime
 
         public Completion ExecuteDebuggerStatement(DebuggerStatement debuggerStatement)
         {
-            throw new System.NotImplementedException();
+            return new Completion(Completion.Normal, null, null);
         }
     }
 }

+ 34 - 0
Jint/StrictModeScope.cs

@@ -0,0 +1,34 @@
+using System;
+
+namespace Jint
+{
+    public class StrictModeScope : IDisposable
+    {
+        private readonly bool _strict;
+
+        [ThreadStatic] 
+        private static int _refCount;
+
+        public StrictModeScope(bool strict = true)
+        {
+            _strict = strict;
+            if (_strict)
+            {
+                _refCount++;
+            }
+        }
+
+        public void Dispose()
+        {
+            if (_strict)
+            {
+                _refCount--;
+            }
+        }
+
+        public static bool IsStrictModeCode
+        {
+            get { return _refCount > 0; }
+        }
+    }
+}