jscript: Treat function expressions with identifier as function declarations.
This commit is contained in:
parent
c7899cb9e8
commit
30de39b2a7
|
@ -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};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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*);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue