sync jscript with wine 1.1.27

svn path=/trunk/; revision=42496
This commit is contained in:
Christoph von Wittich 2009-08-08 07:34:09 +00:00
parent 2a10e77d03
commit 23d4ad046d
30 changed files with 3440 additions and 1336 deletions

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <math.h>
#include "jscript.h"
#include "wine/debug.h"
@ -40,7 +42,6 @@ static const WCHAR sortW[] = {'s','o','r','t',0};
static const WCHAR spliceW[] = {'s','p','l','i','c','e',0};
static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
static const WCHAR unshiftW[] = {'u','n','s','h','i','f','t',0};
static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p','e','r','t','y',0};
static const WCHAR propertyIsEnumerableW[] =
@ -61,6 +62,30 @@ static HRESULT Array_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
V_VT(retv) = VT_I4;
V_I4(retv) = This->length;
break;
case DISPATCH_PROPERTYPUT: {
VARIANT num;
DOUBLE len = -1;
DWORD i;
HRESULT hres;
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &num);
if(V_VT(&num) == VT_I4)
len = V_I4(&num);
else
len = floor(V_R8(&num));
if(len!=(DWORD)len)
return throw_range_error(dispex->ctx, ei, IDS_INVALID_LENGTH, NULL);
for(i=len; i<This->length; i++) {
hres = jsdisp_delete_idx(dispex, i);
if(FAILED(hres))
return hres;
}
This->length = len;
break;
}
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
@ -394,8 +419,81 @@ static HRESULT Array_shift(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS
static HRESULT Array_slice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
DispatchEx *arr;
VARIANT v;
DOUBLE range;
DWORD length, start, end, idx;
HRESULT hres;
TRACE("\n");
if(is_class(dispex, JSCLASS_ARRAY)) {
length = ((ArrayInstance*)dispex)->length;
}else {
FIXME("not Array this\n");
return E_NOTIMPL;
}
if(arg_cnt(dp)) {
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
if(FAILED(hres))
return hres;
if(V_VT(&v) == VT_I4)
range = V_I4(&v);
else
range = floor(V_R8(&v));
if(-range>length || isnan(range)) start = 0;
else if(range < 0) start = range+length;
else if(range <= length) start = range;
else start = length;
}
else start = 0;
if(arg_cnt(dp)>1) {
hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &v);
if(FAILED(hres))
return hres;
if(V_VT(&v) == VT_I4)
range = V_I4(&v);
else
range = floor(V_R8(&v));
if(-range>length) end = 0;
else if(range < 0) end = range+length;
else if(range <= length) end = range;
else end = length;
}
else end = length;
hres = create_array(dispex->ctx, (end>start)?end-start:0, &arr);
if(FAILED(hres))
return hres;
for(idx=start; idx<end; idx++) {
hres = jsdisp_propget_idx(dispex, idx, lcid, &v, ei, sp);
if(hres == DISP_E_UNKNOWNNAME)
continue;
if(SUCCEEDED(hres))
hres = jsdisp_propput_idx(arr, idx-start, lcid, &v, ei, sp);
if(FAILED(hres)) {
jsdisp_release(arr);
return hres;
}
}
if(retv) {
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(arr);
}
else
jsdisp_release(arr);
return S_OK;
}
static HRESULT sort_cmp(script_ctx_t *ctx, DispatchEx *cmp_func, VARIANT *v1, VARIANT *v2, jsexcept_t *ei,
@ -638,13 +736,6 @@ static HRESULT Array_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, D
return E_NOTIMPL;
}
static HRESULT Array_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_unshift(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
@ -679,6 +770,8 @@ static HRESULT Array_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS
TRACE("\n");
switch(flags) {
case INVOKE_FUNC:
return throw_type_error(dispex->ctx, ei, IDS_NOT_FUNC, NULL);
case INVOKE_PROPERTYGET:
return array_join(dispex, lcid, ((ArrayInstance*)dispex)->length, default_separatorW, retv, ei, sp);
default:
@ -732,7 +825,6 @@ static const builtin_prop_t Array_props[] = {
{toLocaleStringW, Array_toLocaleString, PROPF_METHOD},
{toStringW, Array_toString, PROPF_METHOD},
{unshiftW, Array_unshift, PROPF_METHOD},
{valueOfW, Array_valueOf, PROPF_METHOD}
};
static const builtin_info_t Array_info = {
@ -755,12 +847,11 @@ static HRESULT ArrayConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISP
TRACE("\n");
switch(flags) {
case DISPATCH_METHOD:
case DISPATCH_CONSTRUCT: {
if(arg_cnt(dp) == 1 && V_VT((arg_var = get_arg(dp, 0))) == VT_I4) {
if(V_I4(arg_var) < 0) {
FIXME("throw RangeError\n");
return E_FAIL;
}
if(V_I4(arg_var) < 0)
return throw_range_error(dispex->ctx, ei, IDS_INVALID_LENGTH, NULL);
hres = create_array(dispex->ctx, V_I4(arg_var), &obj);
if(FAILED(hres))
@ -809,7 +900,7 @@ static HRESULT alloc_array(script_ctx_t *ctx, BOOL use_constr, ArrayInstance **r
if(use_constr)
hres = init_dispex_from_constr(&array->dispex, ctx, &Array_info, ctx->array_constr);
else
hres = init_dispex(&array->dispex, ctx, &Array_info, NULL);
hres = init_dispex_from_constr(&array->dispex, ctx, &Array_info, ctx->object_constr);
if(FAILED(hres)) {
heap_free(array);

View file

@ -1,5 +1,6 @@
/*
* Copyright 2008 Jacek Caban for CodeWeavers
* Copyright 2009 Piotr Caban
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -36,25 +37,59 @@ static const WCHAR propertyIsEnumerableW[] =
{'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
/* ECMA-262 3rd Edition 15.6.4.2 */
static HRESULT Bool_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
static const WCHAR trueW[] = {'t','r','u','e',0};
static const WCHAR falseW[] = {'f','a','l','s','e',0};
TRACE("\n");
if(!is_class(dispex, JSCLASS_BOOLEAN))
return throw_type_error(dispex->ctx, ei, IDS_NOT_BOOL, NULL);
if(retv) {
BoolInstance *bool = (BoolInstance*)dispex;
BSTR val;
if(bool->val) val = SysAllocString(trueW);
else val = SysAllocString(falseW);
if(!val)
return E_OUTOFMEMORY;
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = val;
}
return S_OK;
}
static HRESULT Bool_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
TRACE("\n");
return Bool_toString(dispex, lcid, flags, dp, retv, ei, sp);
}
/* ECMA-262 3rd Edition 15.6.4.3 */
static HRESULT Bool_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
TRACE("\n");
if(!is_class(dispex, JSCLASS_BOOLEAN))
return throw_type_error(dispex->ctx, ei, IDS_NOT_BOOL, NULL);
if(retv) {
BoolInstance *bool = (BoolInstance*)dispex;
V_VT(retv) = VT_BOOL;
V_BOOL(retv) = bool->val;
}
return S_OK;
}
static HRESULT Bool_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@ -81,8 +116,18 @@ static HRESULT Bool_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DIS
static HRESULT Bool_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
TRACE("\n");
switch(flags) {
case INVOKE_FUNC:
return throw_type_error(dispex->ctx, ei, IDS_NOT_FUNC, NULL);
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
return S_OK;
}
static const builtin_prop_t Bool_props[] = {
@ -106,8 +151,41 @@ static const builtin_info_t Bool_info = {
static HRESULT BoolConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
HRESULT hres;
VARIANT_BOOL value = VARIANT_FALSE;
if(arg_cnt(dp)) {
hres = to_boolean(get_arg(dp,0), &value);
if(FAILED(hres))
return hres;
}
switch(flags) {
case DISPATCH_CONSTRUCT: {
DispatchEx *bool;
hres = create_bool(dispex->ctx, value, &bool);
if(FAILED(hres))
return hres;
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(bool);
return S_OK;
}
case INVOKE_FUNC:
if(retv) {
V_VT(retv) = VT_BOOL;
V_BOOL(retv) = value;
}
return S_OK;
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
return S_OK;
}
static HRESULT alloc_bool(script_ctx_t *ctx, BOOL use_constr, BoolInstance **ret)

File diff suppressed because it is too large Load diff

View file

@ -828,7 +828,7 @@ HRESULT jsdisp_call_value(DispatchEx *disp, LCID lcid, WORD flags, DISPPARAMS *d
return disp->builtin_info->value_prop.invoke(disp, lcid, flags, dp, retv, ei, caller);
}
static HRESULT jsdisp_call(DispatchEx *disp, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv,
HRESULT jsdisp_call(DispatchEx *disp, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv,
jsexcept_t *ei, IServiceProvider *caller)
{
dispex_prop_t *prop;
@ -1010,3 +1010,19 @@ HRESULT disp_propget(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexce
return hres;
}
HRESULT jsdisp_delete_idx(DispatchEx *obj, DWORD idx)
{
static const WCHAR formatW[] = {'%','d',0};
WCHAR buf[12];
dispex_prop_t *prop;
HRESULT hres;
sprintfW(buf, formatW, idx);
hres = find_prop_name(obj, buf, &prop);
if(FAILED(hres) || !prop)
return hres;
return delete_prop(prop);
}

View file

@ -179,6 +179,8 @@ HRESULT create_exec_ctx(IDispatch *this_obj, DispatchEx *var_disp, scope_chain_t
if(!ctx)
return E_OUTOFMEMORY;
ctx->ref = 1;
IDispatch_AddRef(this_obj);
ctx->this_obj = this_obj;
@ -230,10 +232,8 @@ static HRESULT disp_get_id(IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
/* ECMA-262 3rd Edition 8.7.2 */
static HRESULT put_value(script_ctx_t *ctx, exprval_t *ref, VARIANT *v, jsexcept_t *ei)
{
if(ref->type != EXPRVAL_IDREF) {
FIXME("throw ReferemceError\n");
return E_FAIL;
}
if(ref->type != EXPRVAL_IDREF)
return throw_reference_error(ctx, ei, IDS_ILLEGAL_ASSIGN, NULL);
return disp_propput(ref->u.idref.disp, ref->u.idref.id, ctx->lcid, v, ei, NULL/*FIXME*/);
}
@ -304,7 +304,12 @@ static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
*ret = V_R8(lval) == V_R8(rval);
break;
case VT_BSTR:
*ret = !strcmpW(V_BSTR(lval), V_BSTR(rval));
if(!V_BSTR(lval))
*ret = SysStringLen(V_BSTR(rval))?FALSE:TRUE;
else if(!V_BSTR(rval))
*ret = SysStringLen(V_BSTR(lval))?FALSE:TRUE;
else
*ret = !strcmpW(V_BSTR(lval), V_BSTR(rval));
break;
case VT_DISPATCH:
return disp_cmp(V_DISPATCH(lval), V_DISPATCH(rval), ret);
@ -431,7 +436,7 @@ HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *so
}
/* ECMA-262 3rd Edition 10.1.4 */
static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, exprval_t *ret)
static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, jsexcept_t *ei, exprval_t *ret)
{
scope_chain_t *scope;
named_item_t *item;
@ -516,8 +521,7 @@ static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, ex
return S_OK;
}
WARN("Could not find identifier %s\n", debugstr_w(identifier));
return E_FAIL;
return throw_type_error(ctx->var_disp->ctx, ei, IDS_UNDEFINED, identifier);
}
/* ECMA-262 3rd Edition 12.1 */
@ -853,7 +857,7 @@ HRESULT forin_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t
TRACE("iter %s\n", debugstr_w(str));
if(stat->variable)
hres = identifier_eval(ctx, identifier, 0, &exprval);
hres = identifier_eval(ctx, identifier, 0, NULL, &exprval);
else
hres = expr_eval(ctx, stat->expr, EXPR_NEWREF, &rt->ei, &exprval);
if(SUCCEEDED(hres)) {
@ -1536,11 +1540,16 @@ HRESULT call_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags,
hres = args_to_param(ctx, expr->argument_list, ei, &dp);
if(SUCCEEDED(hres)) {
switch(exprval.type) {
case EXPRVAL_VARIANT:
if(V_VT(&exprval.u.var) != VT_DISPATCH)
return throw_type_error(ctx->var_disp->ctx, ei, IDS_NO_PROPERTY, NULL);
hres = disp_call(V_DISPATCH(&exprval.u.var), DISPID_VALUE, ctx->parser->script->lcid,
DISPATCH_METHOD, &dp, flags & EXPR_NOVAL ? NULL : &var, ei, NULL/*FIXME*/);
break;
case EXPRVAL_IDREF:
hres = disp_call(exprval.u.idref.disp, exprval.u.idref.id, ctx->parser->script->lcid, DISPATCH_METHOD,
&dp, flags & EXPR_NOVAL ? NULL : &var, ei, NULL/*FIXME*/);
if(flags & EXPR_NOVAL)
V_VT(&var) = VT_EMPTY;
hres = disp_call(exprval.u.idref.disp, exprval.u.idref.id, ctx->parser->script->lcid,
DISPATCH_METHOD, &dp, flags & EXPR_NOVAL ? NULL : &var, ei, NULL/*FIXME*/);
break;
default:
FIXME("unimplemented type %d\n", exprval.type);
@ -1554,9 +1563,13 @@ HRESULT call_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags,
if(FAILED(hres))
return hres;
TRACE("= %s\n", debugstr_variant(&var));
ret->type = EXPRVAL_VARIANT;
ret->u.var = var;
if(flags & EXPR_NOVAL) {
V_VT(&ret->u.var) = VT_EMPTY;
}else {
TRACE("= %s\n", debugstr_variant(&var));
ret->u.var = var;
}
return S_OK;
}
@ -1585,7 +1598,7 @@ HRESULT identifier_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD f
if(!identifier)
return E_OUTOFMEMORY;
hres = identifier_eval(ctx, identifier, flags, ret);
hres = identifier_eval(ctx, identifier, flags, ei, ret);
SysFreeString(identifier);
return hres;
@ -1931,11 +1944,11 @@ static HRESULT add_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_
VARIANT r, l;
HRESULT hres;
hres = to_primitive(ctx->parser->script, lval, ei, &l);
hres = to_primitive(ctx->parser->script, lval, ei, &l, NO_HINT);
if(FAILED(hres))
return hres;
hres = to_primitive(ctx->parser->script, rval, ei, &r);
hres = to_primitive(ctx->parser->script, rval, ei, &r, NO_HINT);
if(FAILED(hres)) {
VariantClear(&l);
return hres;
@ -2518,7 +2531,7 @@ static HRESULT equal_values(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexc
VARIANT v;
HRESULT hres;
hres = to_primitive(ctx->parser->script, rval, ei, &v);
hres = to_primitive(ctx->parser->script, rval, ei, &v, NO_HINT);
if(FAILED(hres))
return hres;
@ -2533,7 +2546,7 @@ static HRESULT equal_values(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexc
VARIANT v;
HRESULT hres;
hres = to_primitive(ctx->parser->script, lval, ei, &v);
hres = to_primitive(ctx->parser->script, lval, ei, &v, NO_HINT);
if(FAILED(hres))
return hres;
@ -2638,11 +2651,11 @@ static HRESULT less_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL gre
VARIANT l, r, ln, rn;
HRESULT hres;
hres = to_primitive(ctx->parser->script, lval, ei, &l);
hres = to_primitive(ctx->parser->script, lval, ei, &l, NO_HINT);
if(FAILED(hres))
return hres;
hres = to_primitive(ctx->parser->script, rval, ei, &r);
hres = to_primitive(ctx->parser->script, rval, ei, &r, NO_HINT);
if(FAILED(hres)) {
VariantClear(&l);
return hres;

View file

@ -56,6 +56,7 @@ typedef struct _parser_ctx_t {
source_elements_t *source;
BOOL nl;
BOOL is_html;
BOOL lexer_error;
HRESULT hres;
jsheap_t heap;

View file

@ -0,0 +1,481 @@
/*
* Copyright 2009 Piotr Caban
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wine/port.h"
#include <math.h>
#include "jscript.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
typedef struct {
DispatchEx dispex;
VARIANT number;
VARIANT description;
VARIANT message;
} ErrorInstance;
static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
static const WCHAR messageW[] = {'m','e','s','s','a','g','e',0};
static const WCHAR numberW[] = {'n','u','m','b','e','r',0};
static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p','e','r','t','y',0};
static const WCHAR propertyIsEnumerableW[] =
{'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
static HRESULT Error_number(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
ErrorInstance *This = (ErrorInstance*)dispex;
TRACE("\n");
switch(flags) {
case DISPATCH_PROPERTYGET:
return VariantCopy(retv, &This->number);
case DISPATCH_PROPERTYPUT:
return VariantCopy(&This->number, get_arg(dp, 0));
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
}
static HRESULT Error_description(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
ErrorInstance *This = (ErrorInstance*)dispex;
TRACE("\n");
switch(flags) {
case DISPATCH_PROPERTYGET:
return VariantCopy(retv, &This->description);
case DISPATCH_PROPERTYPUT:
return VariantCopy(&This->description, get_arg(dp, 0));
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
}
/* ECMA-262 3rd Edition 15.11.4.3 */
static HRESULT Error_message(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
ErrorInstance *This = (ErrorInstance*)dispex;
TRACE("\n");
switch(flags) {
case DISPATCH_PROPERTYGET:
return VariantCopy(retv, &This->message);
case DISPATCH_PROPERTYPUT:
return VariantCopy(&This->message, get_arg(dp, 0));
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
}
/* ECMA-262 3rd Edition 15.11.4.4 */
static HRESULT Error_toString(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
static const WCHAR str[] = {'[','o','b','j','e','c','t',' ','E','r','r','o','r',']',0};
TRACE("\n");
if(retv) {
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = SysAllocString(str);
if(!V_BSTR(retv))
return E_OUTOFMEMORY;
}
return S_OK;
}
static HRESULT Error_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Error_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Error_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Error_value(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
switch(flags) {
case INVOKE_FUNC:
return throw_type_error(dispex->ctx, ei, IDS_NOT_FUNC, NULL);
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
return S_OK;
}
static void Error_destructor(DispatchEx *dispex)
{
ErrorInstance *This = (ErrorInstance*)dispex;
VariantClear(&This->number);
VariantClear(&This->description);
VariantClear(&This->message);
heap_free(This);
}
static const builtin_prop_t Error_props[] = {
{descriptionW, Error_description, 0},
{hasOwnPropertyW, Error_hasOwnProperty, PROPF_METHOD},
{isPrototypeOfW, Error_isPrototypeOf, PROPF_METHOD},
{messageW, Error_message, 0},
{numberW, Error_number, 0},
{propertyIsEnumerableW, Error_propertyIsEnumerable, PROPF_METHOD},
{toStringW, Error_toString, PROPF_METHOD}
};
static const builtin_info_t Error_info = {
JSCLASS_ERROR,
{NULL, Error_value, 0},
sizeof(Error_props)/sizeof(*Error_props),
Error_props,
Error_destructor,
NULL
};
static const builtin_prop_t ErrorInst_props[] = {
{descriptionW, Error_description, 0},
{hasOwnPropertyW, Error_hasOwnProperty, PROPF_METHOD},
{isPrototypeOfW, Error_isPrototypeOf, PROPF_METHOD},
{messageW, Error_message, 0},
{numberW, Error_number, 0},
{propertyIsEnumerableW, Error_propertyIsEnumerable, PROPF_METHOD}
};
static const builtin_info_t ErrorInst_info = {
JSCLASS_ERROR,
{NULL, Error_value, 0},
sizeof(ErrorInst_props)/sizeof(*ErrorInst_props),
ErrorInst_props,
Error_destructor,
NULL
};
static HRESULT alloc_error(script_ctx_t *ctx, BOOL error_prototype,
DispatchEx *constr, ErrorInstance **ret)
{
ErrorInstance *err;
DispatchEx *inherit;
HRESULT hres;
err = heap_alloc_zero(sizeof(ErrorInstance));
if(!err)
return E_OUTOFMEMORY;
inherit = error_prototype ? ctx->object_constr : ctx->error_constr;
hres = init_dispex_from_constr(&err->dispex, ctx,
error_prototype ? &Error_info : &ErrorInst_info,
constr ? constr : inherit);
if(FAILED(hres)) {
heap_free(err);
return hres;
}
*ret = err;
return S_OK;
}
static HRESULT create_error(script_ctx_t *ctx, DispatchEx *constr,
const UINT *number, const WCHAR *msg, DispatchEx **ret)
{
ErrorInstance *err;
HRESULT hres;
hres = alloc_error(ctx, FALSE, constr, &err);
if(FAILED(hres))
return hres;
if(number) {
V_VT(&err->number) = VT_I4;
V_I4(&err->number) = *number;
}
V_VT(&err->message) = VT_BSTR;
if(msg) V_BSTR(&err->message) = SysAllocString(msg);
else V_BSTR(&err->message) = SysAllocStringLen(NULL, 0);
VariantCopy(&err->description, &err->message);
if(!V_BSTR(&err->message)) {
heap_free(err);
return E_OUTOFMEMORY;
}
*ret = &err->dispex;
return S_OK;
}
static HRESULT error_constr(DispatchEx *dispex, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, DispatchEx *constr) {
DispatchEx *err;
VARIANT numv;
UINT num;
BSTR msg = NULL;
HRESULT hres;
V_VT(&numv) = VT_NULL;
if(arg_cnt(dp)) {
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &numv);
if(FAILED(hres) || (V_VT(&numv)==VT_R8 && isnan(V_R8(&numv))))
hres = to_string(dispex->ctx, get_arg(dp, 0), ei, &msg);
else if(V_VT(&numv) == VT_I4)
num = V_I4(&numv);
else
num = V_R8(&numv);
if(FAILED(hres))
return hres;
}
if(arg_cnt(dp)>1 && !msg) {
hres = to_string(dispex->ctx, get_arg(dp, 1), ei, &msg);
if(FAILED(hres))
return hres;
}
switch(flags) {
case INVOKE_FUNC:
case DISPATCH_CONSTRUCT:
if(V_VT(&numv) == VT_NULL)
hres = create_error(dispex->ctx, constr, NULL, msg, &err);
else
hres = create_error(dispex->ctx, constr, &num, msg, &err);
if(FAILED(hres))
return hres;
if(retv) {
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(err);
}
else
IDispatchEx_Release(_IDispatchEx_(err));
return S_OK;
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
}
static HRESULT ErrorConstr_value(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return error_constr(dispex, flags, dp, retv, ei,
dispex->ctx->error_constr);
}
static HRESULT EvalErrorConstr_value(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return error_constr(dispex, flags, dp, retv, ei,
dispex->ctx->eval_error_constr);
}
static HRESULT RangeErrorConstr_value(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return error_constr(dispex, flags, dp, retv, ei,
dispex->ctx->range_error_constr);
}
static HRESULT ReferenceErrorConstr_value(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return error_constr(dispex, flags, dp, retv, ei,
dispex->ctx->reference_error_constr);
}
static HRESULT SyntaxErrorConstr_value(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return error_constr(dispex, flags, dp, retv, ei,
dispex->ctx->syntax_error_constr);
}
static HRESULT TypeErrorConstr_value(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return error_constr(dispex, flags, dp, retv, ei,
dispex->ctx->type_error_constr);
}
static HRESULT URIErrorConstr_value(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return error_constr(dispex, flags, dp, retv, ei,
dispex->ctx->uri_error_constr);
}
HRESULT init_error_constr(script_ctx_t *ctx)
{
static const WCHAR nameW[] = {'n','a','m','e',0};
static const WCHAR ErrorW[] = {'E','r','r','o','r',0};
static const WCHAR EvalErrorW[] = {'E','v','a','l','E','r','r','o','r',0};
static const WCHAR RangeErrorW[] = {'R','a','n','g','e','E','r','r','o','r',0};
static const WCHAR ReferenceErrorW[] = {'R','e','f','e','r','e','n','c','e','E','r','r','o','r',0};
static const WCHAR SyntaxErrorW[] = {'S','y','n','t','a','x','E','r','r','o','r',0};
static const WCHAR TypeErrorW[] = {'T','y','p','e','E','r','r','o','r',0};
static const WCHAR URIErrorW[] = {'U','R','I','E','r','r','o','r',0};
static const WCHAR *names[] = {ErrorW, EvalErrorW, RangeErrorW,
ReferenceErrorW, SyntaxErrorW, TypeErrorW, URIErrorW};
DispatchEx **constr_addr[] = {&ctx->error_constr, &ctx->eval_error_constr,
&ctx->range_error_constr, &ctx->reference_error_constr,
&ctx->syntax_error_constr, &ctx->type_error_constr,
&ctx->uri_error_constr};
static builtin_invoke_t constr_val[] = {ErrorConstr_value, EvalErrorConstr_value,
RangeErrorConstr_value, ReferenceErrorConstr_value, SyntaxErrorConstr_value,
TypeErrorConstr_value, URIErrorConstr_value};
ErrorInstance *err;
INT i;
VARIANT v;
HRESULT hres;
for(i=0; i<7; i++) {
hres = alloc_error(ctx, i==0, NULL, &err);
if(FAILED(hres))
return hres;
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = SysAllocString(names[i]);
if(!V_BSTR(&v)) {
IDispatchEx_Release(_IDispatchEx_(&err->dispex));
return E_OUTOFMEMORY;
}
hres = jsdisp_propput_name(&err->dispex, nameW, ctx->lcid, &v, NULL/*FIXME*/, NULL/*FIXME*/);
if(SUCCEEDED(hres))
hres = create_builtin_function(ctx, constr_val[i], NULL,
PROPF_CONSTR, &err->dispex, constr_addr[i]);
IDispatchEx_Release(_IDispatchEx_(&err->dispex));
VariantClear(&v);
if(FAILED(hres))
return hres;
}
return S_OK;
}
static HRESULT throw_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str, DispatchEx *constr)
{
WCHAR buf[1024], *pos = NULL;
DispatchEx *err;
HRESULT hres;
buf[0] = '\0';
LoadStringW(jscript_hinstance, id&0xFFFF, buf, sizeof(buf)/sizeof(WCHAR));
if(str) pos = strchrW(buf, '|');
if(pos) {
int len = strlenW(str);
memmove(pos+len, pos+1, (strlenW(pos+1)+1)*sizeof(WCHAR));
memcpy(pos, str, len*sizeof(WCHAR));
}
WARN("%s\n", debugstr_w(buf));
id |= JSCRIPT_ERROR;
hres = create_error(ctx, constr, &id, buf, &err);
if(FAILED(hres))
return hres;
if(!ei)
return id;
V_VT(&ei->var) = VT_DISPATCH;
V_DISPATCH(&ei->var) = (IDispatch*)_IDispatchEx_(err);
return id;
}
HRESULT throw_eval_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
{
return throw_error(ctx, ei, id, str, ctx->eval_error_constr);
}
HRESULT throw_range_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
{
return throw_error(ctx, ei, id, str, ctx->range_error_constr);
}
HRESULT throw_reference_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
{
return throw_error(ctx, ei, id, str, ctx->reference_error_constr);
}
HRESULT throw_syntax_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
{
return throw_error(ctx, ei, id, str, ctx->syntax_error_constr);
}
HRESULT throw_type_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
{
return throw_error(ctx, ei, id, str, ctx->type_error_constr);
}
HRESULT throw_uri_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
{
return throw_error(ctx, ei, id, str, ctx->uri_error_constr);
}

View file

@ -41,7 +41,6 @@ static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
static const WCHAR lengthW[] = {'l','e','n','g','t','h',0};
static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
static const WCHAR applyW[] = {'a','p','p','l','y',0};
static const WCHAR callW[] = {'c','a','l','l',0};
static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p','e','r','t','y',0};
@ -198,9 +197,10 @@ static HRESULT invoke_constructor(FunctionInstance *function, LCID lcid, DISPPAR
return hres;
hres = invoke_source(function, (IDispatch*)_IDispatchEx_(this_obj), lcid, dp, retv, ei, caller);
jsdisp_release(this_obj);
if(FAILED(hres))
if(FAILED(hres)) {
jsdisp_release(this_obj);
return hres;
}
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(this_obj);
@ -272,10 +272,8 @@ static HRESULT Function_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISP
TRACE("\n");
if(!is_class(dispex, JSCLASS_FUNCTION)) {
FIXME("throw TypeError\n");
return E_FAIL;
}
if(!is_class(dispex, JSCLASS_FUNCTION))
return throw_type_error(dispex->ctx, ei, IDS_NOT_FUNC, NULL);
function = (FunctionInstance*)dispex;
@ -299,13 +297,6 @@ static HRESULT Function_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags
return E_NOTIMPL;
}
static HRESULT Function_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Function_apply(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
@ -408,8 +399,7 @@ static const builtin_prop_t Function_props[] = {
{lengthW, Function_length, 0},
{propertyIsEnumerableW, Function_propertyIsEnumerable, PROPF_METHOD},
{toLocaleStringW, Function_toLocaleString, PROPF_METHOD},
{toStringW, Function_toString, PROPF_METHOD},
{valueOfW, Function_valueOf, PROPF_METHOD}
{toStringW, Function_toString, PROPF_METHOD}
};
static const builtin_info_t Function_info = {
@ -457,35 +447,38 @@ static HRESULT create_function(script_ctx_t *ctx, const builtin_info_t *builtin_
function->flags = flags;
function->length = flags & PROPF_ARGMASK;
if(prototype) {
jsexcept_t jsexcept;
VARIANT var;
V_VT(&var) = VT_DISPATCH;
V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(prototype);
memset(&jsexcept, 0, sizeof(jsexcept));
hres = jsdisp_propput_name(&function->dispex, prototypeW, ctx->lcid, &var, &jsexcept, NULL/*FIXME*/);
if(FAILED(hres)) {
IDispatchEx_Release(_IDispatchEx_(&function->dispex));
return hres;
}
}
*ret = function;
return S_OK;
}
static HRESULT set_prototype(script_ctx_t *ctx, DispatchEx *dispex, DispatchEx *prototype)
{
jsexcept_t jsexcept;
VARIANT var;
V_VT(&var) = VT_DISPATCH;
V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(prototype);
memset(&jsexcept, 0, sizeof(jsexcept));
return jsdisp_propput_name(dispex, prototypeW, ctx->lcid, &var, &jsexcept, NULL/*FIXME*/);
}
HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc,
const builtin_info_t *builtin_info, DWORD flags, DispatchEx *prototype, DispatchEx **ret)
{
FunctionInstance *function;
HRESULT hres;
hres = create_function(ctx, builtin_info, flags, FALSE, prototype, &function);
hres = create_function(ctx, builtin_info, flags, FALSE, NULL, &function);
if(FAILED(hres))
return hres;
hres = set_prototype(ctx, &function->dispex, prototype);
if(FAILED(hres)) {
jsdisp_release(&function->dispex);
return hres;
}
function->value_proc = value_proc;
*ret = &function->dispex;
@ -505,7 +498,12 @@ HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, sourc
if(FAILED(hres))
return hres;
hres = create_function(ctx->script, NULL, PROPF_CONSTR, FALSE, prototype, &function);
hres = create_function(ctx->script, NULL, PROPF_CONSTR, FALSE, NULL, &function);
if(SUCCEEDED(hres)) {
hres = set_prototype(ctx->script, &function->dispex, prototype);
if(FAILED(hres))
jsdisp_release(&function->dispex);
}
jsdisp_release(prototype);
if(FAILED(hres))
return hres;
@ -532,23 +530,28 @@ HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, sourc
return S_OK;
}
HRESULT init_function_constr(script_ctx_t *ctx)
HRESULT init_function_constr(script_ctx_t *ctx, DispatchEx *object_prototype)
{
FunctionInstance *prot, *constr;
HRESULT hres;
hres = create_function(ctx, NULL, PROPF_CONSTR, TRUE, NULL, &prot);
hres = create_function(ctx, NULL, PROPF_CONSTR, TRUE, object_prototype, &prot);
if(FAILED(hres))
return hres;
prot->value_proc = FunctionProt_value;
hres = create_function(ctx, NULL, PROPF_CONSTR, TRUE, &prot->dispex, &constr);
if(SUCCEEDED(hres)) {
constr->value_proc = FunctionConstr_value;
hres = set_prototype(ctx, &constr->dispex, &prot->dispex);
if(FAILED(hres))
jsdisp_release(&constr->dispex);
}
jsdisp_release(&prot->dispex);
if(FAILED(hres))
return hres;
constr->value_proc = FunctionConstr_value;
ctx->function_constr = &constr->dispex;
return hres;
return S_OK;
}

View file

@ -20,6 +20,7 @@
#include "wine/port.h"
#include <math.h>
#include <limits.h>
#include "jscript.h"
#include "engine.h"
@ -28,11 +29,20 @@
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
#define LONGLONG_MAX (((LONGLONG)0x7fffffff<<32)|0xffffffff)
static const WCHAR NaNW[] = {'N','a','N',0};
static const WCHAR InfinityW[] = {'I','n','f','i','n','i','t','y',0};
static const WCHAR ArrayW[] = {'A','r','r','a','y',0};
static const WCHAR BooleanW[] = {'B','o','o','l','e','a','n',0};
static const WCHAR DateW[] = {'D','a','t','e',0};
static const WCHAR ErrorW[] = {'E','r','r','o','r',0};
static const WCHAR EvalErrorW[] = {'E','v','a','l','E','r','r','o','r',0};
static const WCHAR RangeErrorW[] = {'R','a','n','g','e','E','r','r','o','r',0};
static const WCHAR ReferenceErrorW[] = {'R','e','f','e','r','e','n','c','e','E','r','r','o','r',0};
static const WCHAR SyntaxErrorW[] = {'S','y','n','t','a','x','E','r','r','o','r',0};
static const WCHAR TypeErrorW[] = {'T','y','p','e','E','r','r','o','r',0};
static const WCHAR URIErrorW[] = {'U','R','I','E','r','r','o','r',0};
static const WCHAR FunctionW[] = {'F','u','n','c','t','i','o','n',0};
static const WCHAR NumberW[] = {'N','u','m','b','e','r',0};
static const WCHAR ObjectW[] = {'O','b','j','e','c','t',0};
@ -165,6 +175,62 @@ static HRESULT JSGlobal_Date(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARA
return constructor_call(dispex->ctx->date_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_Error(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->error_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_EvalError(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->eval_error_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_RangeError(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->range_error_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_ReferenceError(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->reference_error_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_SyntaxError(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->syntax_error_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_TypeError(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->type_error_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_URIError(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->uri_error_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_Function(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
@ -267,7 +333,7 @@ static HRESULT JSGlobal_eval(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARA
hres = script_parse(dispex->ctx, V_BSTR(arg), NULL, &parser_ctx);
if(FAILED(hres)) {
WARN("parse (%s) failed: %08x\n", debugstr_w(V_BSTR(arg)), hres);
return hres;
return throw_syntax_error(dispex->ctx, ei, hres, NULL);
}
hres = exec_source(dispex->ctx->exec_ctx, parser_ctx, parser_ctx->source, ei, retv);
@ -411,8 +477,103 @@ static HRESULT JSGlobal_parseInt(DispatchEx *dispex, LCID lcid, WORD flags, DISP
static HRESULT JSGlobal_parseFloat(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
LONGLONG d = 0, hlp;
int exp = 0, length;
VARIANT *arg;
WCHAR *str;
BSTR val_str = NULL;
BOOL ret_nan = TRUE, positive = TRUE;
HRESULT hres;
if(!arg_cnt(dp)) {
if(retv)
num_set_nan(retv);
return S_OK;
}
arg = get_arg(dp, 0);
hres = to_string(dispex->ctx, arg, ei, &val_str);
if(FAILED(hres))
return hres;
str = val_str;
length = SysStringLen(val_str);
while(isspaceW(*str)) str++;
if(*str == '+')
str++;
else if(*str == '-') {
positive = FALSE;
str++;
}
if(isdigitW(*str))
ret_nan = FALSE;
while(isdigitW(*str)) {
hlp = d*10 + *(str++) - '0';
if(d>LONGLONG_MAX/10 || hlp<0) {
exp++;
break;
}
else
d = hlp;
}
while(isdigitW(*str)) {
exp++;
str++;
}
if(*str == '.') str++;
if(isdigitW(*str))
ret_nan = FALSE;
while(isdigitW(*str)) {
hlp = d*10 + *(str++) - '0';
if(d>LONGLONG_MAX/10 || hlp<0)
break;
d = hlp;
exp--;
}
while(isdigitW(*str))
str++;
if(*str && !ret_nan && (*str=='e' || *str=='E')) {
int sign = 1, e = 0;
str++;
if(*str == '+')
str++;
else if(*str == '-') {
sign = -1;
str++;
}
while(isdigitW(*str)) {
if(e>INT_MAX/10 || (e = e*10 + *str++ - '0')<0)
e = INT_MAX;
}
e *= sign;
if(exp<0 && e<0 && exp+e>0) exp = INT_MIN;
else if(exp>0 && e>0 && exp+e<0) exp = INT_MAX;
else exp += e;
}
SysFreeString(val_str);
if(ret_nan) {
if(retv)
num_set_nan(retv);
return S_OK;
}
V_VT(retv) = VT_R8;
V_R8(retv) = (double)(positive?d:-d)*pow(10, exp);
return S_OK;
}
static HRESULT JSGlobal_unescape(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@ -541,6 +702,8 @@ static const builtin_prop_t JSGlobal_props[] = {
{CollectGarbageW, JSGlobal_CollectGarbage, PROPF_METHOD},
{DateW, JSGlobal_Date, PROPF_CONSTR},
{EnumeratorW, JSGlobal_Enumerator, PROPF_METHOD},
{ErrorW, JSGlobal_Error, PROPF_CONSTR},
{EvalErrorW, JSGlobal_EvalError, PROPF_CONSTR},
{FunctionW, JSGlobal_Function, PROPF_CONSTR},
{_GetObjectW, JSGlobal_GetObject, PROPF_METHOD},
{InfinityW, JSGlobal_Infinity, 0},
@ -548,12 +711,17 @@ static const builtin_prop_t JSGlobal_props[] = {
{NaNW, JSGlobal_NaN, 0},
{NumberW, JSGlobal_Number, PROPF_CONSTR},
{ObjectW, JSGlobal_Object, PROPF_CONSTR},
{RangeErrorW, JSGlobal_RangeError, PROPF_CONSTR},
{ReferenceErrorW, JSGlobal_ReferenceError, PROPF_CONSTR},
{RegExpW, JSGlobal_RegExp, PROPF_CONSTR},
{ScriptEngineW, JSGlobal_ScriptEngine, PROPF_METHOD},
{ScriptEngineBuildVersionW, JSGlobal_ScriptEngineBuildVersion, PROPF_METHOD},
{ScriptEngineMajorVersionW, JSGlobal_ScriptEngineMajorVersion, PROPF_METHOD},
{ScriptEngineMinorVersionW, JSGlobal_ScriptEngineMinorVersion, PROPF_METHOD},
{StringW, JSGlobal_String, PROPF_CONSTR},
{SyntaxErrorW, JSGlobal_SyntaxError, PROPF_CONSTR},
{TypeErrorW, JSGlobal_TypeError, PROPF_CONSTR},
{URIErrorW, JSGlobal_URIError, PROPF_CONSTR},
{VBArrayW, JSGlobal_VBArray, PROPF_METHOD},
{encodeURIW, JSGlobal_encodeURI, PROPF_METHOD},
{escapeW, JSGlobal_escape, PROPF_METHOD},
@ -574,11 +742,15 @@ static const builtin_info_t JSGlobal_info = {
NULL
};
static HRESULT init_constructors(script_ctx_t *ctx)
static HRESULT init_constructors(script_ctx_t *ctx, DispatchEx *object_prototype)
{
HRESULT hres;
hres = init_function_constr(ctx);
hres = init_function_constr(ctx, object_prototype);
if(FAILED(hres))
return hres;
hres = create_object_constr(ctx, object_prototype, &ctx->object_constr);
if(FAILED(hres))
return hres;
@ -594,11 +766,11 @@ static HRESULT init_constructors(script_ctx_t *ctx)
if(FAILED(hres))
return hres;
hres = create_number_constr(ctx, &ctx->number_constr);
hres = init_error_constr(ctx);
if(FAILED(hres))
return hres;
hres = create_object_constr(ctx, &ctx->object_constr);
hres = create_number_constr(ctx, &ctx->number_constr);
if(FAILED(hres))
return hres;
@ -615,14 +787,19 @@ static HRESULT init_constructors(script_ctx_t *ctx)
HRESULT init_global(script_ctx_t *ctx)
{
DispatchEx *math;
DispatchEx *math, *object_prototype;
VARIANT var;
HRESULT hres;
if(ctx->global)
return S_OK;
hres = init_constructors(ctx);
hres = create_object_prototype(ctx, &object_prototype);
if(FAILED(hres))
return hres;
hres = init_constructors(ctx, object_prototype);
jsdisp_release(object_prototype);
if(FAILED(hres))
return hres;

View file

@ -28,9 +28,13 @@
#include "dispex.h"
#include "activscp.h"
#include "resource.h"
#include "wine/unicode.h"
#include "wine/list.h"
#define JSCRIPT_ERROR 0x800A0000
typedef struct _script_ctx_t script_ctx_t;
typedef struct _exec_ctx_t exec_ctx_t;
typedef struct _dispex_prop_t dispex_prop_t;
@ -58,6 +62,8 @@ jsheap_t *jsheap_mark(jsheap_t*);
typedef struct DispatchEx DispatchEx;
extern HINSTANCE jscript_hinstance;
#define PROPF_ARGMASK 0x00ff
#define PROPF_METHOD 0x0100
#define PROPF_ENUM 0x0200
@ -68,6 +74,7 @@ typedef enum {
JSCLASS_ARRAY,
JSCLASS_BOOLEAN,
JSCLASS_DATE,
JSCLASS_ERROR,
JSCLASS_FUNCTION,
JSCLASS_GLOBAL,
JSCLASS_MATH,
@ -123,6 +130,7 @@ DispatchEx *iface_to_jsdisp(IUnknown*);
HRESULT disp_call(IDispatch*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_call_value(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_call(DispatchEx*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT disp_propget(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT disp_propput(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_propget(DispatchEx*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
@ -131,11 +139,19 @@ HRESULT jsdisp_propput_idx(DispatchEx*,DWORD,LCID,VARIANT*,jsexcept_t*,IServiceP
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*);
HRESULT jsdisp_delete_idx(DispatchEx*,DWORD);
HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,const builtin_info_t*,DWORD,
DispatchEx*,DispatchEx**);
HRESULT Function_value(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT throw_eval_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
HRESULT throw_range_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
HRESULT throw_reference_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
HRESULT throw_syntax_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
HRESULT throw_type_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
HRESULT throw_uri_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
HRESULT create_object(script_ctx_t*,DispatchEx*,DispatchEx**);
HRESULT create_math(script_ctx_t*,DispatchEx**);
@ -145,7 +161,13 @@ HRESULT create_string(script_ctx_t*,const WCHAR*,DWORD,DispatchEx**);
HRESULT create_bool(script_ctx_t*,VARIANT_BOOL,DispatchEx**);
HRESULT create_number(script_ctx_t*,VARIANT*,DispatchEx**);
HRESULT to_primitive(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*);
typedef enum {
NO_HINT,
HINT_STRING,
HINT_NUMBER
} hint_t;
HRESULT to_primitive(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*, hint_t);
HRESULT to_boolean(VARIANT*,VARIANT_BOOL*);
HRESULT to_number(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*);
HRESULT to_integer(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*);
@ -179,6 +201,13 @@ struct _script_ctx_t {
DispatchEx *array_constr;
DispatchEx *bool_constr;
DispatchEx *date_constr;
DispatchEx *error_constr;
DispatchEx *eval_error_constr;
DispatchEx *range_error_constr;
DispatchEx *reference_error_constr;
DispatchEx *syntax_error_constr;
DispatchEx *type_error_constr;
DispatchEx *uri_error_constr;
DispatchEx *number_constr;
DispatchEx *object_constr;
DispatchEx *regexp_constr;
@ -193,13 +222,15 @@ static inline void script_addref(script_ctx_t *ctx)
}
HRESULT init_global(script_ctx_t*);
HRESULT init_function_constr(script_ctx_t*);
HRESULT init_function_constr(script_ctx_t*,DispatchEx*);
HRESULT create_object_prototype(script_ctx_t*,DispatchEx**);
HRESULT create_array_constr(script_ctx_t*,DispatchEx**);
HRESULT create_bool_constr(script_ctx_t*,DispatchEx**);
HRESULT create_date_constr(script_ctx_t*,DispatchEx**);
HRESULT init_error_constr(script_ctx_t*);
HRESULT create_number_constr(script_ctx_t*,DispatchEx**);
HRESULT create_object_constr(script_ctx_t*,DispatchEx**);
HRESULT create_object_constr(script_ctx_t*,DispatchEx*,DispatchEx**);
HRESULT create_regexp_constr(script_ctx_t*,DispatchEx**);
HRESULT create_string_constr(script_ctx_t*,DispatchEx**);

View file

@ -10,11 +10,13 @@
<dependency>jsglobal</dependency>
<library>wine</library>
<library>kernel32</library>
<library>user32</library>
<library>oleaut32</library>
<library>advapi32</library>
<file>date.c</file>
<file>dispex.c</file>
<file>engine.c</file>
<file>error.c</file>
<file>jscript.c</file>
<file>jscript_main.c</file>
<file>jsutils.c</file>

View file

@ -0,0 +1,43 @@
/*
* Copyright 2009 André Hentschel
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
#pragma code_page(65001)
LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
STRINGTABLE DISCARDABLE
{
IDS_TO_PRIMITIVE "Fehler beim umwandeln des Objektes in einen Grundtyp"
IDS_INVALID_CALL_ARG "Ungültiger Funktionsaufruf oder Argument"
IDS_NO_PROPERTY "Das Objekt unterstützt diese Eigenschaft oder Methode nicht"
IDS_ARG_NOT_OPT "Argument nicht optional"
IDS_SYNTAX_ERROR "Syntax Fehler"
IDS_SEMICOLON "';' erwartet"
IDS_LBRACKET "'(' erwartet"
IDS_RBRACKET "')' erwartet"
IDS_UNTERMINATED_STR "konstante Zeichenkette nicht terminiert"
IDS_NOT_FUNC "Funktion erwartet"
IDS_NOT_DATE "'[Objekt]' ist kein Datums-Objekt"
IDS_NOT_NUM "Nummer erwartet"
IDS_ILLEGAL_ASSIGN "Unzulässige Zuweisung"
IDS_UNDEFINED "'|' nicht definiert"
IDS_NOT_BOOL "Boolisches Objekt erwartet"
IDS_INVALID_LENGTH "Array-Größe muss eine endliche, positive Ganzzahl sein"
}

View file

@ -0,0 +1,41 @@
/*
* Copyright 2009 Piotr Caban
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
IDS_TO_PRIMITIVE "Error converting object to primitive type"
IDS_INVALID_CALL_ARG "Invalid procedure call or argument"
IDS_NO_PROPERTY "Object doesn't support this property or method"
IDS_ARG_NOT_OPT "Argument not optional"
IDS_SYNTAX_ERROR "Syntax error"
IDS_SEMICOLON "Expected ';'"
IDS_LBRACKET "Expected '('"
IDS_RBRACKET "Expected ')'"
IDS_UNTERMINATED_STR "Unterminated string constant"
IDS_NOT_FUNC "Function expected"
IDS_NOT_DATE "'[object]' is not a date object"
IDS_NOT_NUM "Number expected"
IDS_ILLEGAL_ASSIGN "Illegal assignment"
IDS_UNDEFINED "'|' is undefined"
IDS_NOT_BOOL "Boolean object expected"
IDS_INVALID_LENGTH "Array length must be a finite positive integer"
}

View file

@ -0,0 +1,46 @@
/*
* French resources for jscript
*
* Copyright 2009 Frédéric Delanoy
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
/* UTF-8 */
#pragma code_page(65001)
LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
STRINGTABLE DISCARDABLE
{
IDS_TO_PRIMITIVE "Erreur lors de la conversion de l'objet vers un type primitif"
IDS_INVALID_CALL_ARG "Appel de procédure ou argument invalide"
IDS_NO_PROPERTY "Cet objet ne supporte pas cette propriété ou méthode"
IDS_ARG_NOT_OPT "Argument non optionnel"
IDS_SYNTAX_ERROR "Erreur de syntaxe"
IDS_SEMICOLON "« ; » attendu"
IDS_LBRACKET "« ( » attendu"
IDS_RBRACKET "« ) » attendu"
IDS_UNTERMINATED_STR "Constante chaîne de caractères non clôturée"
IDS_NOT_FUNC "Fonction attendue"
IDS_NOT_DATE "« [objet] » n'est pas un objet de type date"
IDS_NOT_NUM "Nombre attendu"
IDS_ILLEGAL_ASSIGN "Affectation illégale"
IDS_UNDEFINED "« | » n'est pas défini"
IDS_NOT_BOOL "Booléen attendu"
IDS_INVALID_LENGTH "La longueur d'un tableau doit être un entier positif"
}

View file

@ -0,0 +1,44 @@
/*
* Copyright 2009 Aurimas Fišeras <aurimas@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
/* UTF-8 */
#pragma code_page(65001)
LANGUAGE LANG_LITHUANIAN, SUBLANG_NEUTRAL
STRINGTABLE DISCARDABLE
{
IDS_TO_PRIMITIVE "Klaida keičiant objektą į primityvų tipą"
IDS_INVALID_CALL_ARG "Netinkamas kreipinys į procedūrą ar argumentas"
IDS_NO_PROPERTY "Objektas nepalaiko šios savybės ar metodo"
IDS_ARG_NOT_OPT "Argumentas nėra neprivalomas"
IDS_SYNTAX_ERROR "Sintaksės klaida"
IDS_SEMICOLON "Tikėtasi „;“"
IDS_LBRACKET "Tikėtasi „(“"
IDS_RBRACKET "Tikėtasi „)“"
IDS_UNTERMINATED_STR "Nebaigta eilutės konstanta"
IDS_NOT_FUNC "Tikėtasi funkcijos"
IDS_NOT_DATE "„[objektas]“ nėra datos objektas"
IDS_NOT_NUM "Tikėtasi skaičiaus"
IDS_ILLEGAL_ASSIGN "Neleistinas priskyrimas"
IDS_UNDEFINED "„|“ yra neapibrėžtas"
IDS_NOT_BOOL "Tikėtasi loginio objekto"
IDS_INVALID_LENGTH "Masyvo dydis turi būti teigiamas sveikasis skaičius"
}

View file

@ -0,0 +1,40 @@
/*
* Copyright 2009 Paul Vriens
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL
STRINGTABLE DISCARDABLE
{
IDS_TO_PRIMITIVE "Fout bij het omzetten van het object naar een primitief type"
IDS_INVALID_CALL_ARG "Ongeldige procedure-aanroep of argument"
IDS_NO_PROPERTY "Dit object ondersteunt deze eigenschap of methode niet"
IDS_ARG_NOT_OPT "Argument is niet optioneel"
IDS_SYNTAX_ERROR "Syntax fout"
IDS_SEMICOLON "';' verwacht"
IDS_LBRACKET "'(' verwacht"
IDS_RBRACKET "')' verwacht"
IDS_NOT_FUNC "Functie verwacht"
IDS_NOT_DATE "'[object]' is geen datum object"
IDS_NOT_NUM "Getal verwacht"
IDS_ILLEGAL_ASSIGN "Ongeldige toekenning"
IDS_UNDEFINED "'|' is ongedefinieerd"
IDS_NOT_BOOL "Boolean object verwacht"
IDS_INVALID_LENGTH "Array lengte moet een eindig, positief geheel getal zijn"
}

View file

@ -0,0 +1,42 @@
/*
* Copyright 2009 Ricardo Filipe
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
#pragma code_page(65001)
LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE
STRINGTABLE DISCARDABLE
{
IDS_TO_PRIMITIVE "Erro ao converter objecto em tipo primitivo"
IDS_INVALID_CALL_ARG "Argumento ou chamada de procedimento inválida"
IDS_NO_PROPERTY "O objecto não suporta esta propriedade ou método"
IDS_ARG_NOT_OPT "Argumento não opcional"
IDS_SYNTAX_ERROR "Erro de sintaxe"
IDS_SEMICOLON "';' esperado"
IDS_LBRACKET "'(' esperado"
IDS_RBRACKET "')' esperado"
IDS_NOT_FUNC "Função esperada"
IDS_NOT_DATE "'[object]' não é um objecto de data"
IDS_NOT_NUM "Número esperado"
IDS_ILLEGAL_ASSIGN "Atribuição ilegal"
IDS_UNDEFINED "'|' é indefinido"
IDS_NOT_BOOL "Objecto boleano esperado"
IDS_INVALID_LENGTH "Tamanho do vector tem de ser um inteiro finito positivo"
}

View file

@ -40,7 +40,7 @@ static const CLSID CLSID_JScriptEncode =
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
static HINSTANCE jscript_hinstance;
HINSTANCE jscript_hinstance;
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
{

View file

@ -175,7 +175,7 @@ jsheap_t *jsheap_mark(jsheap_t *heap)
}
/* ECMA-262 3rd Edition 9.1 */
HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret, hint_t hint)
{
switch(V_VT(v)) {
case VT_EMPTY:
@ -189,8 +189,61 @@ HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret
V_VT(ret) = VT_BSTR;
V_BSTR(ret) = SysAllocString(V_BSTR(v));
break;
case VT_DISPATCH:
return disp_propget(V_DISPATCH(v), DISPID_VALUE, ctx->lcid, ret, ei, NULL /*FIXME*/);
case VT_DISPATCH: {
DispatchEx *jsdisp;
DISPID id;
DISPPARAMS dp = {NULL, NULL, 0, 0};
HRESULT hres;
static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
jsdisp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
if(!jsdisp)
return disp_propget(V_DISPATCH(v), DISPID_VALUE, ctx->lcid, ret, ei, NULL /*FIXME*/);
if(hint == NO_HINT)
hint = is_class(jsdisp, JSCLASS_DATE) ? HINT_STRING : HINT_NUMBER;
/* Native implementation doesn't throw TypeErrors, returns strange values */
hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? toStringW : valueOfW, 0, &id);
if(SUCCEEDED(hres)) {
hres = jsdisp_call(jsdisp, id, ctx->lcid, DISPATCH_METHOD, &dp, ret, ei, NULL /*FIXME*/);
if(FAILED(hres)) {
WARN("call error - forwarding exception\n");
jsdisp_release(jsdisp);
return hres;
}
else if(V_VT(ret) != VT_DISPATCH) {
jsdisp_release(jsdisp);
return S_OK;
}
else
IDispatch_Release(V_DISPATCH(ret));
}
hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? valueOfW : toStringW, 0, &id);
if(SUCCEEDED(hres)) {
hres = jsdisp_call(jsdisp, id, ctx->lcid, DISPATCH_METHOD, &dp, ret, ei, NULL /*FIXME*/);
if(FAILED(hres)) {
WARN("call error - forwarding exception\n");
jsdisp_release(jsdisp);
return hres;
}
else if(V_VT(ret) != VT_DISPATCH) {
jsdisp_release(jsdisp);
return S_OK;
}
else
IDispatch_Release(V_DISPATCH(ret));
}
jsdisp_release(jsdisp);
WARN("failed\n");
return throw_type_error(ctx, ei, IDS_TO_PRIMITIVE, NULL);
}
default:
FIXME("Unimplemented for vt %d\n", V_VT(v));
return E_NOTIMPL;
@ -211,7 +264,8 @@ HRESULT to_boolean(VARIANT *v, VARIANT_BOOL *b)
*b = V_I4(v) ? VARIANT_TRUE : VARIANT_FALSE;
break;
case VT_R8:
*b = V_R8(v) ? VARIANT_TRUE : VARIANT_FALSE;
if(isnan(V_R8(v))) *b = VARIANT_FALSE;
else *b = V_R8(v) ? VARIANT_TRUE : VARIANT_FALSE;
break;
case VT_BSTR:
*b = V_BSTR(v) && *V_BSTR(v) ? VARIANT_TRUE : VARIANT_FALSE;
@ -355,7 +409,7 @@ HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
VARIANT prim;
HRESULT hres;
hres = to_primitive(ctx, v, ei, &prim);
hres = to_primitive(ctx, v, ei, &prim, HINT_NUMBER);
if(FAILED(hres))
return hres;
@ -458,6 +512,8 @@ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
const WCHAR nullW[] = {'n','u','l','l',0};
const WCHAR trueW[] = {'t','r','u','e',0};
const WCHAR falseW[] = {'f','a','l','s','e',0};
const WCHAR NaNW[] = {'N','a','N',0};
const WCHAR InfinityW[] = {'-','I','n','f','i','n','i','t','y',0};
switch(V_VT(v)) {
case VT_EMPTY:
@ -470,16 +526,23 @@ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
*str = int_to_bstr(V_I4(v));
break;
case VT_R8: {
VARIANT strv;
HRESULT hres;
if(isnan(V_R8(v)))
*str = SysAllocString(NaNW);
else if(isinf(V_R8(v)))
*str = SysAllocString(V_R8(v)<0 ? InfinityW : InfinityW+1);
else {
VARIANT strv;
HRESULT hres;
V_VT(&strv) = VT_EMPTY;
hres = VariantChangeTypeEx(&strv, v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR);
if(FAILED(hres))
return hres;
V_VT(&strv) = VT_EMPTY;
hres = VariantChangeTypeEx(&strv, v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR);
if(FAILED(hres))
return hres;
*str = V_BSTR(&strv);
return S_OK;
*str = V_BSTR(&strv);
return S_OK;
}
break;
}
case VT_BSTR:
*str = SysAllocString(V_BSTR(v));
@ -488,7 +551,7 @@ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
VARIANT prim;
HRESULT hres;
hres = to_primitive(ctx, v, ei, &prim);
hres = to_primitive(ctx, v, ei, &prim, HINT_STRING);
if(FAILED(hres))
return hres;

View file

@ -100,7 +100,8 @@ static const struct {
static int lex_error(parser_ctx_t *ctx, HRESULT hres)
{
ctx->hres = hres;
ctx->hres = JSCRIPT_ERROR|hres;
ctx->lexer_error = TRUE;
return -1;
}
@ -342,10 +343,8 @@ static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret, WCHAR endc
ctx->ptr++;
}
if(ctx->ptr == ctx->end) {
WARN("unexpected end of file\n");
return lex_error(ctx, E_FAIL);
}
if(ctx->ptr == ctx->end)
return lex_error(ctx, IDS_UNTERMINATED_STR);
len = ctx->ptr-ptr;

View file

@ -1,5 +1,6 @@
/*
* Copyright 2008 Jacek Caban for CodeWeavers
* Copyright 2009 Piotr Caban
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <math.h>
#include "jscript.h"
#include "wine/debug.h"
@ -39,31 +41,126 @@ static const WCHAR propertyIsEnumerableW[] =
{'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
#define NUMBER_TOSTRING_BUF_SIZE 64
/* ECMA-262 3rd Edition 15.7.4.2 */
static HRESULT Number_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
NumberInstance *number;
INT radix = 10;
DOUBLE val;
BSTR str;
HRESULT hres;
TRACE("\n");
if(!is_class(dispex, JSCLASS_NUMBER)) {
FIXME("throw TypeError\n");
return E_FAIL;
}
if(!is_class(dispex, JSCLASS_NUMBER))
return throw_type_error(dispex->ctx, ei, IDS_NOT_NUM, NULL);
number = (NumberInstance*)dispex;
if(arg_cnt(dp) != 0) {
FIXME("unsupported args\n");
return E_NOTIMPL;
if(arg_cnt(dp)) {
hres = to_int32(dispex->ctx, get_arg(dp, 0), ei, &radix);
if(FAILED(hres))
return hres;
if(radix<2 || radix>36)
return throw_type_error(dispex->ctx, ei, IDS_INVALID_CALL_ARG, NULL);
}
hres = to_string(dispex->ctx, &number->num, ei, &str);
if(FAILED(hres))
return hres;
if(V_VT(&number->num) == VT_I4)
val = V_I4(&number->num);
else
val = V_R8(&number->num);
if(radix==10 || isnan(val) || isinf(val)) {
hres = to_string(dispex->ctx, &number->num, ei, &str);
if(FAILED(hres))
return hres;
}
else {
INT idx = 0;
DOUBLE integ, frac, log_radix = 0;
WCHAR buf[NUMBER_TOSTRING_BUF_SIZE+16];
BOOL exp = FALSE;
if(val<0) {
val = -val;
buf[idx++] = '-';
}
while(1) {
integ = floor(val);
frac = val-integ;
if(integ == 0)
buf[idx++] = '0';
while(integ>=1 && idx<NUMBER_TOSTRING_BUF_SIZE) {
buf[idx] = fmod(integ, radix);
if(buf[idx]<10) buf[idx] += '0';
else buf[idx] += 'a'-10;
integ /= radix;
idx++;
}
if(idx<NUMBER_TOSTRING_BUF_SIZE) {
INT beg = buf[0]=='-'?1:0;
INT end = idx-1;
WCHAR wch;
while(end > beg) {
wch = buf[beg];
buf[beg++] = buf[end];
buf[end--] = wch;
}
}
if(idx != NUMBER_TOSTRING_BUF_SIZE) buf[idx++] = '.';
while(frac>0 && idx<NUMBER_TOSTRING_BUF_SIZE) {
frac *= radix;
buf[idx] = fmod(frac, radix);
frac -= buf[idx];
if(buf[idx]<10) buf[idx] += '0';
else buf[idx] += 'a'-10;
idx++;
}
if(idx==NUMBER_TOSTRING_BUF_SIZE && !exp) {
exp = TRUE;
idx = (buf[0]=='-') ? 1 : 0;
log_radix = floor(log(val)/log(radix));
val *= pow(radix, -log_radix);
continue;
}
break;
}
while(buf[idx-1] == '0') idx--;
if(buf[idx-1] == '.') idx--;
if(exp) {
if(log_radix==0)
buf[idx++] = '\0';
else {
static const WCHAR formatW[] = {'(','e','%','c','%','d',')',0};
WCHAR ch;
if(log_radix<0) {
log_radix = -log_radix;
ch = '-';
}
else ch = '+';
sprintfW(&buf[idx], formatW, ch, (int)log_radix);
}
}
else buf[idx] = '\0';
str = SysAllocString(buf);
if(!str)
return E_OUTOFMEMORY;
}
if(retv) {
V_VT(retv) = VT_BSTR;
@ -107,10 +204,8 @@ static HRESULT Number_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
{
TRACE("\n");
if(!is_class(dispex, JSCLASS_NUMBER)) {
FIXME("throw TypeError\n");
return E_FAIL;
}
if(!is_class(dispex, JSCLASS_NUMBER))
return throw_type_error(dispex->ctx, ei, IDS_NOT_NUM, NULL);
if(retv) {
NumberInstance *number = (NumberInstance*)dispex;
@ -146,6 +241,8 @@ static HRESULT Number_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
NumberInstance *number = (NumberInstance*)dispex;
switch(flags) {
case INVOKE_FUNC:
return throw_type_error(dispex->ctx, ei, IDS_NOT_FUNC, NULL);
case DISPATCH_PROPERTYGET:
*retv = number->num;
break;

View file

@ -35,22 +35,62 @@ static const WCHAR default_valueW[] = {'[','o','b','j','e','c','t',' ','O','b','
static HRESULT Object_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
static const WCHAR formatW[] = {'[','o','b','j','e','c','t',' ','%','s',']',0};
static const WCHAR arrayW[] = {'A','r','r','a','y',0};
static const WCHAR booleanW[] = {'B','o','o','l','e','a','n',0};
static const WCHAR dateW[] = {'D','a','t','e',0};
static const WCHAR errorW[] = {'E','r','r','o','r',0};
static const WCHAR functionW[] = {'F','u','n','c','t','i','o','n',0};
static const WCHAR mathW[] = {'M','a','t','h',0};
static const WCHAR numberW[] = {'N','u','m','b','e','r',0};
static const WCHAR objectW[] = {'O','b','j','e','c','t',0};
static const WCHAR regexpW[] = {'R','e','g','E','x','p',0};
static const WCHAR stringW[] = {'S','t','r','i','n','g',0};
/* Keep in sync with jsclass_t enum */
static const WCHAR *names[] = {NULL, arrayW, booleanW, dateW, errorW,
functionW, NULL, mathW, numberW, objectW, regexpW, stringW};
TRACE("\n");
if(names[dispex->builtin_info->class] == NULL) {
ERR("dispex->builtin_info->class = %d\n",
dispex->builtin_info->class);
return E_FAIL;
}
if(retv) {
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = SysAllocStringLen(NULL, 9+strlenW(names[dispex->builtin_info->class]));
if(!V_BSTR(retv))
return E_OUTOFMEMORY;
sprintfW(V_BSTR(retv), formatW, names[dispex->builtin_info->class]);
}
return S_OK;
}
static HRESULT Object_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
TRACE("\n");
return Object_toString(dispex, lcid, flags, dp, retv, ei, sp);
}
static HRESULT Object_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
TRACE("\n");
if(retv) {
IDispatchEx_AddRef(_IDispatchEx_(dispex));
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(dispex);
}
return S_OK;
}
static HRESULT Object_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@ -80,6 +120,8 @@ static HRESULT Object_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
TRACE("\n");
switch(flags) {
case INVOKE_FUNC:
return throw_type_error(dispex->ctx, ei, IDS_NOT_FUNC, NULL);
case DISPATCH_PROPERTYGET:
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = SysAllocString(default_valueW);
@ -145,19 +187,15 @@ static HRESULT ObjectConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DIS
return S_OK;
}
HRESULT create_object_constr(script_ctx_t *ctx, DispatchEx **ret)
HRESULT create_object_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret)
{
DispatchEx *object;
HRESULT hres;
return create_builtin_function(ctx, ObjectConstr_value, NULL, PROPF_CONSTR,
object_prototype, ret);
}
hres = create_dispex(ctx, &Object_info, NULL, &object);
if(FAILED(hres))
return hres;
hres = create_builtin_function(ctx, ObjectConstr_value, NULL, PROPF_CONSTR, object, ret);
jsdisp_release(object);
return hres;
HRESULT create_object_prototype(script_ctx_t *ctx, DispatchEx **ret)
{
return create_dispex(ctx, &Object_info, NULL, ret);
}
HRESULT create_object(script_ctx_t *ctx, DispatchEx *constr, DispatchEx **ret)

File diff suppressed because it is too large Load diff

View file

@ -91,7 +91,7 @@ typedef union YYSTYPE
{
/* Line 1676 of yacc.c */
#line 149 "parser.y"
#line 151 "parser.y"
int ival;
const WCHAR *srcptr;

View file

@ -25,6 +25,8 @@
#define YYPARSE_PARAM ctx
static int parser_error(const char*);
static void set_error(parser_ctx_t*,UINT);
static BOOL explicit_error(parser_ctx_t*,void*,WCHAR);
static BOOL allow_auto_semicolon(parser_ctx_t*);
static void program_parsed(parser_ctx_t*,source_elements_t*);
static source_elements_t *function_body_parsed(parser_ctx_t*,source_elements_t*);
@ -200,7 +202,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state
%type <statement> Finally
%type <statement_list> StatementList StatementList_opt
%type <parameter_list> FormalParameterList FormalParameterList_opt
%type <expr> Expression Expression_opt
%type <expr> Expression Expression_opt Expression_err
%type <expr> ExpressionNoIn ExpressionNoIn_opt
%type <expr> FunctionExpression
%type <expr> AssignmentExpression AssignmentExpressionNoIn
@ -266,7 +268,7 @@ SourceElements
/* ECMA-262 3rd Edition 13 */
FunctionExpression
: KFunction Identifier_opt '(' FormalParameterList_opt ')' '{' FunctionBody '}'
: KFunction Identifier_opt left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}'
{ $$ = new_function_expression(ctx, $2, $4, $7, $1, $8-$1+1); }
KFunction
@ -379,24 +381,32 @@ ExpressionStatement
/* ECMA-262 3rd Edition 12.5 */
IfStatement
: kIF '(' Expression ')' Statement kELSE Statement
: kIF left_bracket Expression_err right_bracket Statement kELSE Statement
{ $$ = new_if_statement(ctx, $3, $5, $7); }
| kIF '(' Expression ')' Statement %prec LOWER_THAN_ELSE
| kIF left_bracket Expression_err right_bracket Statement %prec LOWER_THAN_ELSE
{ $$ = new_if_statement(ctx, $3, $5, NULL); }
/* ECMA-262 3rd Edition 12.6 */
IterationStatement
: kDO Statement kWHILE '(' Expression ')' ';'
: kDO Statement kWHILE left_bracket Expression_err right_bracket semicolon_opt
{ $$ = new_while_statement(ctx, TRUE, $5, $2); }
| kWHILE '(' Expression ')' Statement
| kWHILE left_bracket Expression_err right_bracket Statement
{ $$ = new_while_statement(ctx, FALSE, $3, $5); }
| kFOR '(' ExpressionNoIn_opt ';' Expression_opt ';' Expression_opt ')' Statement
{ $$ = new_for_statement(ctx, NULL, $3, $5, $7, $9); }
| kFOR '(' kVAR VariableDeclarationListNoIn ';' Expression_opt ';' Expression_opt ')' Statement
{ $$ = new_for_statement(ctx, $4, NULL, $6, $8, $10); }
| kFOR '(' LeftHandSideExpression kIN Expression ')' Statement
| kFOR left_bracket ExpressionNoIn_opt
{ if(!explicit_error(ctx, $3, ';')) YYABORT; }
semicolon Expression_opt
{ if(!explicit_error(ctx, $6, ';')) YYABORT; }
semicolon Expression_opt right_bracket Statement
{ $$ = new_for_statement(ctx, NULL, $3, $6, $9, $11); }
| kFOR left_bracket kVAR VariableDeclarationListNoIn
{ if(!explicit_error(ctx, $4, ';')) YYABORT; }
semicolon Expression_opt
{ if(!explicit_error(ctx, $7, ';')) YYABORT; }
semicolon Expression_opt right_bracket Statement
{ $$ = new_for_statement(ctx, $4, NULL, $7, $10, $12); }
| kFOR left_bracket LeftHandSideExpression kIN Expression_err right_bracket Statement
{ $$ = new_forin_statement(ctx, NULL, $3, $5, $7); }
| kFOR '(' kVAR VariableDeclarationNoIn kIN Expression ')' Statement
| kFOR left_bracket kVAR VariableDeclarationNoIn kIN Expression_err right_bracket Statement
{ $$ = new_forin_statement(ctx, $4, NULL, $6, $8); }
/* ECMA-262 3rd Edition 12.7 */
@ -416,7 +426,7 @@ ReturnStatement
/* ECMA-262 3rd Edition 12.10 */
WithStatement
: kWITH '(' Expression ')' Statement
: kWITH left_bracket Expression right_bracket Statement
{ $$ = new_with_statement(ctx, $3, $5); }
/* ECMA-262 3rd Edition 12.12 */
@ -426,8 +436,8 @@ LabelledStatement
/* ECMA-262 3rd Edition 12.11 */
SwitchStatement
: kSWITCH '(' Expression ')' CaseBlock
{ $$ = new_switch_statement(ctx, $3, $5); }
: kSWITCH left_bracket Expression right_bracket CaseBlock
{ $$ = new_switch_statement(ctx, $3, $5); }
/* ECMA-262 3rd Edition 12.11 */
CaseBlock
@ -471,8 +481,8 @@ TryStatement
/* ECMA-262 3rd Edition 12.14 */
Catch
: kCATCH '(' tIdentifier ')' Block
{ $$ = new_catch_block(ctx, $3, $5); }
: kCATCH left_bracket tIdentifier right_bracket Block
{ $$ = new_catch_block(ctx, $3, $5); }
/* ECMA-262 3rd Edition 12.14 */
Finally
@ -483,6 +493,10 @@ Expression_opt
: /* empty */ { $$ = NULL; }
| Expression { $$ = $1; }
Expression_err
: Expression { $$ = $1; }
| error { set_error(ctx, IDS_SYNTAX_ERROR); YYABORT; }
/* ECMA-262 3rd Edition 11.14 */
Expression
: AssignmentExpression { $$ = $1; }
@ -796,6 +810,18 @@ semicolon_opt
: ';'
| error { if(!allow_auto_semicolon(ctx)) {YYABORT;} }
left_bracket
: '('
| error { set_error(ctx, IDS_LBRACKET); YYABORT; }
right_bracket
: ')'
| error { set_error(ctx, IDS_RBRACKET); YYABORT; }
semicolon
: ';'
| error { set_error(ctx, IDS_SEMICOLON); YYABORT; }
%%
static BOOL allow_auto_semicolon(parser_ctx_t *ctx)
@ -1434,6 +1460,20 @@ static int parser_error(const char *str)
return 0;
}
static void set_error(parser_ctx_t *ctx, UINT error)
{
ctx->hres = JSCRIPT_ERROR|error;
}
static BOOL explicit_error(parser_ctx_t *ctx, void *obj, WCHAR next)
{
if(obj || *(ctx->ptr-1)==next) return TRUE;
set_error(ctx, IDS_SYNTAX_ERROR);
return FALSE;
}
static expression_t *new_identifier_expression(parser_ctx_t *ctx, const WCHAR *identifier)
{
identifier_expression_t *ret = parser_alloc(ctx, sizeof(identifier_expression_t));
@ -1537,7 +1577,8 @@ static void program_parsed(parser_ctx_t *ctx, source_elements_t *source)
pop_func(ctx);
ctx->source = source;
ctx->hres = S_OK;
if(!ctx->lexer_error)
ctx->hres = S_OK;
}
void parser_release(parser_ctx_t *ctx)
@ -1568,7 +1609,7 @@ HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimite
return E_OUTOFMEMORY;
parser_ctx->ref = 1;
parser_ctx->hres = E_FAIL;
parser_ctx->hres = JSCRIPT_ERROR|IDS_SYNTAX_ERROR;
parser_ctx->is_html = delimiter && !strcmpiW(delimiter, html_tagW);
parser_ctx->begin = parser_ctx->ptr = code;

View file

@ -96,6 +96,7 @@ static const WCHAR propertyIsEnumerableW[] =
{'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
static const WCHAR execW[] = {'e','x','e','c',0};
static const WCHAR testW[] = {'t','e','s','t',0};
static const WCHAR emptyW[] = {0};
@ -3505,13 +3506,29 @@ static HRESULT RegExp_exec(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS
return E_NOTIMPL;
}
static HRESULT RegExp_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
static HRESULT RegExp_test(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT RegExp_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
switch(flags) {
case INVOKE_FUNC:
return throw_type_error(dispex->ctx, ei, IDS_NOT_FUNC, NULL);
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
return S_OK;
}
static void RegExp_destructor(DispatchEx *dispex)
{
RegExpInstance *This = (RegExpInstance*)dispex;
@ -3532,6 +3549,7 @@ static const builtin_prop_t RegExp_props[] = {
{multilineW, RegExp_multiline, 0},
{propertyIsEnumerableW, RegExp_propertyIsEnumerable, PROPF_METHOD},
{sourceW, RegExp_source, 0},
{testW, RegExp_test, PROPF_METHOD},
{toLocaleStringW, RegExp_toLocaleString, PROPF_METHOD},
{toStringW, RegExp_toString, PROPF_METHOD}
};

View file

@ -0,0 +1,36 @@
/*
* Copyright 2009 Piotr Caban
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <windef.h>
#define IDS_TO_PRIMITIVE 0x0001
#define IDS_INVALID_CALL_ARG 0x0005
#define IDS_NO_PROPERTY 0x01B6
#define IDS_ARG_NOT_OPT 0x01c1
#define IDS_SYNTAX_ERROR 0x03EA
#define IDS_SEMICOLON 0x03EC
#define IDS_LBRACKET 0x03ED
#define IDS_RBRACKET 0x03EE
#define IDS_UNTERMINATED_STR 0x03F7
#define IDS_NOT_FUNC 0x138A
#define IDS_NOT_DATE 0x138E
#define IDS_NOT_NUM 0x1389
#define IDS_ILLEGAL_ASSIGN 0x1390
#define IDS_UNDEFINED 0x1391
#define IDS_NOT_BOOL 0x1392
#define IDS_INVALID_LENGTH 0x13A5

View file

@ -21,3 +21,10 @@ REGINST REGINST jscript.inf
/* @makedep: jsglobal.tlb */
1 TYPELIB LOADONCALL DISCARDABLE jsglobal.tlb
#include "jscript_De.rc"
#include "jscript_En.rc"
#include "jscript_Fr.rc"
#include "jscript_Lt.rc"
#include "jscript_Nl.rc"
#include "jscript_Pt.rc"

View file

@ -66,6 +66,7 @@ static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p',
static const WCHAR propertyIsEnumerableW[] =
{'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
static const WCHAR fromCharCodeW[] = {'f','r','o','m','C','h','a','r','C','o','d','e',0};
static HRESULT String_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
@ -127,34 +128,123 @@ static HRESULT do_attributeless_tag_format(DispatchEx *dispex, LCID lcid, WORD f
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp, const WCHAR *tagname)
{
static const WCHAR tagfmt[] = {'<','%','s','>','%','s','<','/','%','s','>',0};
StringInstance *string;
BSTR ret;
const WCHAR *str;
DWORD length;
BSTR val_str = NULL;
HRESULT hres;
if(!is_class(dispex, JSCLASS_STRING)) {
WARN("this is not a string object\n");
return E_NOTIMPL;
VARIANT this;
V_VT(&this) = VT_DISPATCH;
V_DISPATCH(&this) = (IDispatch*)_IDispatchEx_(dispex);
hres = to_string(dispex->ctx, &this, ei, &val_str);
if(FAILED(hres))
return hres;
str = val_str;
length = SysStringLen(val_str);
}
else {
StringInstance *this = (StringInstance*)dispex;
str = this->str;
length = this->length;
}
string = (StringInstance*)dispex;
if(retv) {
ret = SysAllocStringLen(NULL, string->length + 2*strlenW(tagname) + 5);
if(!ret)
BSTR ret = SysAllocStringLen(NULL, length + 2*strlenW(tagname) + 5);
if(!ret) {
SysFreeString(val_str);
return E_OUTOFMEMORY;
}
sprintfW(ret, tagfmt, tagname, string->str, tagname);
sprintfW(ret, tagfmt, tagname, str, tagname);
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = ret;
}
SysFreeString(val_str);
return S_OK;
}
static HRESULT do_attribute_tag_format(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp,
const WCHAR *tagname, const WCHAR *attr)
{
static const WCHAR tagfmtW[]
= {'<','%','s',' ','%','s','=','\"','%','s','\"','>','%','s','<','/','%','s','>',0};
static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
const WCHAR *str;
DWORD length;
BSTR attr_value, val_str = NULL;
HRESULT hres;
if(!is_class(dispex, JSCLASS_STRING)) {
VARIANT this;
V_VT(&this) = VT_DISPATCH;
V_DISPATCH(&this) = (IDispatch*)_IDispatchEx_(dispex);
hres = to_string(dispex->ctx, &this, ei, &val_str);
if(FAILED(hres))
return hres;
str = val_str;
length = SysStringLen(val_str);
}
else {
StringInstance *this = (StringInstance*)dispex;
str = this->str;
length = this->length;
}
if(arg_cnt(dp)) {
hres = to_string(dispex->ctx, get_arg(dp, 0), ei, &attr_value);
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
}
else {
attr_value = SysAllocString(undefinedW);
if(!attr_value) {
SysFreeString(val_str);
return E_OUTOFMEMORY;
}
}
if(retv) {
BSTR ret = SysAllocStringLen(NULL, length + 2*strlenW(tagname)
+ strlenW(attr) + SysStringLen(attr_value) + 9);
if(!ret) {
SysFreeString(attr_value);
SysFreeString(val_str);
return E_OUTOFMEMORY;
}
sprintfW(ret, tagfmtW, tagname, attr, attr_value, str, tagname);
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = ret;
}
SysFreeString(attr_value);
SysFreeString(val_str);
return S_OK;
}
static HRESULT String_anchor(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
static const WCHAR fontW[] = {'A',0};
static const WCHAR colorW[] = {'N','A','M','E',0};
return do_attribute_tag_format(dispex, lcid, flags, dp, retv, ei, sp, fontW, colorW);
}
static HRESULT String_big(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@ -182,26 +272,42 @@ static HRESULT String_bold(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS
static HRESULT String_charAt(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
StringInstance *strobj;
BSTR str;
const WCHAR *str;
DWORD length;
BSTR ret, val_str = NULL;
INT pos = 0;
HRESULT hres;
TRACE("\n");
if(dispex->builtin_info->class != JSCLASS_STRING) {
FIXME("not string this not supported\n");
return E_NOTIMPL;
}
if(!is_class(dispex, JSCLASS_STRING)) {
VARIANT this;
strobj = (StringInstance*)dispex;
V_VT(&this) = VT_DISPATCH;
V_DISPATCH(&this) = (IDispatch*)_IDispatchEx_(dispex);
hres = to_string(dispex->ctx, &this, ei, &val_str);
if(FAILED(hres))
return hres;
str = val_str;
length = SysStringLen(val_str);
}
else {
StringInstance *this = (StringInstance*)dispex;
str = this->str;
length = this->length;
}
if(arg_cnt(dp)) {
VARIANT num;
hres = to_integer(dispex->ctx, get_arg(dp, 0), ei, &num);
if(FAILED(hres))
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
if(V_VT(&num) == VT_I4) {
pos = V_I4(&num);
@ -211,18 +317,22 @@ static HRESULT String_charAt(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARA
}
}
if(!retv)
if(!retv) {
SysFreeString(val_str);
return S_OK;
}
if(0 <= pos && pos < strobj->length)
str = SysAllocStringLen(strobj->str+pos, 1);
if(0 <= pos && pos < length)
ret = SysAllocStringLen(str+pos, 1);
else
str = SysAllocStringLen(NULL, 0);
if(!str)
ret = SysAllocStringLen(NULL, 0);
SysFreeString(val_str);
if(!ret) {
return E_OUTOFMEMORY;
}
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = str;
V_BSTR(retv) = ret;
return S_OK;
}
@ -231,30 +341,44 @@ static HRESULT String_charCodeAt(DispatchEx *dispex, LCID lcid, WORD flags, DISP
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
const WCHAR *str;
BSTR val_str = NULL;
DWORD length, idx = 0;
HRESULT hres;
TRACE("\n");
if(dispex->builtin_info->class == JSCLASS_STRING) {
StringInstance *string = (StringInstance*)dispex;
if(!is_class(dispex, JSCLASS_STRING)) {
VARIANT this;
str = string->str;
length = string->length;
}else {
FIXME("not string this not supported\n");
return E_NOTIMPL;
V_VT(&this) = VT_DISPATCH;
V_DISPATCH(&this) = (IDispatch*)_IDispatchEx_(dispex);
hres = to_string(dispex->ctx, &this, ei, &val_str);
if(FAILED(hres))
return hres;
str = val_str;
length = SysStringLen(val_str);
}
else {
StringInstance *this = (StringInstance*)dispex;
str = this->str;
length = this->length;
}
if(arg_cnt(dp) > 0) {
VARIANT v;
hres = to_integer(dispex->ctx, get_arg(dp, 0), ei, &v);
if(FAILED(hres))
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
if(V_VT(&v) != VT_I4 || V_I4(&v) < 0 || V_I4(&v) >= length) {
if(retv) num_set_nan(&v);
SysFreeString(val_str);
return S_OK;
}
@ -265,6 +389,8 @@ static HRESULT String_charCodeAt(DispatchEx *dispex, LCID lcid, WORD flags, DISP
V_VT(retv) = VT_I4;
V_I4(retv) = str[idx];
}
SysFreeString(val_str);
return S_OK;
}
@ -336,15 +462,19 @@ static HRESULT String_fixed(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
static HRESULT String_fontcolor(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
static const WCHAR fontW[] = {'F','O','N','T',0};
static const WCHAR colorW[] = {'C','O','L','O','R',0};
return do_attribute_tag_format(dispex, lcid, flags, dp, retv, ei, sp, fontW, colorW);
}
static HRESULT String_fontsize(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
static const WCHAR fontW[] = {'F','O','N','T',0};
static const WCHAR colorW[] = {'S','I','Z','E',0};
return do_attribute_tag_format(dispex, lcid, flags, dp, retv, ei, sp, fontW, colorW);
}
static HRESULT String_indexOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@ -352,20 +482,30 @@ static HRESULT String_indexOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
{
DWORD length, pos = 0;
const WCHAR *str;
BSTR search_str;
BSTR search_str, val_str = NULL;
INT ret = -1;
HRESULT hres;
TRACE("\n");
if(is_class(dispex, JSCLASS_STRING)) {
StringInstance *string = (StringInstance*)dispex;
if(!is_class(dispex, JSCLASS_STRING)) {
VARIANT this;
str = string->str;
length = string->length;
}else {
FIXME("not String this\n");
return E_NOTIMPL;
V_VT(&this) = VT_DISPATCH;
V_DISPATCH(&this) = (IDispatch*)_IDispatchEx_(dispex);
hres = to_string(dispex->ctx, &this, ei, &val_str);
if(FAILED(hres))
return hres;
str = val_str;
length = SysStringLen(val_str);
}
else {
StringInstance *this = (StringInstance*)dispex;
str = this->str;
length = this->length;
}
if(!arg_cnt(dp)) {
@ -373,12 +513,15 @@ static HRESULT String_indexOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
V_VT(retv) = VT_I4;
V_I4(retv) = -1;
}
SysFreeString(val_str);
return S_OK;
}
hres = to_string(dispex->ctx, get_arg(dp,0), ei, &search_str);
if(FAILED(hres))
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
if(arg_cnt(dp) >= 2) {
VARIANT ival;
@ -405,6 +548,7 @@ static HRESULT String_indexOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
}
SysFreeString(search_str);
SysFreeString(val_str);
if(FAILED(hres))
return hres;
@ -432,27 +576,33 @@ static HRESULT String_lastIndexOf(DispatchEx *dispex, LCID lcid, WORD flags, DIS
static HRESULT String_link(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
static const WCHAR fontW[] = {'A',0};
static const WCHAR colorW[] = {'H','R','E','F',0};
return do_attribute_tag_format(dispex, lcid, flags, dp, retv, ei, sp, fontW, colorW);
}
/* ECMA-262 3rd Edition 15.5.4.10 */
static HRESULT String_match(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
StringInstance *This = (StringInstance*)dispex;
const WCHAR *str;
match_result_t *match_result;
DispatchEx *regexp;
DispatchEx *array;
VARIANT var, *arg_var;
DWORD match_cnt, i;
DWORD length, match_cnt, i;
BSTR val_str = NULL;
HRESULT hres = S_OK;
TRACE("\n");
if(arg_cnt(dp) != 1) {
FIXME("unsupported args\n");
return E_NOTIMPL;
if(!arg_cnt(dp)) {
if(retv) {
V_VT(retv) = VT_NULL;
}
return S_OK;
}
arg_var = get_arg(dp, 0);
@ -478,22 +628,50 @@ static HRESULT String_match(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
}
}
hres = regexp_match(regexp, This->str, This->length, FALSE, &match_result, &match_cnt);
if(!is_class(dispex, JSCLASS_STRING)) {
VARIANT this;
V_VT(&this) = VT_DISPATCH;
V_DISPATCH(&this) = (IDispatch*)_IDispatchEx_(dispex);
hres = to_string(dispex->ctx, &this, ei, &val_str);
if(FAILED(hres)) {
jsdisp_release(regexp);
return hres;
}
str = val_str;
length = SysStringLen(val_str);
}
else {
StringInstance *this = (StringInstance*)dispex;
str = this->str;
length = this->length;
}
hres = regexp_match(regexp, str, length, FALSE, &match_result, &match_cnt);
jsdisp_release(regexp);
if(FAILED(hres))
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
if(!match_cnt) {
TRACE("no match\n");
if(retv)
V_VT(retv) = VT_NULL;
SysFreeString(val_str);
return S_OK;
}
hres = create_array(dispex->ctx, match_cnt, &array);
if(FAILED(hres))
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
V_VT(&var) = VT_BSTR;
@ -510,6 +688,8 @@ static HRESULT String_match(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
break;
}
SysFreeString(val_str);
if(SUCCEEDED(hres) && retv) {
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array);
@ -618,11 +798,11 @@ static HRESULT rep_call(DispatchEx *func, const WCHAR *str, match_result_t *matc
static HRESULT String_replace(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
const WCHAR *str;
DWORD parens_cnt = 0, parens_size=0, rep_len=0, length;
BSTR rep_str = NULL, match_str = NULL, ret_str;
BSTR rep_str = NULL, match_str = NULL, ret_str, val_str = NULL;
DispatchEx *rep_func = NULL, *regexp = NULL;
match_result_t *parens = NULL, match;
const WCHAR *str;
strbuf_t ret = {NULL,0,0};
BOOL gcheck = FALSE;
VARIANT *arg_var;
@ -630,23 +810,36 @@ static HRESULT String_replace(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
TRACE("\n");
if(is_class(dispex, JSCLASS_STRING)) {
StringInstance *string = (StringInstance*)dispex;
str = string->str;
length = string->length;
}else {
FIXME("not String this\n");
return E_NOTIMPL;
if(!is_class(dispex, JSCLASS_STRING)) {
VARIANT this;
V_VT(&this) = VT_DISPATCH;
V_DISPATCH(&this) = (IDispatch*)_IDispatchEx_(dispex);
hres = to_string(dispex->ctx, &this, ei, &val_str);
if(FAILED(hres))
return hres;
str = val_str;
length = SysStringLen(val_str);
}
else {
StringInstance *this = (StringInstance*)dispex;
str = this->str;
length = this->length;
}
if(!arg_cnt(dp)) {
if(retv) {
ret_str = SysAllocString(str);
if(!ret_str)
return E_OUTOFMEMORY;
if(!val_str) {
val_str = SysAllocStringLen(str, length);
if(!val_str)
return E_OUTOFMEMORY;
}
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = ret_str;
V_BSTR(retv) = val_str;
}
return S_OK;
}
@ -666,8 +859,10 @@ static HRESULT String_replace(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
default:
hres = to_string(dispex->ctx, arg_var, ei, &match_str);
if(FAILED(hres))
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
}
if(arg_cnt(dp) >= 2) {
@ -760,6 +955,7 @@ static HRESULT String_replace(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
jsdisp_release(rep_func);
if(regexp)
jsdisp_release(regexp);
SysFreeString(val_str);
SysFreeString(rep_str);
SysFreeString(match_str);
heap_free(parens);
@ -790,6 +986,7 @@ static HRESULT String_slice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
const WCHAR *str;
BSTR val_str = NULL;
DWORD length;
INT start=0, end;
VARIANT v;
@ -797,20 +994,32 @@ static HRESULT String_slice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
TRACE("\n");
if(is_class(dispex, JSCLASS_STRING)) {
StringInstance *string = (StringInstance*)dispex;
if(!is_class(dispex, JSCLASS_STRING)) {
VARIANT this;
str = string->str;
length = string->length;
}else {
FIXME("this is not a string class\n");
return E_NOTIMPL;
V_VT(&this) = VT_DISPATCH;
V_DISPATCH(&this) = (IDispatch*)_IDispatchEx_(dispex);
hres = to_string(dispex->ctx, &this, ei, &val_str);
if(FAILED(hres))
return hres;
str = val_str;
length = SysStringLen(val_str);
}
else {
StringInstance *this = (StringInstance*)dispex;
str = this->str;
length = this->length;
}
if(arg_cnt(dp)) {
hres = to_integer(dispex->ctx, dp->rgvarg + dp->cArgs-1, ei, &v);
if(FAILED(hres))
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
if(V_VT(&v) == VT_I4) {
start = V_I4(&v);
@ -830,8 +1039,10 @@ static HRESULT String_slice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
if(arg_cnt(dp) >= 2) {
hres = to_integer(dispex->ctx, dp->rgvarg + dp->cArgs-2, ei, &v);
if(FAILED(hres))
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
if(V_VT(&v) == VT_I4) {
end = V_I4(&v);
@ -854,12 +1065,16 @@ static HRESULT String_slice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
if(retv) {
BSTR retstr = SysAllocStringLen(str+start, end-start);
if(!str)
if(!retstr) {
SysFreeString(val_str);
return E_OUTOFMEMORY;
}
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = retstr;
}
SysFreeString(val_str);
return S_OK;
}
@ -874,28 +1089,40 @@ static HRESULT String_split(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
match_result_t *match_result = NULL;
DWORD match_cnt, i, match_len = 0;
StringInstance *string;
const WCHAR *ptr, *ptr2;
DWORD length, match_cnt, i, match_len = 0;
const WCHAR *str, *ptr, *ptr2;
VARIANT *arg, var;
DispatchEx *array;
BSTR match_str = NULL;
BSTR val_str = NULL, match_str = NULL;
HRESULT hres;
TRACE("\n");
if(!is_class(dispex, JSCLASS_STRING)) {
FIXME("not String this\n");
return E_NOTIMPL;
}
string = (StringInstance*)dispex;
if(arg_cnt(dp) != 1) {
FIXME("unsupported args\n");
return E_NOTIMPL;
}
if(!is_class(dispex, JSCLASS_STRING)) {
VARIANT this;
V_VT(&this) = VT_DISPATCH;
V_DISPATCH(&this) = (IDispatch*)_IDispatchEx_(dispex);
hres = to_string(dispex->ctx, &this, ei, &val_str);
if(FAILED(hres))
return hres;
str = val_str;
length = SysStringLen(val_str);
}
else {
StringInstance *this = (StringInstance*)dispex;
str = this->str;
length = this->length;
}
arg = get_arg(dp, 0);
switch(V_VT(arg)) {
case VT_DISPATCH: {
@ -904,10 +1131,12 @@ static HRESULT String_split(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
if(regexp) {
if(is_class(regexp, JSCLASS_REGEXP)) {
hres = regexp_match(regexp, string->str, string->length, TRUE, &match_result, &match_cnt);
hres = regexp_match(regexp, str, length, TRUE, &match_result, &match_cnt);
jsdisp_release(regexp);
if(FAILED(hres))
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
break;
}
jsdisp_release(regexp);
@ -915,8 +1144,10 @@ static HRESULT String_split(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
}
default:
hres = to_string(dispex->ctx, arg, ei, &match_str);
if(FAILED(hres))
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
match_len = SysStringLen(match_str);
if(!match_len) {
@ -928,7 +1159,7 @@ static HRESULT String_split(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
hres = create_array(dispex->ctx, 0, &array);
if(SUCCEEDED(hres)) {
ptr = string->str;
ptr = str;
for(i=0;; i++) {
if(match_result) {
if(i == match_cnt)
@ -966,7 +1197,7 @@ static HRESULT String_split(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
}
if(SUCCEEDED(hres) && (match_str || match_result)) {
DWORD len = (string->str+string->length) - ptr;
DWORD len = (str+length) - ptr;
if(len || match_str) {
V_VT(&var) = VT_BSTR;
@ -982,6 +1213,7 @@ static HRESULT String_split(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
}
SysFreeString(match_str);
SysFreeString(val_str);
heap_free(match_result);
if(SUCCEEDED(hres) && retv) {
@ -1013,6 +1245,7 @@ static HRESULT String_substring(DispatchEx *dispex, LCID lcid, WORD flags, DISPP
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
const WCHAR *str;
BSTR val_str = NULL;
INT start=0, end;
DWORD length;
VARIANT v;
@ -1020,20 +1253,32 @@ static HRESULT String_substring(DispatchEx *dispex, LCID lcid, WORD flags, DISPP
TRACE("\n");
if(is_class(dispex, JSCLASS_STRING)) {
StringInstance *string = (StringInstance*)dispex;
if(!is_class(dispex, JSCLASS_STRING)) {
VARIANT this;
length = string->length;
str = string->str;
}else {
FIXME("not string this not supported\n");
return E_NOTIMPL;
V_VT(&this) = VT_DISPATCH;
V_DISPATCH(&this) = (IDispatch*)_IDispatchEx_(dispex);
hres = to_string(dispex->ctx, &this, ei, &val_str);
if(FAILED(hres))
return hres;
str = val_str;
length = SysStringLen(val_str);
}
else {
StringInstance *this = (StringInstance*)dispex;
str = this->str;
length = this->length;
}
if(arg_cnt(dp) >= 1) {
hres = to_integer(dispex->ctx, dp->rgvarg + dp->cArgs-1, ei, &v);
if(FAILED(hres))
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
if(V_VT(&v) == VT_I4) {
start = V_I4(&v);
@ -1048,8 +1293,10 @@ static HRESULT String_substring(DispatchEx *dispex, LCID lcid, WORD flags, DISPP
if(arg_cnt(dp) >= 2) {
hres = to_integer(dispex->ctx, dp->rgvarg + dp->cArgs-2, ei, &v);
if(FAILED(hres))
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
if(V_VT(&v) == VT_I4) {
end = V_I4(&v);
@ -1073,9 +1320,12 @@ static HRESULT String_substring(DispatchEx *dispex, LCID lcid, WORD flags, DISPP
if(retv) {
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = SysAllocStringLen(str+start, end-start);
if(!V_BSTR(retv))
if(!V_BSTR(retv)) {
SysFreeString(val_str);
return E_OUTOFMEMORY;
}
}
SysFreeString(val_str);
return S_OK;
}
@ -1096,66 +1346,92 @@ static HRESULT String_sup(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS
static HRESULT String_toLowerCase(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
StringInstance *string;
const WCHAR* str;
DWORD length;
BSTR bstr;
BSTR val_str = NULL;
HRESULT hres;
TRACE("\n");
if(is_class(dispex, JSCLASS_STRING)) {
string = (StringInstance*)dispex;
if(!is_class(dispex, JSCLASS_STRING)) {
VARIANT this;
length = string->length;
str = string->str;
}else {
FIXME("not string this not supported\n");
return E_NOTIMPL;
V_VT(&this) = VT_DISPATCH;
V_DISPATCH(&this) = (IDispatch*)_IDispatchEx_(dispex);
hres = to_string(dispex->ctx, &this, ei, &val_str);
if(FAILED(hres))
return hres;
str = val_str;
length = SysStringLen(val_str);
}
else {
StringInstance *this = (StringInstance*)dispex;
str = this->str;
length = this->length;
}
if(retv) {
bstr = SysAllocStringLen(str, length);
if (!bstr)
return E_OUTOFMEMORY;
if(!val_str) {
val_str = SysAllocStringLen(str, length);
if(!val_str)
return E_OUTOFMEMORY;
}
strlwrW(bstr);
strlwrW(val_str);
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = bstr;
V_BSTR(retv) = val_str;
}
else SysFreeString(val_str);
return S_OK;
}
static HRESULT String_toUpperCase(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
StringInstance *string;
const WCHAR* str;
DWORD length;
BSTR bstr;
BSTR val_str = NULL;
HRESULT hres;
TRACE("\n");
if(is_class(dispex, JSCLASS_STRING)) {
string = (StringInstance*)dispex;
if(!is_class(dispex, JSCLASS_STRING)) {
VARIANT this;
length = string->length;
str = string->str;
}else {
FIXME("not string this not supported\n");
return E_NOTIMPL;
V_VT(&this) = VT_DISPATCH;
V_DISPATCH(&this) = (IDispatch*)_IDispatchEx_(dispex);
hres = to_string(dispex->ctx, &this, ei, &val_str);
if(FAILED(hres))
return hres;
str = val_str;
length = SysStringLen(val_str);
}
else {
StringInstance *this = (StringInstance*)dispex;
str = this->str;
length = this->length;
}
if(retv) {
bstr = SysAllocStringLen(str, length);
if (!bstr)
return E_OUTOFMEMORY;
if(!val_str) {
val_str = SysAllocStringLen(str, length);
if(!val_str)
return E_OUTOFMEMORY;
}
struprW(bstr);
struprW(val_str);
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = bstr;
V_BSTR(retv) = val_str;
}
else SysFreeString(val_str);
return S_OK;
}
@ -1209,6 +1485,8 @@ static HRESULT String_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
TRACE("\n");
switch(flags) {
case INVOKE_FUNC:
return throw_type_error(dispex->ctx, ei, IDS_NOT_FUNC, NULL);
case DISPATCH_PROPERTYGET: {
BSTR str = SysAllocString(This->str);
if(!str)
@ -1282,6 +1560,37 @@ static const builtin_info_t String_info = {
NULL
};
/* ECMA-262 3rd Edition 15.5.3.2 */
static HRESULT StringConstr_fromCharCode(DispatchEx *dispex, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
DWORD i, code;
BSTR ret;
HRESULT hres;
ret = SysAllocStringLen(NULL, arg_cnt(dp));
if(!ret)
return E_OUTOFMEMORY;
for(i=0; i<arg_cnt(dp); i++) {
hres = to_uint32(dispex->ctx, get_arg(dp, i), ei, &code);
if(FAILED(hres)) {
SysFreeString(ret);
return hres;
}
ret[i] = code;
}
if(retv) {
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = ret;
}
else SysFreeString(ret);
return S_OK;
}
static HRESULT StringConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
@ -1361,6 +1670,19 @@ static HRESULT string_alloc(script_ctx_t *ctx, BOOL use_constr, StringInstance *
return S_OK;
}
static const builtin_prop_t StringConstr_props[] = {
{fromCharCodeW, StringConstr_fromCharCode, PROPF_METHOD},
};
static const builtin_info_t StringConstr_info = {
JSCLASS_FUNCTION,
{NULL, Function_value, 0},
sizeof(StringConstr_props)/sizeof(*StringConstr_props),
StringConstr_props,
NULL,
NULL
};
HRESULT create_string_constr(script_ctx_t *ctx, DispatchEx **ret)
{
StringInstance *string;
@ -1370,7 +1692,7 @@ HRESULT create_string_constr(script_ctx_t *ctx, DispatchEx **ret)
if(FAILED(hres))
return hres;
hres = create_builtin_function(ctx, StringConstr_value, NULL, PROPF_CONSTR, &string->dispex, ret);
hres = create_builtin_function(ctx, StringConstr_value, &StringConstr_info, PROPF_CONSTR, &string->dispex, ret);
jsdisp_release(&string->dispex);
return hres;