jscript: Added Function.toString implementation.
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c
index 5337b24..bc0b525 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -367,7 +367,8 @@
DispatchEx *func_obj;
VARIANT var;
- hres = create_source_function(parser, func->parameter_list, func->source_elements, ctx->scope_chain, &func_obj);
+ hres = create_source_function(parser, func->parameter_list, func->source_elements,
+ ctx->scope_chain, func->src_str, func->src_len, &func_obj);
if(FAILED(hres))
return hres;
@@ -1242,7 +1243,8 @@
TRACE("\n");
- hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain, &dispex);
+ hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain,
+ expr->src_str, expr->src_len, &dispex);
if(FAILED(hres))
return hres;
diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h
index 3f7fda8..beabc9b 100644
--- a/dlls/jscript/engine.h
+++ b/dlls/jscript/engine.h
@@ -98,7 +98,8 @@
typedef struct _expression_t expression_t;
typedef struct _parameter_t parameter_t;
-HRESULT create_source_function(parser_ctx_t*,parameter_t*,source_elements_t*,scope_chain_t*,DispatchEx**);
+HRESULT create_source_function(parser_ctx_t*,parameter_t*,source_elements_t*,scope_chain_t*,
+ const WCHAR*,DWORD,DispatchEx**);
typedef struct {
VARTYPE vt;
@@ -277,6 +278,8 @@
const WCHAR *identifier;
parameter_t *parameter_list;
source_elements_t *source_elements;
+ const WCHAR *src_str;
+ DWORD src_len;
struct _function_declaration_t *next;
} function_declaration_t;
@@ -293,6 +296,8 @@
const WCHAR *identifier;
parameter_t *parameter_list;
source_elements_t *source_elements;
+ const WCHAR *src_str;
+ DWORD src_len;
} function_expression_t;
typedef struct {
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c
index 7d39ad0..c0ba1e2 100644
--- a/dlls/jscript/function.c
+++ b/dlls/jscript/function.c
@@ -31,6 +31,8 @@
parameter_t *parameters;
scope_chain_t *scope_chain;
parser_ctx_t *parser;
+ const WCHAR *src_str;
+ DWORD src_len;
DWORD length;
} FunctionInstance;
@@ -226,6 +228,23 @@
return hres;
}
+static HRESULT function_to_string(FunctionInstance *function, BSTR *ret)
+{
+ BSTR str;
+
+ if(function->value_proc) {
+ FIXME("Builtin functions not implemented\n");
+ return E_NOTIMPL;
+ }
+
+ str = SysAllocStringLen(function->src_str, function->src_len);
+ if(!str)
+ return E_OUTOFMEMORY;
+
+ *ret = str;
+ return S_OK;
+}
+
static HRESULT Function_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
@@ -249,8 +268,30 @@
static HRESULT Function_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
- FIXME("\n");
- return E_NOTIMPL;
+ FunctionInstance *function;
+ BSTR str;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ if(!is_class(dispex, JSCLASS_FUNCTION)) {
+ FIXME("throw TypeError\n");
+ return E_FAIL;
+ }
+
+ function = (FunctionInstance*)dispex;
+
+ hres = function_to_string(function, &str);
+ if(FAILED(hres))
+ return hres;
+
+ if(retv) {
+ V_VT(retv) = VT_BSTR;
+ V_BSTR(retv) = str;
+ }else {
+ SysFreeString(str);
+ }
+ return S_OK;
}
static HRESULT Function_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -438,7 +479,7 @@
}
HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, source_elements_t *source,
- scope_chain_t *scope_chain, DispatchEx **ret)
+ scope_chain_t *scope_chain, const WCHAR *src_str, DWORD src_len, DispatchEx **ret)
{
FunctionInstance *function;
DispatchEx *prototype;
@@ -470,6 +511,9 @@
length++;
function->length = length;
+ function->src_str = src_str;
+ function->src_len = src_len;
+
*ret = &function->dispex;
return S_OK;
}
diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c
index 7c7def0..3730661 100644
--- a/dlls/jscript/jscript.c
+++ b/dlls/jscript/jscript.c
@@ -621,7 +621,7 @@
return hres;
}
- hres = create_source_function(parser_ctx, NULL, parser_ctx->source, NULL, &dispex);
+ hres = create_source_function(parser_ctx, NULL, parser_ctx->source, NULL, NULL, 0, &dispex);
parser_release(parser_ctx);
if(FAILED(hres))
return hres;
diff --git a/dlls/jscript/lex.c b/dlls/jscript/lex.c
index ba80154..4ad9fe5 100644
--- a/dlls/jscript/lex.c
+++ b/dlls/jscript/lex.c
@@ -101,7 +101,7 @@
return -1;
}
-static int check_keyword(parser_ctx_t *ctx, const WCHAR *word)
+static int check_keyword(parser_ctx_t *ctx, const WCHAR *word, const WCHAR **lval)
{
const WCHAR *p1 = ctx->ptr;
const WCHAR *p2 = word;
@@ -116,6 +116,7 @@
if(*p2 || (p1 < ctx->end && isalnumW(*p1)))
return 1;
+ *lval = ctx->ptr;
ctx->ptr = p1;
return 0;
}
@@ -145,14 +146,14 @@
return -1;
}
-static int check_keywords(parser_ctx_t *ctx)
+static int check_keywords(parser_ctx_t *ctx, const WCHAR **lval)
{
int min = 0, max = sizeof(keywords)/sizeof(keywords[0])-1, r, i;
while(min <= max) {
i = (min+max)/2;
- r = check_keyword(ctx, keywords[i].word);
+ r = check_keyword(ctx, keywords[i].word, lval);
if(!r)
return keywords[i].token;
@@ -468,7 +469,7 @@
}while(skip_comment(ctx));
if(isalphaW(*ctx->ptr)) {
- ret = check_keywords(ctx);
+ ret = check_keywords(ctx, lval);
if(ret)
return ret;
@@ -480,7 +481,6 @@
switch(*ctx->ptr) {
case '{':
- case '}':
case '(':
case ')':
case '[':
@@ -492,6 +492,10 @@
case ':':
return *ctx->ptr++;
+ case '}':
+ *(const WCHAR**)lval = ctx->ptr++;
+ return '}';
+
case '.':
if(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
return parse_double_literal(ctx, 0, lval);
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y
index c7c6fb4..96ca9e5 100644
--- a/dlls/jscript/parser.y
+++ b/dlls/jscript/parser.y
@@ -120,7 +120,8 @@
static parameter_list_t *new_parameter_list(parser_ctx_t*,const WCHAR*);
static parameter_list_t *parameter_list_add(parser_ctx_t*,parameter_list_t*,const WCHAR*);
-static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*,source_elements_t*);
+static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*,
+ source_elements_t*,const WCHAR*,DWORD);
static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expression_t*,expression_t*);
static expression_t *new_unary_expression(parser_ctx_t*,expression_type_t,expression_t*);
static expression_t *new_conditional_expression(parser_ctx_t*,expression_t*,expression_t*,expression_t*);
@@ -134,7 +135,8 @@
static expression_t *new_array_literal_expression(parser_ctx_t*,element_list_t*,int);
static expression_t *new_prop_and_value_expression(parser_ctx_t*,property_list_t*);
-static function_declaration_t *new_function_declaration(parser_ctx_t*,const WCHAR*,parameter_list_t*,source_elements_t*);
+static function_declaration_t *new_function_declaration(parser_ctx_t*,const WCHAR*,parameter_list_t*,
+ source_elements_t*,const WCHAR*,DWORD);
static source_elements_t *new_source_elements(parser_ctx_t*);
static source_elements_t *source_elements_add_statement(source_elements_t*,statement_t*);
static source_elements_t *source_elements_add_function(source_elements_t*,function_declaration_t*);
@@ -146,6 +148,7 @@
%union {
int ival;
+ const WCHAR *srcptr;
LPCWSTR wstr;
literal_t *literal;
struct _argument_list_t *argument_list;
@@ -166,10 +169,12 @@
}
/* keywords */
-%token kBREAK kCASE kCATCH kCONTINUE kDEFAULT kDELETE kDO kELSE kIF kFINALLY kFOR kFUNCTION kIN
+%token kBREAK kCASE kCATCH kCONTINUE kDEFAULT kDELETE kDO kELSE kIF kFINALLY kFOR kIN
%token kINSTANCEOF kNEW kNULL kUNDEFINED kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE kTRY kTYPEOF kVAR kVOID kWHILE kWITH
%token tANDAND tOROR tINC tDEC
+%token <srcptr> kFUNCTION '}'
+
/* tokens */
%token <identifier> tIdentifier
%token <ival> tAssignOper tEqOper tShiftOper tRelOper
@@ -257,12 +262,12 @@
/* ECMA-262 3rd Edition 13 */
FunctionDeclaration
: kFUNCTION tIdentifier '(' FormalParameterList_opt ')' '{' FunctionBody '}'
- { $$ = new_function_declaration(ctx, $2, $4, $7); }
+ { $$ = new_function_declaration(ctx, $2, $4, $7, $1, $8-$1+1); }
/* ECMA-262 3rd Edition 13 */
FunctionExpression
: kFUNCTION Identifier_opt '(' FormalParameterList_opt ')' '{' FunctionBody '}'
- { $$ = new_function_expression(ctx, $2, $4, $7); }
+ { $$ = new_function_expression(ctx, $2, $4, $7, $1, $8-$1+1); }
/* ECMA-262 3rd Edition 13 */
FunctionBody
@@ -1247,7 +1252,7 @@
}
static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier,
- parameter_list_t *parameter_list, source_elements_t *source_elements)
+ parameter_list_t *parameter_list, source_elements_t *source_elements, const WCHAR *src_str, DWORD src_len)
{
function_expression_t *ret = parser_alloc(ctx, sizeof(function_expression_t));
@@ -1255,6 +1260,8 @@
ret->identifier = identifier;
ret->parameter_list = parameter_list ? parameter_list->head : NULL;
ret->source_elements = source_elements;
+ ret->src_str = src_str;
+ ret->src_len = src_len;
return &ret->expr;
}
@@ -1444,13 +1451,15 @@
}
static function_declaration_t *new_function_declaration(parser_ctx_t *ctx, const WCHAR *identifier,
- parameter_list_t *parameter_list, source_elements_t *source_elements)
+ parameter_list_t *parameter_list, source_elements_t *source_elements, const WCHAR *src_str, DWORD src_len)
{
function_declaration_t *ret = parser_alloc(ctx, sizeof(function_declaration_t));
ret->identifier = identifier;
ret->parameter_list = parameter_list ? parameter_list->head : NULL;
ret->source_elements = source_elements;
+ ret->src_str = src_str;
+ ret->src_len = src_len;
ret->next = NULL;
return ret;
diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js
index d590308..4084241 100644
--- a/dlls/jscript/tests/api.js
+++ b/dlls/jscript/tests/api.js
@@ -315,4 +315,18 @@
tmp = Math.pow(2, 2, 3);
ok(tmp === 4, "Math.pow(2, 2, 3) = " + tmp);
+var func = function (a) {
+ var a = 1;
+ if(a) return;
+ }.toString();
+ok(func.toString() === "function (a) {\n var a = 1;\n if(a) return;\n }",
+ "func.toString() = " + func.toString());
+
+function testFuncToString(x,y) {
+ return x+y;
+}
+
+ok(testFuncToString.toString() === "function testFuncToString(x,y) {\n return x+y;\n}",
+ "testFuncToString.toString() = " + testFuncToString.toString());
+
reportSuccess();