jscript: Treat function expressions with identifier as function declarations.

This commit is contained in:
Jacek Caban 2008-10-20 13:12:42 -07:00 committed by Alexandre Julliard
parent c7899cb9e8
commit 30de39b2a7
6 changed files with 82 additions and 68 deletions

View File

@ -941,7 +941,7 @@ HRESULT disp_propput(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexce
return hres;
}
static HRESULT jsdisp_propget_name(DispatchEx *obj, const WCHAR *name, LCID lcid, VARIANT *var,
HRESULT jsdisp_propget_name(DispatchEx *obj, const WCHAR *name, LCID lcid, VARIANT *var,
jsexcept_t *ei, IServiceProvider *caller)
{
DISPPARAMS dp = {NULL, NULL, 0, 0};

View File

@ -367,14 +367,14 @@ HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *so
DispatchEx *func_obj;
VARIANT var;
hres = create_source_function(parser, func->parameter_list, func->source_elements,
ctx->scope_chain, func->src_str, func->src_len, &func_obj);
hres = create_source_function(parser, func->expr->parameter_list, func->expr->source_elements,
ctx->scope_chain, func->expr->src_str, func->expr->src_len, &func_obj);
if(FAILED(hres))
return hres;
V_VT(&var) = VT_DISPATCH;
V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(func_obj);
hres = jsdisp_propput_name(ctx->var_disp, func->identifier, script->lcid, &var, ei, NULL);
hres = jsdisp_propput_name(ctx->var_disp, func->expr->identifier, script->lcid, &var, ei, NULL);
jsdisp_release(func_obj);
if(FAILED(hres))
return hres;
@ -1244,26 +1244,25 @@ static HRESULT assign_oper_eval(exec_ctx_t *ctx, expression_t *lexpr, expression
HRESULT function_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
{
function_expression_t *expr = (function_expression_t*)_expr;
DispatchEx *dispex;
VARIANT var;
HRESULT hres;
TRACE("\n");
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;
V_VT(&var) = VT_DISPATCH;
V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(dispex);
if(expr->identifier) {
hres = jsdisp_propput_name(ctx->var_disp, expr->identifier, ctx->parser->script->lcid, &var, ei, NULL/*FIXME*/);
if(FAILED(hres)) {
jsdisp_release(dispex);
hres = jsdisp_propget_name(ctx->var_disp, expr->identifier, ctx->parser->script->lcid, &var, ei, NULL/*FIXME*/);
if(FAILED(hres))
return hres;
}
}else {
DispatchEx *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;
V_VT(&var) = VT_DISPATCH;
V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(dispex);
}
ret->type = EXPRVAL_VARIANT;

View File

@ -17,12 +17,19 @@
*/
typedef struct _source_elements_t source_elements_t;
typedef struct _function_expression_t function_expression_t;
typedef struct _obj_literal_t {
DispatchEx *obj;
struct _obj_literal_t *next;
} obj_literal_t;
typedef struct _function_declaration_t {
function_expression_t *expr;
struct _function_declaration_t *next;
} function_declaration_t;
typedef struct _var_list_t {
const WCHAR *identifier;
@ -30,6 +37,8 @@ typedef struct _var_list_t {
} var_list_t;
typedef struct _func_stack {
function_declaration_t *func_head;
function_declaration_t *func_tail;
var_list_t *var_head;
var_list_t *var_tail;
@ -288,32 +297,21 @@ struct _parameter_t {
struct _parameter_t *next;
};
typedef struct _function_declaration_t {
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;
struct _source_elements_t {
statement_t *statement;
statement_t *statement_tail;
function_declaration_t *functions;
function_declaration_t *functions_tail;
var_list_t *variables;
};
typedef struct {
struct _function_expression_t {
expression_t expr;
const WCHAR *identifier;
parameter_t *parameter_list;
source_elements_t *source_elements;
const WCHAR *src_str;
DWORD src_len;
} function_expression_t;
};
typedef struct {
expression_t expr;

View File

@ -128,6 +128,7 @@ HRESULT disp_propput(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvide
HRESULT jsdisp_propget(DispatchEx*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_propput_name(DispatchEx*,const WCHAR*,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_propput_idx(DispatchEx*,DWORD,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_propget_name(DispatchEx*,LPCWSTR,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_propget_idx(DispatchEx*,DWORD,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_get_id(DispatchEx*,const WCHAR*,DWORD,DISPID*);

View File

@ -142,11 +142,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_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*,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*);
%}
@ -165,7 +162,6 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi
struct _element_list_t *element_list;
expression_t *expr;
const WCHAR *identifier;
function_declaration_t *function_declaration;
struct _parameter_list_t *parameter_list;
struct _property_list_t *property_list;
source_elements_t *source_elements;
@ -207,7 +203,6 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi
%type <statement> TryStatement
%type <statement> Finally
%type <statement_list> StatementList StatementList_opt
%type <function_declaration> FunctionDeclaration
%type <parameter_list> FormalParameterList FormalParameterList_opt
%type <expr> Expression Expression_opt
%type <expr> ExpressionNoIn ExpressionNoIn_opt
@ -267,13 +262,6 @@ SourceElements
: /* empty */ { $$ = new_source_elements(ctx); }
| SourceElements Statement
{ $$ = source_elements_add_statement($1, $2); }
| SourceElements FunctionDeclaration
{ $$ = source_elements_add_function($1, $2); }
/* ECMA-262 3rd Edition 13 */
FunctionDeclaration
: KFunction tIdentifier '(' FormalParameterList_opt ')' '{' FunctionBody '}'
{ $$ = new_function_declaration(ctx, $2, $4, $7, $1, $8-$1+1); }
/* ECMA-262 3rd Edition 13 */
FunctionExpression
@ -1287,6 +1275,18 @@ static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *ide
ret->src_str = src_str;
ret->src_len = src_len;
if(ret->identifier) {
function_declaration_t *decl = parser_alloc(ctx, sizeof(function_declaration_t));
decl->expr = ret;
decl->next = NULL;
if(ctx->func_stack->func_tail)
ctx->func_stack->func_tail = ctx->func_stack->func_tail->next = decl;
else
ctx->func_stack->func_head = ctx->func_stack->func_tail = decl;
}
return &ret->expr;
}
@ -1474,21 +1474,6 @@ static expression_t *new_literal_expression(parser_ctx_t *ctx, literal_t *litera
return &ret->expr;
}
static function_declaration_t *new_function_declaration(parser_ctx_t *ctx, const WCHAR *identifier,
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;
}
static source_elements_t *new_source_elements(parser_ctx_t *ctx)
{
source_elements_t *ret = parser_alloc(ctx, sizeof(source_elements_t));
@ -1508,17 +1493,6 @@ static source_elements_t *source_elements_add_statement(source_elements_t *sourc
return source_elements;
}
static source_elements_t *source_elements_add_function(source_elements_t *source_elements,
function_declaration_t *function_declaration)
{
if(source_elements->functions_tail)
source_elements->functions_tail = source_elements->functions_tail->next = function_declaration;
else
source_elements->functions = source_elements->functions_tail = function_declaration;
return source_elements;
}
statement_list_t *new_statement_list(parser_ctx_t *ctx, statement_t *statement)
{
statement_list_t *ret = parser_alloc_tmp(ctx, sizeof(statement_list_t));
@ -1539,6 +1513,7 @@ static void push_func(parser_ctx_t *ctx)
{
func_stack_t *new_func = parser_alloc_tmp(ctx, sizeof(func_stack_t));
new_func->func_head = new_func->func_tail = NULL;
new_func->var_head = new_func->var_tail = NULL;
new_func->next = ctx->func_stack;
@ -1547,6 +1522,7 @@ static void push_func(parser_ctx_t *ctx)
static source_elements_t *function_body_parsed(parser_ctx_t *ctx, source_elements_t *source)
{
source->functions = ctx->func_stack->func_head;
source->variables = ctx->func_stack->var_head;
pop_func(ctx);
@ -1555,6 +1531,7 @@ static source_elements_t *function_body_parsed(parser_ctx_t *ctx, source_element
static void program_parsed(parser_ctx_t *ctx, source_elements_t *source)
{
source->functions = ctx->func_stack->func_head;
source->variables = ctx->func_stack->var_head;
pop_func(ctx);

View File

@ -832,4 +832,43 @@ ok((Infinity != NaN) === true, "(Infinity != NaN) !== true");
ok((Infinity != NaN) === true, "(Infinity != NaN) !== true");
ok((0 == NaN) === false, "(0 === NaN) != false");
ok(typeof(testFunc2) === "function", "typeof(testFunc2) = " + typeof(testFunc2));
tmp = testFunc2(1);
ok(tmp === 2, "testFunc2(1) = " + tmp);
function testFunc2(x) { return x+1; }
ok(typeof(testFunc3) === "function", "typeof(testFunc3) = " + typeof(testFunc3));
tmp = testFunc3(1);
ok(tmp === 3, "testFunc3(1) = " + tmp);
tmp = function testFunc3(x) { return x+2; };
tmp = testFunc4(1);
ok(tmp === 5, "testFunc4(1) = " + tmp);
tmp = function testFunc4(x) { return x+3; };
tmp = testFunc4(1);
testFunc4 = 1;
ok(testFunc4 === 1, "testFunc4 = " + testFunc4);
ok(tmp === 5, "testFunc4(1) = " + tmp);
tmp = function testFunc4(x) { return x+4; };
ok(testFunc4 === 1, "testFunc4 = " + testFunc4);
function testEmbededFunctions() {
ok(typeof(testFunc5) === "function", "typeof(testFunc5) = " + typeof(testFunc5));
tmp = testFunc5(1);
ok(tmp === 3, "testFunc5(1) = " + tmp);
tmp = function testFunc5(x) { return x+2; };
tmp = testFunc6(1);
ok(tmp === 5, "testFunc6(1) = " + tmp);
tmp = function testFunc6(x) { return x+3; };
tmp = testFunc6(1);
ok(tmp === 5, "testFunc6(1) = " + tmp);
tmp = function testFunc6(x) { return x+4; };
testFunc6 = 1;
ok(testFunc6 === 1, "testFunc4 = " + testFunc6);
}
testEmbededFunctions();
reportSuccess();