Browse Source

Passing strict mode function unit tests

Sebastien Ros 12 years ago
parent
commit
0507fb9a78

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

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

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

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

+ 2 - 0
Jint.Tests.Ecma/Ecma/10.1.7.cs

@@ -1,7 +1,9 @@
+using System.ComponentModel;
 using Xunit;
 using Xunit;
 
 
 namespace Jint.Tests.Ecma
 namespace Jint.Tests.Ecma
 {
 {
+    [Trait("Category", "Pass")]
     public class Test_10_1_7 : EcmaTest
     public class Test_10_1_7 : EcmaTest
     {
     {
         [Fact]
         [Fact]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 1 - 0
Jint.Tests.Ecma/TestCases/ch10/10.1/10.1.1/10.1.1-29-s.js

@@ -8,6 +8,7 @@
 
 
 function testcase() {
 function testcase() {
         "use strict";
         "use strict";
+        debugger;
         var funObj = new Function("a", "eval('public = 1;');");
         var funObj = new Function("a", "eval('public = 1;');");
         funObj();
         funObj();
         return true;
         return true;

+ 1 - 1
Jint/Engine.cs

@@ -175,7 +175,7 @@ namespace Jint
 
 
         public object Execute(Program program)
         public object Execute(Program program)
         {
         {
-            using (new StrictModeScope(Options.IsStrict()))
+            using (new StrictModeScope(Options.IsStrict() || program.Strict))
             {
             {
                 var result = _statements.ExecuteProgram(program);
                 var result = _statements.ExecuteProgram(program);
                 if (result.Type == Completion.Throw)
                 if (result.Type == Completion.Throw)

+ 15 - 2
Jint/Native/Function/EvalFunctionInstance.cs

@@ -20,11 +20,24 @@ namespace Jint.Native.Function
             {
             {
                 throw new JavaScriptException(Engine.SyntaxError, "eval() is not allowed in strict mode.");
                 throw new JavaScriptException(Engine.SyntaxError, "eval() is not allowed in strict mode.");
             }
             }
+
             var code = TypeConverter.ToString(arguments[0]);
             var code = TypeConverter.ToString(arguments[0]);
 
 
             var parser = new JavaScriptParser();
             var parser = new JavaScriptParser();
-            var program = parser.Parse(code);
-            return _engine.ExecuteStatement(program).Value ?? Undefined.Instance;
+            try
+            {
+                var program = parser.Parse(code);
+                using (new StrictModeScope(program.Strict))
+                {
+                    return _engine.ExecuteStatement(program).Value ?? Undefined.Instance;
+                }
+            }
+            catch (ParserError e)
+            {
+                throw new JavaScriptException(Engine.SyntaxError);
+            }
+
+            
         }
         }
     }
     }
 }
 }

+ 14 - 4
Jint/Native/Function/FunctionConstructor.cs

@@ -72,12 +72,22 @@ namespace Jint.Native.Function
                 body = TypeConverter.ToString(arguments[argCount-1]);
                 body = TypeConverter.ToString(arguments[argCount-1]);
             }
             }
             body = TypeConverter.ToString(body);
             body = TypeConverter.ToString(body);
-            var parser = new JavaScriptParser();
             
             
             // todo: ensure parsable as parameter list
             // todo: ensure parsable as parameter list
             var parameters = p.Split(new [] {','}, StringSplitOptions.RemoveEmptyEntries);
             var parameters = p.Split(new [] {','}, StringSplitOptions.RemoveEmptyEntries);
-            var statements = parser.ParseFunctionBody(body);
+            var parser = new JavaScriptParser();
+            FunctionExpression function;
+            try
+            {
+                var functionExpression = "function(" + p + ") { " + body + "}";
+                function = parser.ParseFunctionExpression(functionExpression); 
+            }
+            catch (ParserError e)
+            {
+                throw new JavaScriptException(Engine.SyntaxError);
+            }
 
 
+            // todo: check if there is not a way to use the FunctionExpression directly instead of creating a FunctionDeclaration
             var functionObject = new ScriptFunctionInstance(
             var functionObject = new ScriptFunctionInstance(
                 Engine,
                 Engine,
                 new FunctionDeclaration
                 new FunctionDeclaration
@@ -86,7 +96,7 @@ namespace Jint.Native.Function
                         Body = new BlockStatement
                         Body = new BlockStatement
                             {
                             {
                                 Type = SyntaxNodes.BlockStatement,
                                 Type = SyntaxNodes.BlockStatement,
-                                Body = statements
+                                Body = new Statement[] { function.Body }
                             },
                             },
                         Parameters = parameters.Select(x => new Identifier
                         Parameters = parameters.Select(x => new Identifier
                             {
                             {
@@ -97,7 +107,7 @@ namespace Jint.Native.Function
                         VariableDeclarations = new List<VariableDeclaration>()
                         VariableDeclarations = new List<VariableDeclaration>()
                     },  
                     },  
                 LexicalEnvironment.NewDeclarativeEnvironment(Engine, Engine.ExecutionContext.LexicalEnvironment),
                 LexicalEnvironment.NewDeclarativeEnvironment(Engine, Engine.ExecutionContext.LexicalEnvironment),
-                false
+                function.Strict
                 ) { Extensible = true };
                 ) { Extensible = true };
 
 
             return functionObject;
             return functionObject;

+ 2 - 1
Jint/Native/Function/ScriptFunctionInstance.cs

@@ -58,7 +58,8 @@ namespace Jint.Native.Function
         public override object Call(object thisArg, object[] arguments)
         public override object Call(object thisArg, object[] arguments)
         {
         {
             object thisBinding;
             object thisBinding;
-            using (new StrictModeScope(Strict))
+
+            using (new StrictModeScope(Strict, true))
             {
             {
                 // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3
                 // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3
                 if (StrictModeScope.IsStrictModeCode)
                 if (StrictModeScope.IsStrictModeCode)

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

@@ -2,7 +2,7 @@ using System.Collections.Generic;
 
 
 namespace Jint.Parser.Ast
 namespace Jint.Parser.Ast
 {
 {
-    public class FunctionDeclaration : Statement, IFunctionDeclaration, IVariableScope
+    public class FunctionDeclaration : Statement, IFunctionDeclaration
     {
     {
         public FunctionDeclaration()
         public FunctionDeclaration()
         {
         {

+ 4 - 5
Jint/Parser/JavascriptParser.cs

@@ -3926,9 +3926,9 @@ namespace Jint.Parser
             return program;
             return program;
         }
         }
 
 
-        public IEnumerable<Statement> ParseFunctionBody(string code)
+        public FunctionExpression ParseFunctionExpression(string functionExpression)
         {
         {
-            _source = code;
+            _source = functionExpression;
             _index = 0;
             _index = 0;
             _lineNumber = (_source.Length > 0) ? 1 : 0;
             _lineNumber = (_source.Length > 0) ? 1 : 0;
             _lineStart = 0;
             _lineStart = 0;
@@ -3952,10 +3952,9 @@ namespace Jint.Parser
 
 
             };
             };
 
 
+            _strict = false;
             Peek();
             Peek();
-            var statement = ParseStatementList();
-            return statement;
-        
+            return ParseFunctionExpression();
         }
         }
 
 
         private class Extra
         private class Extra

+ 0 - 5
Jint/Runtime/StatementInterpreter.cs

@@ -444,11 +444,6 @@ namespace Jint.Runtime
 
 
         public Completion ExecuteProgram(Program program)
         public Completion ExecuteProgram(Program program)
         {
         {
-            if (program.Strict)
-            {
-                _engine.Options.Strict();
-            }
-
             _engine.FunctionDeclarationBindings(program, _engine.ExecutionContext.LexicalEnvironment, true, program.Strict);
             _engine.FunctionDeclarationBindings(program, _engine.ExecutionContext.LexicalEnvironment, true, program.Strict);
             _engine.VariableDeclarationBinding(program.VariableDeclarations, _engine.ExecutionContext.LexicalEnvironment.Record, true, program.Strict);
             _engine.VariableDeclarationBinding(program.VariableDeclarations, _engine.ExecutionContext.LexicalEnvironment.Record, true, program.Strict);
 
 

+ 29 - 1
Jint/StrictModeScope.cs

@@ -5,17 +5,28 @@ namespace Jint
     public class StrictModeScope : IDisposable
     public class StrictModeScope : IDisposable
     {
     {
         private readonly bool _strict;
         private readonly bool _strict;
+        private readonly bool _force;
+        private readonly int _forcedRefCount;
 
 
         [ThreadStatic] 
         [ThreadStatic] 
         private static int _refCount;
         private static int _refCount;
 
 
-        public StrictModeScope(bool strict = true)
+        public StrictModeScope(bool strict = true, bool force = false)
         {
         {
             _strict = strict;
             _strict = strict;
+            _force = force;
+
+            if (_force)
+            {
+                _forcedRefCount = _refCount;
+                _refCount = 0;
+            }
+
             if (_strict)
             if (_strict)
             {
             {
                 _refCount++;
                 _refCount++;
             }
             }
+
         }
         }
 
 
         public void Dispose()
         public void Dispose()
@@ -24,11 +35,28 @@ namespace Jint
             {
             {
                 _refCount--;
                 _refCount--;
             }
             }
+
+            if (_force)
+            {
+                _refCount = _forcedRefCount;
+            } 
         }
         }
 
 
         public static bool IsStrictModeCode
         public static bool IsStrictModeCode
         {
         {
             get { return _refCount > 0; }
             get { return _refCount > 0; }
         }
         }
+
+        public static int RefCount
+        {
+            get
+            {
+                return _refCount;
+            }
+            set
+            {
+                _refCount = value;
+            }
+        }
     }
     }
 }
 }