Commit 5760eb80 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

jscript: Added Function.toString implementation.

parent 68bd72c7
...@@ -367,7 +367,8 @@ HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *so ...@@ -367,7 +367,8 @@ HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *so
DispatchEx *func_obj; DispatchEx *func_obj;
VARIANT var; 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)) if(FAILED(hres))
return hres; return hres;
...@@ -1242,7 +1243,8 @@ HRESULT function_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD fla ...@@ -1242,7 +1243,8 @@ HRESULT function_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD fla
TRACE("\n"); 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)) if(FAILED(hres))
return hres; return hres;
......
...@@ -98,7 +98,8 @@ typedef struct _statement_t statement_t; ...@@ -98,7 +98,8 @@ typedef struct _statement_t statement_t;
typedef struct _expression_t expression_t; typedef struct _expression_t expression_t;
typedef struct _parameter_t parameter_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 { typedef struct {
VARTYPE vt; VARTYPE vt;
...@@ -277,6 +278,8 @@ typedef struct _function_declaration_t { ...@@ -277,6 +278,8 @@ typedef struct _function_declaration_t {
const WCHAR *identifier; const WCHAR *identifier;
parameter_t *parameter_list; parameter_t *parameter_list;
source_elements_t *source_elements; source_elements_t *source_elements;
const WCHAR *src_str;
DWORD src_len;
struct _function_declaration_t *next; struct _function_declaration_t *next;
} function_declaration_t; } function_declaration_t;
...@@ -293,6 +296,8 @@ typedef struct { ...@@ -293,6 +296,8 @@ typedef struct {
const WCHAR *identifier; const WCHAR *identifier;
parameter_t *parameter_list; parameter_t *parameter_list;
source_elements_t *source_elements; source_elements_t *source_elements;
const WCHAR *src_str;
DWORD src_len;
} function_expression_t; } function_expression_t;
typedef struct { typedef struct {
......
...@@ -31,6 +31,8 @@ typedef struct { ...@@ -31,6 +31,8 @@ typedef struct {
parameter_t *parameters; parameter_t *parameters;
scope_chain_t *scope_chain; scope_chain_t *scope_chain;
parser_ctx_t *parser; parser_ctx_t *parser;
const WCHAR *src_str;
DWORD src_len;
DWORD length; DWORD length;
} FunctionInstance; } FunctionInstance;
...@@ -226,6 +228,23 @@ static HRESULT invoke_value_proc(FunctionInstance *function, LCID lcid, WORD fla ...@@ -226,6 +228,23 @@ static HRESULT invoke_value_proc(FunctionInstance *function, LCID lcid, WORD fla
return hres; 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, static HRESULT Function_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{ {
...@@ -249,8 +268,30 @@ static HRESULT Function_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPA ...@@ -249,8 +268,30 @@ static HRESULT Function_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPA
static HRESULT Function_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, static HRESULT Function_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{ {
FIXME("\n"); FunctionInstance *function;
return E_NOTIMPL; 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, static HRESULT Function_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
...@@ -438,7 +479,7 @@ HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc, ...@@ -438,7 +479,7 @@ HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc,
} }
HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, source_elements_t *source, 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; FunctionInstance *function;
DispatchEx *prototype; DispatchEx *prototype;
...@@ -470,6 +511,9 @@ HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, sourc ...@@ -470,6 +511,9 @@ HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, sourc
length++; length++;
function->length = length; function->length = length;
function->src_str = src_str;
function->src_len = src_len;
*ret = &function->dispex; *ret = &function->dispex;
return S_OK; return S_OK;
} }
......
...@@ -621,7 +621,7 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars ...@@ -621,7 +621,7 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars
return hres; 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); parser_release(parser_ctx);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
......
...@@ -101,7 +101,7 @@ static int lex_error(parser_ctx_t *ctx, HRESULT hres) ...@@ -101,7 +101,7 @@ static int lex_error(parser_ctx_t *ctx, HRESULT hres)
return -1; 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 *p1 = ctx->ptr;
const WCHAR *p2 = word; const WCHAR *p2 = word;
...@@ -116,6 +116,7 @@ static int check_keyword(parser_ctx_t *ctx, const WCHAR *word) ...@@ -116,6 +116,7 @@ static int check_keyword(parser_ctx_t *ctx, const WCHAR *word)
if(*p2 || (p1 < ctx->end && isalnumW(*p1))) if(*p2 || (p1 < ctx->end && isalnumW(*p1)))
return 1; return 1;
*lval = ctx->ptr;
ctx->ptr = p1; ctx->ptr = p1;
return 0; return 0;
} }
...@@ -145,14 +146,14 @@ static int hex_to_int(WCHAR c) ...@@ -145,14 +146,14 @@ static int hex_to_int(WCHAR c)
return -1; 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; int min = 0, max = sizeof(keywords)/sizeof(keywords[0])-1, r, i;
while(min <= max) { while(min <= max) {
i = (min+max)/2; i = (min+max)/2;
r = check_keyword(ctx, keywords[i].word); r = check_keyword(ctx, keywords[i].word, lval);
if(!r) if(!r)
return keywords[i].token; return keywords[i].token;
...@@ -468,7 +469,7 @@ int parser_lex(void *lval, parser_ctx_t *ctx) ...@@ -468,7 +469,7 @@ int parser_lex(void *lval, parser_ctx_t *ctx)
}while(skip_comment(ctx)); }while(skip_comment(ctx));
if(isalphaW(*ctx->ptr)) { if(isalphaW(*ctx->ptr)) {
ret = check_keywords(ctx); ret = check_keywords(ctx, lval);
if(ret) if(ret)
return ret; return ret;
...@@ -480,7 +481,6 @@ int parser_lex(void *lval, parser_ctx_t *ctx) ...@@ -480,7 +481,6 @@ int parser_lex(void *lval, parser_ctx_t *ctx)
switch(*ctx->ptr) { switch(*ctx->ptr) {
case '{': case '{':
case '}':
case '(': case '(':
case ')': case ')':
case '[': case '[':
...@@ -492,6 +492,10 @@ int parser_lex(void *lval, parser_ctx_t *ctx) ...@@ -492,6 +492,10 @@ int parser_lex(void *lval, parser_ctx_t *ctx)
case ':': case ':':
return *ctx->ptr++; return *ctx->ptr++;
case '}':
*(const WCHAR**)lval = ctx->ptr++;
return '}';
case '.': case '.':
if(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) if(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
return parse_double_literal(ctx, 0, lval); return parse_double_literal(ctx, 0, lval);
......
...@@ -120,7 +120,8 @@ typedef struct _parameter_list_t { ...@@ -120,7 +120,8 @@ typedef struct _parameter_list_t {
static parameter_list_t *new_parameter_list(parser_ctx_t*,const WCHAR*); 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 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_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_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*); static expression_t *new_conditional_expression(parser_ctx_t*,expression_t*,expression_t*,expression_t*);
...@@ -134,7 +135,8 @@ static expression_t *new_literal_expression(parser_ctx_t*,literal_t*); ...@@ -134,7 +135,8 @@ static expression_t *new_literal_expression(parser_ctx_t*,literal_t*);
static expression_t *new_array_literal_expression(parser_ctx_t*,element_list_t*,int); 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 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 *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_statement(source_elements_t*,statement_t*);
static source_elements_t *source_elements_add_function(source_elements_t*,function_declaration_t*); static source_elements_t *source_elements_add_function(source_elements_t*,function_declaration_t*);
...@@ -146,6 +148,7 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi ...@@ -146,6 +148,7 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi
%union { %union {
int ival; int ival;
const WCHAR *srcptr;
LPCWSTR wstr; LPCWSTR wstr;
literal_t *literal; literal_t *literal;
struct _argument_list_t *argument_list; struct _argument_list_t *argument_list;
...@@ -166,10 +169,12 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi ...@@ -166,10 +169,12 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi
} }
/* keywords */ /* 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 kINSTANCEOF kNEW kNULL kUNDEFINED kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE kTRY kTYPEOF kVAR kVOID kWHILE kWITH
%token tANDAND tOROR tINC tDEC %token tANDAND tOROR tINC tDEC
%token <srcptr> kFUNCTION '}'
/* tokens */ /* tokens */
%token <identifier> tIdentifier %token <identifier> tIdentifier
%token <ival> tAssignOper tEqOper tShiftOper tRelOper %token <ival> tAssignOper tEqOper tShiftOper tRelOper
...@@ -257,12 +262,12 @@ SourceElements ...@@ -257,12 +262,12 @@ SourceElements
/* ECMA-262 3rd Edition 13 */ /* ECMA-262 3rd Edition 13 */
FunctionDeclaration FunctionDeclaration
: kFUNCTION tIdentifier '(' FormalParameterList_opt ')' '{' FunctionBody '}' : 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 */ /* ECMA-262 3rd Edition 13 */
FunctionExpression FunctionExpression
: kFUNCTION Identifier_opt '(' FormalParameterList_opt ')' '{' FunctionBody '}' : 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 */ /* ECMA-262 3rd Edition 13 */
FunctionBody FunctionBody
...@@ -1247,7 +1252,7 @@ static parameter_list_t *parameter_list_add(parser_ctx_t *ctx, parameter_list_t ...@@ -1247,7 +1252,7 @@ static parameter_list_t *parameter_list_add(parser_ctx_t *ctx, parameter_list_t
} }
static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier, 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)); function_expression_t *ret = parser_alloc(ctx, sizeof(function_expression_t));
...@@ -1255,6 +1260,8 @@ static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *ide ...@@ -1255,6 +1260,8 @@ static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *ide
ret->identifier = identifier; ret->identifier = identifier;
ret->parameter_list = parameter_list ? parameter_list->head : NULL; ret->parameter_list = parameter_list ? parameter_list->head : NULL;
ret->source_elements = source_elements; ret->source_elements = source_elements;
ret->src_str = src_str;
ret->src_len = src_len;
return &ret->expr; return &ret->expr;
} }
...@@ -1444,13 +1451,15 @@ static expression_t *new_literal_expression(parser_ctx_t *ctx, literal_t *litera ...@@ -1444,13 +1451,15 @@ static expression_t *new_literal_expression(parser_ctx_t *ctx, literal_t *litera
} }
static function_declaration_t *new_function_declaration(parser_ctx_t *ctx, const WCHAR *identifier, 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)); function_declaration_t *ret = parser_alloc(ctx, sizeof(function_declaration_t));
ret->identifier = identifier; ret->identifier = identifier;
ret->parameter_list = parameter_list ? parameter_list->head : NULL; ret->parameter_list = parameter_list ? parameter_list->head : NULL;
ret->source_elements = source_elements; ret->source_elements = source_elements;
ret->src_str = src_str;
ret->src_len = src_len;
ret->next = NULL; ret->next = NULL;
return ret; return ret;
......
...@@ -315,4 +315,18 @@ ok(tmp === 2, "Math.pow(2, 2) = " + tmp); ...@@ -315,4 +315,18 @@ ok(tmp === 2, "Math.pow(2, 2) = " + tmp);
tmp = Math.pow(2, 2, 3); tmp = Math.pow(2, 2, 3);
ok(tmp === 4, "Math.pow(2, 2, 3) = " + tmp); 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(); reportSuccess();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment