Browse Source

Implementing Function(p1,p2, ..., body)

Sebastien Ros 12 years ago
parent
commit
0765117106

+ 8 - 0
Jint.Tests.Ecma/EcmaTest.cs

@@ -21,12 +21,20 @@ namespace Jint.Tests.Ecma
         }
 
         private const string Driver = @"
+            function fnGlobalObject() {
+                return Function('return this')();
+            }
+
             function runTestCase(f) {
                 if(!f()) $ERROR('');
             }
         ";
 
         private const string NegativeDriver = @"
+            function fnGlobalObject() {
+                return Function('return this')();
+            }
+
             function runTestCase(f) {
                 if(f()) $ERROR('');
             }

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

@@ -1,6 +1,8 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using Jint.Native.Object;
+using Jint.Parser;
 using Jint.Parser.Ast;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
@@ -49,11 +51,57 @@ namespace Jint.Native.Function
 
         public ObjectInstance Construct(object[] arguments)
         {
-            var instance = new FunctionShim(Engine, null, Engine.GlobalEnvironment);
-            instance.Extensible = true;
-            instance.DefineOwnProperty("constructor", new DataDescriptor(Prototype) { Writable = true, Enumerable = false, Configurable = false }, false);
+            var argCount = arguments.Length;
+            string p = "";
+            string body = "";
 
-            return instance;
+            if (argCount == 1)
+            {
+                body = TypeConverter.ToString(arguments[0]);
+            }
+            else if (argCount > 1)
+            {
+                var firstArg = arguments[0];
+                p = TypeConverter.ToString(firstArg);
+                for (var k = 1; k < argCount - 1; k++)
+                {
+                    var nextArg = arguments[k];
+                    p += "," + TypeConverter.ToString(nextArg);
+                }
+
+                body = TypeConverter.ToString(arguments[argCount-1]);
+            }
+            body = TypeConverter.ToString(body);
+            var parser = new JavaScriptParser();
+            
+            // todo: ensure parsable as parameter list
+            var parameters = p.Split(new [] {','}, StringSplitOptions.RemoveEmptyEntries);
+            var statements = parser.ParseFunctionBody(body);
+
+            var functionObject = new ScriptFunctionInstance(
+                Engine,
+                new FunctionDeclaration
+                    {
+                        Type = SyntaxNodes.FunctionDeclaration,
+                        Body = new BlockStatement
+                            {
+                                Type = SyntaxNodes.BlockStatement,
+                                Body = statements
+                            },
+                        Parameters = parameters.Select(x => new Identifier
+                            {
+                                Type = SyntaxNodes.Identifier,
+                                Name = x
+                            }),
+                        FunctionDeclarations = new List<FunctionDeclaration>(),
+                        VariableDeclarations = new List<VariableDeclaration>()
+                    },  
+                LexicalEnvironment.NewDeclarativeEnvironment(Engine, Engine.ExecutionContext.LexicalEnvironment),
+                false
+                ) { Extensible = true };
+
+            return functionObject;
+            
         }
 
         /// <summary>

+ 45 - 13
Jint/Parser/JavascriptParser.cs

@@ -3845,22 +3845,22 @@ namespace Jint.Parser
             _length = _source.Length;
             _lookahead = null;
             _state = new State
-                {
-                    AllowIn = true,
-                    LabelSet = new HashSet<string>(),
-                    InFunctionBody = false,
-                    InIteration = false,
-                    InSwitch = false,
-                    LastCommentStart = -1,
-                    MarkerStack = new Stack<int>()
-                };
+            {
+                AllowIn = true,
+                LabelSet = new HashSet<string>(),
+                InFunctionBody = false,
+                InIteration = false,
+                InSwitch = false,
+                LastCommentStart = -1,
+                MarkerStack = new Stack<int>()
+            };
 
             _extra = new Extra
-                {
-                    Range = new int[0], 
-                    Loc = 0,
+            {
+                Range = new int[0],
+                Loc = 0,
 
-                };
+            };
 
             if (options != null)
             {
@@ -3912,6 +3912,38 @@ namespace Jint.Parser
             return program;
         }
 
+        public IEnumerable<Statement> ParseFunctionBody(string code)
+        {
+            _source = code;
+            _index = 0;
+            _lineNumber = (_source.Length > 0) ? 1 : 0;
+            _lineStart = 0;
+            _length = _source.Length;
+            _lookahead = null;
+            _state = new State
+            {
+                AllowIn = true,
+                LabelSet = new HashSet<string>(),
+                InFunctionBody = true,
+                InIteration = false,
+                InSwitch = false,
+                LastCommentStart = -1,
+                MarkerStack = new Stack<int>()
+            };
+
+            _extra = new Extra
+            {
+                Range = new int[0],
+                Loc = 0,
+
+            };
+
+            Peek();
+            var statement = ParseStatementList();
+            return statement;
+        
+        }
+
         private class Extra
         {
             public int? Loc;