[JSCRIPT]

sync jscript to wine 1.1.39

svn path=/trunk/; revision=45765
This commit is contained in:
Christoph von Wittich 2010-03-02 19:46:01 +00:00
parent 72a689d62e
commit 8c353150ee
29 changed files with 1991 additions and 1223 deletions

View file

@ -86,7 +86,7 @@ static IUnknown *create_activex_object(script_ctx_t *ctx, const WCHAR *progid)
if(FAILED(hres) || policy != URLPOLICY_ALLOW)
return NULL;
hres = CoGetClassObject(&guid, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, NULL, &IID_IClassFactory, (void**)&cf);
hres = CoGetClassObject(&guid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
if(FAILED(hres))
return NULL;
@ -192,7 +192,8 @@ HRESULT create_activex_constr(script_ctx_t *ctx, DispatchEx **ret)
if(FAILED(hres))
return hres;
hres = create_builtin_function(ctx, ActiveXObject_value, ActiveXObjectW, NULL, PROPF_CONSTR, prototype, ret);
hres = create_builtin_function(ctx, ActiveXObject_value, ActiveXObjectW, NULL,
PROPF_CONSTR|1, prototype, ret);
jsdisp_release(prototype);
return hres;

View file

@ -166,7 +166,7 @@ static HRESULT concat_array(DispatchEx *array, ArrayInstance *obj, DWORD *len,
HRESULT hres;
for(i=0; i < obj->length; i++) {
hres = jsdisp_propget_idx(&obj->dispex, i, &var, ei, caller);
hres = jsdisp_get_idx(&obj->dispex, i, &var, ei, caller);
if(hres == DISP_E_UNKNOWNNAME)
continue;
if(FAILED(hres))
@ -267,8 +267,11 @@ static HRESULT array_join(script_ctx_t *ctx, DispatchEx *array, DWORD length, co
return E_OUTOFMEMORY;
for(i=0; i < length; i++) {
hres = jsdisp_propget_idx(array, i, &var, ei, caller);
if(FAILED(hres))
hres = jsdisp_get_idx(array, i, &var, ei, caller);
if(hres == DISP_E_UNKNOWNNAME) {
hres = S_OK;
continue;
} else if(FAILED(hres))
break;
if(V_VT(&var) != VT_EMPTY && V_VT(&var) != VT_NULL)
@ -342,20 +345,18 @@ static HRESULT array_join(script_ctx_t *ctx, DispatchEx *array, DWORD length, co
}
/* ECMA-262 3rd Edition 15.4.4.5 */
static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
DispatchEx *jsthis;
DWORD length;
HRESULT hres;
TRACE("\n");
if(is_vclass(jsthis, JSCLASS_ARRAY)) {
length = array_from_vdisp(jsthis)->length;
}else {
FIXME("dispid is not Array\n");
return E_NOTIMPL;
}
hres = get_length(ctx, vthis, ei, &jsthis, &length);
if(FAILED(hres))
return hres;
if(arg_cnt(dp)) {
BSTR sep;
@ -364,62 +365,52 @@ static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPA
if(FAILED(hres))
return hres;
hres = array_join(ctx, jsthis->u.jsdisp, length, sep, retv, ei, caller);
hres = array_join(ctx, jsthis, length, sep, retv, ei, caller);
SysFreeString(sep);
}else {
hres = array_join(ctx, jsthis->u.jsdisp, length, default_separatorW, retv, ei, caller);
hres = array_join(ctx, jsthis, length, default_separatorW, retv, ei, caller);
}
return hres;
}
static HRESULT Array_pop(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
static HRESULT Array_pop(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
DispatchEx *jsthis;
VARIANT val;
DWORD length;
WCHAR buf[14];
DISPID id;
HRESULT hres;
static const WCHAR formatW[] = {'%','d',0};
TRACE("\n");
if(is_vclass(jsthis, JSCLASS_ARRAY)) {
ArrayInstance *array = array_from_vdisp(jsthis);
length = array->length;
}else {
FIXME("not Array this\n");
return E_NOTIMPL;
}
hres = get_length(ctx, vthis, ei, &jsthis, &length);
if(FAILED(hres))
return hres;
if(!length) {
hres = set_length(jsthis, ei, 0);
if(FAILED(hres))
return hres;
if(retv)
V_VT(retv) = VT_EMPTY;
return S_OK;
}
sprintfW(buf, formatW, --length);
hres = jsdisp_get_id(jsthis->u.jsdisp, buf, 0, &id);
length--;
hres = jsdisp_get_idx(jsthis, length, &val, ei, caller);
if(SUCCEEDED(hres)) {
hres = jsdisp_propget(jsthis->u.jsdisp, id, &val, ei, caller);
if(FAILED(hres))
return hres;
hres = IDispatchEx_DeleteMemberByDispID(jsthis->u.dispex, id);
}else if(hres == DISP_E_UNKNOWNNAME) {
hres = jsdisp_delete_idx(jsthis, length);
} else if(hres == DISP_E_UNKNOWNNAME) {
V_VT(&val) = VT_EMPTY;
hres = S_OK;
}else {
} else
return hres;
}
if(SUCCEEDED(hres)) {
ArrayInstance *array = array_from_vdisp(jsthis);
array->length = length;
}
if(SUCCEEDED(hres))
hres = set_length(jsthis, ei, length);
if(FAILED(hres)) {
VariantClear(&val);
@ -430,6 +421,7 @@ static HRESULT Array_pop(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPAR
*retv = val;
else
VariantClear(&val);
return S_OK;
}
@ -469,8 +461,59 @@ static HRESULT Array_push(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPAR
static HRESULT Array_reverse(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
DispatchEx *jsthis;
DWORD length, k, l;
VARIANT v1, v2;
HRESULT hres1, hres2;
TRACE("\n");
hres1 = get_length(ctx, vthis, ei, &jsthis, &length);
if(FAILED(hres1))
return hres1;
for(k=0; k<length/2; k++) {
l = length-k-1;
hres1 = jsdisp_get_idx(jsthis, k, &v1, ei, sp);
if(FAILED(hres1) && hres1!=DISP_E_UNKNOWNNAME)
return hres1;
hres2 = jsdisp_get_idx(jsthis, l, &v2, ei, sp);
if(FAILED(hres2) && hres2!=DISP_E_UNKNOWNNAME) {
VariantClear(&v1);
return hres2;
}
if(hres1 == DISP_E_UNKNOWNNAME)
hres1 = jsdisp_delete_idx(jsthis, l);
else
hres1 = jsdisp_propput_idx(jsthis, l, &v1, ei, sp);
if(FAILED(hres1)) {
VariantClear(&v1);
VariantClear(&v2);
return hres1;
}
if(hres2 == DISP_E_UNKNOWNNAME)
hres2 = jsdisp_delete_idx(jsthis, k);
else
hres2 = jsdisp_propput_idx(jsthis, k, &v2, ei, sp);
if(FAILED(hres2)) {
VariantClear(&v2);
return hres2;
}
}
if(retv) {
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(jsthis);
IDispatch_AddRef(V_DISPATCH(retv));
}
return S_OK;
}
/* ECMA-262 3rd Edition 15.4.4.9 */
@ -500,14 +543,14 @@ static HRESULT Array_shift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPA
return S_OK;
}
hres = jsdisp_propget_idx(jsthis, 0, &ret, ei, caller);
hres = jsdisp_get_idx(jsthis, 0, &ret, ei, caller);
if(hres == DISP_E_UNKNOWNNAME) {
V_VT(&ret) = VT_EMPTY;
hres = S_OK;
}
for(i=1; SUCCEEDED(hres) && i<length; i++) {
hres = jsdisp_propget_idx(jsthis, i, &v, ei, caller);
hres = jsdisp_get_idx(jsthis, i, &v, ei, caller);
if(hres == DISP_E_UNKNOWNNAME)
hres = jsdisp_delete_idx(jsthis, i-1);
else if(SUCCEEDED(hres))
@ -582,12 +625,14 @@ static HRESULT Array_slice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPA
return hres;
for(idx=start; idx<end; idx++) {
hres = jsdisp_propget_idx(jsthis, idx, &v, ei, sp);
hres = jsdisp_get_idx(jsthis, idx, &v, ei, sp);
if(hres == DISP_E_UNKNOWNNAME)
continue;
if(SUCCEEDED(hres))
if(SUCCEEDED(hres)) {
hres = jsdisp_propput_idx(arr, idx-start, &v, ei, sp);
VariantClear(&v);
}
if(FAILED(hres)) {
jsdisp_release(arr);
@ -661,10 +706,10 @@ static HRESULT sort_cmp(script_ctx_t *ctx, DispatchEx *cmp_func, VARIANT *v1, VA
}
/* ECMA-262 3rd Edition 15.4.4.11 */
static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
DispatchEx *cmp_func = NULL;
DispatchEx *jsthis, *cmp_func = NULL;
VARIANT *vtab, **sorttab = NULL;
DWORD length;
DWORD i;
@ -672,12 +717,9 @@ static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPA
TRACE("\n");
if(is_vclass(jsthis, JSCLASS_ARRAY)) {
length = array_from_vdisp(jsthis)->length;
}else {
FIXME("unsupported this not array\n");
return E_NOTIMPL;
}
hres = get_length(ctx, vthis, ei, &jsthis, &length);
if(FAILED(hres))
return hres;
if(arg_cnt(dp) > 1) {
WARN("invalid arg_cnt %d\n", arg_cnt(dp));
@ -707,8 +749,8 @@ static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPA
jsdisp_release(cmp_func);
if(retv) {
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = jsthis->u.disp;
IDispatch_AddRef(jsthis->u.disp);
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(jsthis);
IDispatch_AddRef(V_DISPATCH(retv));
}
return S_OK;
}
@ -716,8 +758,11 @@ static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPA
vtab = heap_alloc_zero(length * sizeof(VARIANT));
if(vtab) {
for(i=0; i<length; i++) {
hres = jsdisp_propget_idx(jsthis->u.jsdisp, i, vtab+i, ei, caller);
if(FAILED(hres) && hres != DISP_E_UNKNOWNNAME) {
hres = jsdisp_get_idx(jsthis, i, vtab+i, ei, caller);
if(hres == DISP_E_UNKNOWNNAME) {
V_VT(vtab+i) = VT_EMPTY;
hres = S_OK;
} else if(FAILED(hres)) {
WARN("Could not get elem %d: %08x\n", i, hres);
break;
}
@ -793,7 +838,7 @@ static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPA
}
for(i=0; SUCCEEDED(hres) && i < length; i++)
hres = jsdisp_propput_idx(jsthis->u.jsdisp, i, sorttab[i], ei, caller);
hres = jsdisp_propput_idx(jsthis, i, sorttab[i], ei, caller);
}
if(vtab) {
@ -810,8 +855,8 @@ static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPA
if(retv) {
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = jsthis->u.disp;
IDispatch_AddRef(jsthis->u.disp);
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(jsthis);
IDispatch_AddRef(V_DISPATCH(retv));
}
return S_OK;
@ -869,7 +914,7 @@ static HRESULT Array_splice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPP
return hres;
for(i=0; SUCCEEDED(hres) && i < delete_cnt; i++) {
hres = jsdisp_propget_idx(jsthis, start+i, &v, ei, caller);
hres = jsdisp_get_idx(jsthis, start+i, &v, ei, caller);
if(hres == DISP_E_UNKNOWNNAME)
hres = S_OK;
else if(SUCCEEDED(hres))
@ -886,7 +931,7 @@ static HRESULT Array_splice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPP
if(add_args < delete_cnt) {
for(i = start; SUCCEEDED(hres) && i < length-delete_cnt; i++) {
hres = jsdisp_propget_idx(jsthis, i+delete_cnt, &v, ei, caller);
hres = jsdisp_get_idx(jsthis, i+delete_cnt, &v, ei, caller);
if(hres == DISP_E_UNKNOWNNAME)
hres = jsdisp_delete_idx(jsthis, i+add_args);
else if(SUCCEEDED(hres))
@ -897,7 +942,7 @@ static HRESULT Array_splice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPP
hres = jsdisp_delete_idx(jsthis, i-1);
}else if(add_args > delete_cnt) {
for(i=length-delete_cnt; SUCCEEDED(hres) && i != start; i--) {
hres = jsdisp_propget_idx(jsthis, i+delete_cnt-1, &v, ei, caller);
hres = jsdisp_get_idx(jsthis, i+delete_cnt-1, &v, ei, caller);
if(hres == DISP_E_UNKNOWNNAME)
hres = jsdisp_delete_idx(jsthis, i+add_args-1);
else if(SUCCEEDED(hres))
@ -967,29 +1012,25 @@ static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISP
return hres;
argc = arg_cnt(dp);
if(!argc) {
if(retv)
V_VT(retv) = VT_EMPTY;
return S_OK;
}
if(argc) {
buf_end = buf + sizeof(buf)/sizeof(WCHAR)-1;
*buf_end-- = 0;
i = length;
buf_end = buf + sizeof(buf)/sizeof(WCHAR)-1;
*buf_end-- = 0;
i = length;
while(i--) {
str = idx_to_str(i, buf_end);
while(i--) {
str = idx_to_str(i, buf_end);
hres = jsdisp_get_id(jsthis, str, 0, &id);
if(SUCCEEDED(hres)) {
hres = jsdisp_propget(jsthis, id, &var, ei, caller);
if(FAILED(hres))
return hres;
hres = jsdisp_get_id(jsthis, str, 0, &id);
if(SUCCEEDED(hres)) {
hres = jsdisp_propget(jsthis, id, &var, ei, caller);
if(FAILED(hres))
return hres;
hres = jsdisp_propput_idx(jsthis, i+argc, &var, ei, caller);
VariantClear(&var);
}else if(hres == DISP_E_UNKNOWNNAME) {
hres = IDispatchEx_DeleteMemberByDispID(vthis->u.dispex, id);
hres = jsdisp_propput_idx(jsthis, i+argc, &var, ei, caller);
VariantClear(&var);
}else if(hres == DISP_E_UNKNOWNNAME) {
hres = IDispatchEx_DeleteMemberByDispID(vthis->u.dispex, id);
}
}
if(FAILED(hres))
@ -1002,12 +1043,21 @@ static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISP
return hres;
}
hres = set_length(jsthis, ei, length+argc);
if(FAILED(hres))
return hres;
if(argc) {
length += argc;
hres = set_length(jsthis, ei, length);
if(FAILED(hres))
return hres;
}
if(retv)
V_VT(retv) = VT_EMPTY;
if(retv) {
if(ctx->version < 2) {
V_VT(retv) = VT_EMPTY;
}else {
V_VT(retv) = VT_I4;
V_I4(retv) = length;
}
}
return S_OK;
}
@ -1166,7 +1216,7 @@ HRESULT create_array_constr(script_ctx_t *ctx, DispatchEx *object_prototype, Dis
if(FAILED(hres))
return hres;
hres = create_builtin_function(ctx, ArrayConstr_value, ArrayW, NULL, PROPF_CONSTR, &array->dispex, ret);
hres = create_builtin_function(ctx, ArrayConstr_value, ArrayW, NULL, PROPF_CONSTR|1, &array->dispex, ret);
jsdisp_release(&array->dispex);
return hres;

View file

@ -191,7 +191,8 @@ HRESULT create_bool_constr(script_ctx_t *ctx, DispatchEx *object_prototype, Disp
if(FAILED(hres))
return hres;
hres = create_builtin_function(ctx, BoolConstr_value, BooleanW, NULL, PROPF_CONSTR, &bool->dispex, ret);
hres = create_builtin_function(ctx, BoolConstr_value, BooleanW, NULL,
PROPF_CONSTR|1, &bool->dispex, ret);
jsdisp_release(&bool->dispex);
return hres;

View file

@ -2624,7 +2624,8 @@ HRESULT create_date_constr(script_ctx_t *ctx, DispatchEx *object_prototype, Disp
if(FAILED(hres))
return hres;
hres = create_builtin_function(ctx, DateConstr_value, DateW, &DateConstr_info, PROPF_CONSTR, date, ret);
hres = create_builtin_function(ctx, DateConstr_value, DateW, &DateConstr_info,
PROPF_CONSTR|7, date, ret);
jsdisp_release(date);
return hres;

View file

@ -30,6 +30,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript);
static const IID IID_IDispatchJS =
{0x719c3050,0xf9d3,0x11cf,{0xa4,0x93,0x00,0x40,0x05,0x23,0xa8,0xa6}};
#define FDEX_VERSION_MASK 0xf0000000
typedef enum {
PROP_VARIANT,
PROP_BUILTIN,
@ -158,7 +160,7 @@ static HRESULT find_prop_name(DispatchEx *This, const WCHAR *name, dispex_prop_t
return S_OK;
}
static HRESULT find_prop_name_prot(DispatchEx *This, const WCHAR *name, BOOL alloc, dispex_prop_t **ret)
static HRESULT find_prop_name_prot(DispatchEx *This, const WCHAR *name, dispex_prop_t **ret)
{
dispex_prop_t *prop;
HRESULT hres;
@ -172,7 +174,7 @@ static HRESULT find_prop_name_prot(DispatchEx *This, const WCHAR *name, BOOL all
}
if(This->prototype) {
hres = find_prop_name_prot(This->prototype, name, FALSE, &prop);
hres = find_prop_name_prot(This->prototype, name, &prop);
if(FAILED(hres))
return hres;
if(prop) {
@ -184,17 +186,30 @@ static HRESULT find_prop_name_prot(DispatchEx *This, const WCHAR *name, BOOL all
}
}
if(alloc) {
*ret = prop;
return S_OK;
}
static HRESULT ensure_prop_name(DispatchEx *This, const WCHAR *name, BOOL search_prot, DWORD create_flags, dispex_prop_t **ret)
{
dispex_prop_t *prop;
HRESULT hres;
if(search_prot)
hres = find_prop_name_prot(This, name, &prop);
else
hres = find_prop_name(This, name, &prop);
if(SUCCEEDED(hres) && !prop) {
TRACE("creating prop %s\n", debugstr_w(name));
prop = alloc_prop(This, name, PROP_VARIANT, PROPF_ENUM);
prop = alloc_prop(This, name, PROP_VARIANT, create_flags);
if(!prop)
return E_OUTOFMEMORY;
VariantInit(&prop->u.var);
}
*ret = prop;
return S_OK;
return hres;
}
static HRESULT set_this(DISPPARAMS *dp, DISPPARAMS *olddp, IDispatch *jsthis)
@ -338,19 +353,19 @@ static HRESULT prop_get(DispatchEx *This, dispex_prop_t *prop, DISPPARAMS *dp,
return hres;
}
static HRESULT prop_put(DispatchEx *This, dispex_prop_t *prop, DISPPARAMS *dp,
static HRESULT prop_put(DispatchEx *This, dispex_prop_t *prop, VARIANT *val,
jsexcept_t *ei, IServiceProvider *caller)
{
DWORD i;
HRESULT hres;
switch(prop->type) {
case PROP_BUILTIN:
if(!(prop->flags & PROPF_METHOD)) {
DISPPARAMS dp = {val, NULL, 1, 0};
vdisp_t vthis;
set_jsdisp(&vthis, This);
hres = prop->u.p->invoke(This->ctx, &vthis, DISPATCH_PROPERTYPUT, dp, NULL, ei, caller);
hres = prop->u.p->invoke(This->ctx, &vthis, DISPATCH_PROPERTYPUT, &dp, NULL, ei, caller);
vdisp_release(&vthis);
return hres;
}
@ -367,24 +382,14 @@ static HRESULT prop_put(DispatchEx *This, dispex_prop_t *prop, DISPPARAMS *dp,
return E_FAIL;
}
for(i=0; i < dp->cNamedArgs; i++) {
if(dp->rgdispidNamedArgs[i] == DISPID_PROPERTYPUT)
break;
}
if(i == dp->cNamedArgs) {
TRACE("no value to set\n");
return DISP_E_PARAMNOTOPTIONAL;
}
hres = VariantCopy(&prop->u.var, dp->rgvarg+i);
hres = VariantCopy(&prop->u.var, val);
if(FAILED(hres))
return hres;
if(This->builtin_info->on_put)
This->builtin_info->on_put(This, prop->name);
TRACE("%s = %s\n", debugstr_w(prop->name), debugstr_variant(dp->rgvarg+i));
TRACE("%s = %s\n", debugstr_w(prop->name), debugstr_variant(val));
return S_OK;
}
@ -471,6 +476,8 @@ static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
}
heap_free(This->props);
script_release(This->ctx);
if(This->prototype)
jsdisp_release(This->prototype);
if(This->builtin_info->destructor)
This->builtin_info->destructor(This);
@ -538,7 +545,7 @@ static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DW
TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
if(grfdex & ~(fdexNameCaseSensitive|fdexNameEnsure|fdexNameImplicit)) {
if(grfdex & ~(fdexNameCaseSensitive|fdexNameEnsure|fdexNameImplicit|FDEX_VERSION_MASK)) {
FIXME("Unsupported grfdex %x\n", grfdex);
return E_NOTIMPL;
}
@ -575,9 +582,22 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
case DISPATCH_PROPERTYGET:
hres = prop_get(This, prop, pdp, pvarRes, &jsexcept, pspCaller);
break;
case DISPATCH_PROPERTYPUT:
hres = prop_put(This, prop, pdp, &jsexcept, pspCaller);
case DISPATCH_PROPERTYPUT: {
DWORD i;
for(i=0; i < pdp->cNamedArgs; i++) {
if(pdp->rgdispidNamedArgs[i] == DISPID_PROPERTYPUT)
break;
}
if(i == pdp->cNamedArgs) {
TRACE("no value to set\n");
return DISP_E_PARAMNOTOPTIONAL;
}
hres = prop_put(This, prop, pdp->rgvarg+i, &jsexcept, pspCaller);
break;
}
default:
FIXME("Unimplemented flags %x\n", wFlags);
return E_INVALIDARG;
@ -606,7 +626,7 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bst
TRACE("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex);
if(grfdex & ~(fdexNameCaseSensitive|fdexNameEnsure|fdexNameImplicit))
if(grfdex & ~(fdexNameCaseSensitive|fdexNameEnsure|fdexNameImplicit|FDEX_VERSION_MASK))
FIXME("Unsupported grfdex %x\n", grfdex);
hres = find_prop_name(This, bstrName, &prop);
@ -783,9 +803,10 @@ HRESULT init_dispex_from_constr(DispatchEx *dispex, script_ctx_t *ctx, const bui
dispex_prop_t *prop;
HRESULT hres;
static const WCHAR constructorW[] = {'c','o','n','s','t','r','u','c','t','o','r'};
static const WCHAR prototypeW[] = {'p','r','o','t','o','t','y','p','e',0};
hres = find_prop_name_prot(constr, prototypeW, FALSE, &prop);
hres = find_prop_name_prot(constr, prototypeW, &prop);
if(SUCCEEDED(hres) && prop) {
jsexcept_t jsexcept;
VARIANT var;
@ -807,6 +828,22 @@ HRESULT init_dispex_from_constr(DispatchEx *dispex, script_ctx_t *ctx, const bui
if(prot)
jsdisp_release(prot);
if(FAILED(hres))
return hres;
hres = ensure_prop_name(dispex, constructorW, FALSE, 0, &prop);
if(SUCCEEDED(hres)) {
jsexcept_t jsexcept;
VARIANT var;
V_VT(&var) = VT_DISPATCH;
V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(constr);
memset(&jsexcept, 0, sizeof(jsexcept));
hres = prop_put(dispex, prop, &var, &jsexcept, NULL/*FIXME*/);
}
if(FAILED(hres))
jsdisp_release(dispex);
return hres;
}
@ -827,7 +864,10 @@ HRESULT jsdisp_get_id(DispatchEx *jsdisp, const WCHAR *name, DWORD flags, DISPID
dispex_prop_t *prop;
HRESULT hres;
hres = find_prop_name_prot(jsdisp, name, (flags&fdexNameEnsure) != 0, &prop);
if(flags & fdexNameEnsure)
hres = ensure_prop_name(jsdisp, name, TRUE, PROPF_ENUM, &prop);
else
hres = find_prop_name_prot(jsdisp, name, &prop);
if(FAILED(hres))
return hres;
@ -874,7 +914,7 @@ HRESULT jsdisp_call_name(DispatchEx *disp, const WCHAR *name, WORD flags, DISPPA
dispex_prop_t *prop;
HRESULT hres;
hres = find_prop_name_prot(disp, name, TRUE, &prop);
hres = find_prop_name_prot(disp, name, &prop);
if(FAILED(hres))
return hres;
@ -924,16 +964,14 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DIS
HRESULT jsdisp_propput_name(DispatchEx *obj, const WCHAR *name, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
{
DISPID named_arg = DISPID_PROPERTYPUT;
DISPPARAMS dp = {val, &named_arg, 1, 1};
dispex_prop_t *prop;
HRESULT hres;
hres = find_prop_name_prot(obj, name, TRUE, &prop);
hres = ensure_prop_name(obj, name, FALSE, PROPF_ENUM, &prop);
if(FAILED(hres))
return hres;
return prop_put(obj, prop, &dp, ei, caller);
return prop_put(obj, prop, val, ei, caller);
}
HRESULT jsdisp_propput_idx(DispatchEx *obj, DWORD idx, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
@ -948,9 +986,6 @@ HRESULT jsdisp_propput_idx(DispatchEx *obj, DWORD idx, VARIANT *val, jsexcept_t
HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
{
DISPID dispid = DISPID_PROPERTYPUT;
DISPPARAMS dp = {val, &dispid, 1, 1};
IDispatchEx *dispex;
DispatchEx *jsdisp;
HRESULT hres;
@ -960,25 +995,28 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *val
prop = get_prop(jsdisp, id);
if(prop)
hres = prop_put(jsdisp, prop, &dp, ei, caller);
hres = prop_put(jsdisp, prop, val, ei, caller);
else
hres = DISP_E_MEMBERNOTFOUND;
jsdisp_release(jsdisp);
return hres;
}else {
DISPID dispid = DISPID_PROPERTYPUT;
DISPPARAMS dp = {val, &dispid, 1, 1};
IDispatchEx *dispex;
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(SUCCEEDED(hres)) {
hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, caller);
IDispatchEx_Release(dispex);
}else {
ULONG err = 0;
TRACE("using IDispatch\n");
hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, &err);
}
}
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(FAILED(hres)) {
ULONG err = 0;
TRACE("using IDispatch\n");
return IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, &err);
}
hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, caller);
IDispatchEx_Release(dispex);
return hres;
}
@ -988,7 +1026,7 @@ HRESULT jsdisp_propget_name(DispatchEx *obj, const WCHAR *name, VARIANT *var, js
dispex_prop_t *prop;
HRESULT hres;
hres = find_prop_name_prot(obj, name, FALSE, &prop);
hres = find_prop_name_prot(obj, name, &prop);
if(FAILED(hres))
return hres;
@ -999,14 +1037,26 @@ HRESULT jsdisp_propget_name(DispatchEx *obj, const WCHAR *name, VARIANT *var, js
return prop_get(obj, prop, &dp, var, ei, caller);
}
HRESULT jsdisp_propget_idx(DispatchEx *obj, DWORD idx, VARIANT *var, jsexcept_t *ei, IServiceProvider *caller)
HRESULT jsdisp_get_idx(DispatchEx *obj, DWORD idx, VARIANT *var, jsexcept_t *ei, IServiceProvider *caller)
{
WCHAR buf[12];
WCHAR name[12];
DISPPARAMS dp = {NULL, NULL, 0, 0};
dispex_prop_t *prop;
HRESULT hres;
static const WCHAR formatW[] = {'%','d',0};
sprintfW(buf, formatW, idx);
return jsdisp_propget_name(obj, buf, var, ei, caller);
sprintfW(name, formatW, idx);
hres = find_prop_name_prot(obj, name, &prop);
if(FAILED(hres))
return hres;
V_VT(var) = VT_EMPTY;
if(!prop)
return DISP_E_UNKNOWNNAME;
return prop_get(obj, prop, &dp, var, ei, caller);
}
HRESULT jsdisp_propget(DispatchEx *jsdisp, DISPID id, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)

View file

@ -223,7 +223,7 @@ void exec_release(exec_ctx_t *ctx)
heap_free(ctx);
}
static HRESULT disp_get_id(IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
{
IDispatchEx *dispex;
HRESULT hres;
@ -237,7 +237,7 @@ static HRESULT disp_get_id(IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
}
*id = 0;
hres = IDispatchEx_GetDispID(dispex, name, flags|fdexNameCaseSensitive, id);
hres = IDispatchEx_GetDispID(dispex, name, make_grfdex(ctx, flags|fdexNameCaseSensitive), id);
IDispatchEx_Release(dispex);
return hres;
}
@ -347,33 +347,45 @@ static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
return S_OK;
}
static HRESULT literal_to_var(literal_t *literal, VARIANT *v)
static HRESULT literal_to_var(script_ctx_t *ctx, literal_t *literal, VARIANT *v)
{
V_VT(v) = literal->vt;
switch(V_VT(v)) {
case VT_EMPTY:
case VT_NULL:
switch(literal->type) {
case LT_NULL:
V_VT(v) = VT_NULL;
break;
case VT_I4:
case LT_INT:
V_VT(v) = VT_I4;
V_I4(v) = literal->u.lval;
break;
case VT_R8:
case LT_DOUBLE:
V_VT(v) = VT_R8;
V_R8(v) = literal->u.dval;
break;
case VT_BSTR:
V_BSTR(v) = SysAllocString(literal->u.wstr);
case LT_STRING: {
BSTR str = SysAllocString(literal->u.wstr);
if(!str)
return E_OUTOFMEMORY;
V_VT(v) = VT_BSTR;
V_BSTR(v) = str;
break;
case VT_BOOL:
}
case LT_BOOL:
V_VT(v) = VT_BOOL;
V_BOOL(v) = literal->u.bval;
break;
case VT_DISPATCH:
IDispatch_AddRef(literal->u.disp);
V_DISPATCH(v) = literal->u.disp;
break;
default:
ERR("wrong type %d\n", V_VT(v));
return E_NOTIMPL;
case LT_REGEXP: {
DispatchEx *regexp;
HRESULT hres;
hres = create_regexp(ctx, literal->u.regexp.str, literal->u.regexp.str_len,
literal->u.regexp.flags, &regexp);
if(FAILED(hres))
return hres;
V_VT(v) = VT_DISPATCH;
V_DISPATCH(v) = (IDispatch*)_IDispatchEx_(regexp);
}
}
return S_OK;
@ -387,7 +399,7 @@ static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t
for(item = ctx->named_items; item; item = item->next) {
if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
hres = disp_get_id(item->disp, identifier, 0, &id);
hres = disp_get_id(ctx, item->disp, identifier, 0, &id);
if(SUCCEEDED(hres)) {
if(ret)
exprval_set_idref(ret, item->disp, id);
@ -399,7 +411,8 @@ static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t
return FALSE;
}
HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, jsexcept_t *ei, VARIANT *retv)
HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, exec_type_t exec_type,
jsexcept_t *ei, VARIANT *retv)
{
script_ctx_t *script = parser->script;
function_declaration_t *func;
@ -478,10 +491,14 @@ HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *so
return hres;
}
if(retv)
if(retv && (exec_type == EXECT_EVAL || rt.type == RT_RETURN))
*retv = val;
else
else {
if (retv) {
VariantInit(retv);
}
VariantClear(&val);
}
return S_OK;
}
@ -1380,7 +1397,7 @@ HRESULT array_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags,
TRACE("\n");
hres = expr_eval(ctx, expr->member_expr, EXPR_NEWREF, ei, &exprval);
hres = expr_eval(ctx, expr->member_expr, 0, ei, &exprval);
if(FAILED(hres))
return hres;
@ -1395,11 +1412,15 @@ HRESULT array_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags,
exprval_release(&exprval);
}
if(SUCCEEDED(hres))
if(SUCCEEDED(hres)) {
hres = to_object(ctx->parser->script, &member, &obj);
if(FAILED(hres))
VariantClear(&val);
}
VariantClear(&member);
if(SUCCEEDED(hres)) {
hres = to_string(ctx->parser->script, &val, ei, &str);
VariantClear(&val);
if(SUCCEEDED(hres)) {
if(flags & EXPR_STRREF) {
ret->type = EXPRVAL_NAMEREF;
@ -1408,7 +1429,8 @@ HRESULT array_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags,
return S_OK;
}
hres = disp_get_id(obj, str, flags & EXPR_NEWREF ? fdexNameEnsure : 0, &id);
hres = disp_get_id(ctx->parser->script, obj, str, flags & EXPR_NEWREF ? fdexNameEnsure : 0, &id);
SysFreeString(str);
}
if(SUCCEEDED(hres)) {
@ -1459,7 +1481,7 @@ HRESULT member_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags
return S_OK;
}
hres = disp_get_id(obj, str, flags & EXPR_NEWREF ? fdexNameEnsure : 0, &id);
hres = disp_get_id(ctx->parser->script, obj, str, flags & EXPR_NEWREF ? fdexNameEnsure : 0, &id);
SysFreeString(str);
if(SUCCEEDED(hres)) {
exprval_set_idref(ret, obj, id);
@ -1552,6 +1574,7 @@ HRESULT new_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, j
hres = disp_call(ctx->parser->script, V_DISPATCH(&constr), DISPID_VALUE,
DISPATCH_CONSTRUCT, &dp, &var, ei, NULL/*FIXME*/);
IDispatch_Release(V_DISPATCH(&constr));
free_dp(&dp);
if(FAILED(hres))
return hres;
@ -1654,7 +1677,7 @@ HRESULT literal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flag
TRACE("\n");
hres = literal_to_var(expr->literal, &var);
hres = literal_to_var(ctx->parser->script, expr->literal, &var);
if(FAILED(hres))
return hres;
@ -1733,7 +1756,7 @@ HRESULT property_value_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWO
return hres;
for(iter = expr->property_list; iter; iter = iter->next) {
hres = literal_to_var(iter->name, &tmp);
hres = literal_to_var(ctx->parser->script, iter->name, &tmp);
if(FAILED(hres))
break;
@ -2053,7 +2076,7 @@ static HRESULT in_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *obj, jsexcept_t
if(FAILED(hres))
return hres;
hres = disp_get_id(V_DISPATCH(obj), str, 0, &id);
hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id);
SysFreeString(str);
if(SUCCEEDED(hres))
ret = VARIANT_TRUE;
@ -2293,7 +2316,8 @@ HRESULT delete_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags
hres = IDispatch_QueryInterface(exprval.u.nameref.disp, &IID_IDispatchEx, (void**)&dispex);
if(SUCCEEDED(hres)) {
hres = IDispatchEx_DeleteMemberByName(dispex, exprval.u.nameref.name, fdexNameCaseSensitive);
hres = IDispatchEx_DeleteMemberByName(dispex, exprval.u.nameref.name,
make_grfdex(ctx->parser->script, fdexNameCaseSensitive));
b = VARIANT_TRUE;
IDispatchEx_Release(dispex);
}
@ -2472,6 +2496,7 @@ HRESULT plus_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags,
return hres;
hres = to_number(ctx->parser->script, &val, ei, &num);
VariantClear(&val);
if(FAILED(hres))
return hres;
@ -2731,6 +2756,8 @@ HRESULT equal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags,
return hres;
hres = equal_values(ctx, &rval, &lval, ei, &b);
VariantClear(&lval);
VariantClear(&rval);
if(FAILED(hres))
return hres;
@ -2752,6 +2779,8 @@ HRESULT equal2_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags
return hres;
hres = equal2_values(&rval, &lval, &b);
VariantClear(&lval);
VariantClear(&rval);
if(FAILED(hres))
return hres;
@ -2773,6 +2802,8 @@ HRESULT not_equal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD fl
return hres;
hres = equal_values(ctx, &lval, &rval, ei, &b);
VariantClear(&lval);
VariantClear(&rval);
if(FAILED(hres))
return hres;
@ -2794,6 +2825,8 @@ HRESULT not_equal2_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD f
return hres;
hres = equal2_values(&lval, &rval, &b);
VariantClear(&lval);
VariantClear(&rval);
if(FAILED(hres))
return hres;
@ -3096,8 +3129,11 @@ HRESULT assign_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags
exprval_release(&exprvalr);
}
if(SUCCEEDED(hres))
if(SUCCEEDED(hres)) {
hres = put_value(ctx->parser->script, &exprval, &rval, ei);
if(FAILED(hres))
VariantClear(&rval);
}
exprval_release(&exprval);
if(FAILED(hres))

View file

@ -19,11 +19,6 @@
typedef struct _source_elements_t source_elements_t;
typedef struct _function_expression_t function_expression_t;
typedef struct _obj_literal_t {
DispatchEx *obj;
struct _obj_literal_t *next;
} obj_literal_t;
typedef struct _function_declaration_t {
function_expression_t *expr;
@ -48,9 +43,9 @@ typedef struct _func_stack {
typedef struct _parser_ctx_t {
LONG ref;
const WCHAR *ptr;
const WCHAR *begin;
WCHAR *begin;
const WCHAR *end;
const WCHAR *ptr;
script_ctx_t *script;
source_elements_t *source;
@ -61,7 +56,6 @@ typedef struct _parser_ctx_t {
jsheap_t heap;
obj_literal_t *obj_literals;
func_stack_t *func_stack;
struct _parser_ctx_t *next;
@ -115,9 +109,15 @@ static inline void exec_addref(exec_ctx_t *ctx)
ctx->ref++;
}
typedef enum {
EXECT_PROGRAM,
EXECT_FUNCTION,
EXECT_EVAL
} exec_type_t;
void exec_release(exec_ctx_t*);
HRESULT create_exec_ctx(script_ctx_t*,IDispatch*,DispatchEx*,scope_chain_t*,exec_ctx_t**);
HRESULT exec_source(exec_ctx_t*,parser_ctx_t*,source_elements_t*,jsexcept_t*,VARIANT*);
HRESULT exec_source(exec_ctx_t*,parser_ctx_t*,source_elements_t*,exec_type_t,jsexcept_t*,VARIANT*);
typedef struct _statement_t statement_t;
typedef struct _expression_t expression_t;
@ -126,14 +126,28 @@ typedef struct _parameter_t parameter_t;
HRESULT create_source_function(parser_ctx_t*,parameter_t*,source_elements_t*,scope_chain_t*,
const WCHAR*,DWORD,DispatchEx**);
typedef enum {
LT_INT,
LT_DOUBLE,
LT_STRING,
LT_BOOL,
LT_NULL,
LT_REGEXP
}literal_type_t;
typedef struct {
VARTYPE vt;
literal_type_t type;
union {
LONG lval;
double dval;
const WCHAR *wstr;
VARIANT_BOOL bval;
IDispatch *disp;
struct {
const WCHAR *str;
DWORD str_len;
DWORD flags;
} regexp;
} u;
} literal_t;

View file

@ -36,6 +36,7 @@ typedef struct {
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 nameW[] = {'n','a','m','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};
@ -44,6 +45,11 @@ static inline ErrorInstance *error_from_vdisp(vdisp_t *vdisp)
return (ErrorInstance*)vdisp->u.jsdisp;
}
static inline ErrorInstance *error_this(vdisp_t *jsthis)
{
return is_vclass(jsthis, JSCLASS_ERROR) ? error_from_vdisp(jsthis) : NULL;
}
static HRESULT Error_number(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
@ -101,17 +107,77 @@ static HRESULT Error_message(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
/* ECMA-262 3rd Edition 15.11.4.4 */
static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
ErrorInstance *error;
BSTR name, msg = NULL, ret = NULL;
VARIANT v;
HRESULT hres;
static const WCHAR str[] = {'[','o','b','j','e','c','t',' ','E','r','r','o','r',']',0};
TRACE("\n");
error = error_this(jsthis);
if(ctx->version < 2 || !error) {
if(retv) {
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = SysAllocString(str);
if(!V_BSTR(retv))
return E_OUTOFMEMORY;
}
return S_OK;
}
hres = jsdisp_propget_name(&error->dispex, nameW, &v, ei, caller);
if(FAILED(hres))
return hres;
hres = to_string(ctx, &v, ei, &name);
VariantClear(&v);
if(FAILED(hres))
return hres;
if(V_VT(&error->message) != VT_EMPTY) {
hres = to_string(ctx, &error->message, ei, &msg);
if(SUCCEEDED(hres) && !*msg) {
SysFreeString(msg);
msg = NULL;
}
}
if(SUCCEEDED(hres)) {
if(msg) {
DWORD name_len, msg_len;
name_len = SysStringLen(name);
msg_len = SysStringLen(msg);
ret = SysAllocStringLen(NULL, name_len + msg_len + 2);
if(ret) {
memcpy(ret, name, name_len*sizeof(WCHAR));
ret[name_len] = ':';
ret[name_len+1] = ' ';
memcpy(ret+name_len+2, msg, msg_len*sizeof(WCHAR));
}
}else {
ret = name;
name = NULL;
}
}
SysFreeString(msg);
SysFreeString(name);
if(FAILED(hres))
return hres;
if(!ret)
return E_OUTOFMEMORY;
if(retv) {
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = SysAllocString(str);
if(!V_BSTR(retv))
return E_OUTOFMEMORY;
V_BSTR(retv) = ret;
}else {
SysFreeString(ret);
}
return S_OK;
@ -264,6 +330,7 @@ static HRESULT error_constr(script_ctx_t *ctx, WORD flags, DISPPARAMS *dp,
hres = create_error(ctx, constr, NULL, msg, &err);
else
hres = create_error(ctx, constr, &num, msg, &err);
SysFreeString(msg);
if(FAILED(hres))
return hres;
@ -341,7 +408,6 @@ static HRESULT URIErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla
HRESULT init_error_constr(script_ctx_t *ctx, DispatchEx *object_prototype)
{
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};
@ -381,7 +447,7 @@ HRESULT init_error_constr(script_ctx_t *ctx, DispatchEx *object_prototype)
if(SUCCEEDED(hres))
hres = create_builtin_function(ctx, constr_val[i], names[i], NULL,
PROPF_CONSTR, &err->dispex, constr_addr[i]);
PROPF_CONSTR|1, &err->dispex, constr_addr[i]);
jsdisp_release(&err->dispex);
VariantClear(&v);
@ -424,11 +490,6 @@ static HRESULT throw_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCH
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_generic_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
{
return throw_error(ctx, ei, id, str, ctx->error_constr);

View file

@ -213,10 +213,11 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis
hres = create_exec_ctx(ctx, this_obj, var_disp, scope, &exec_ctx);
scope_release(scope);
}
jsdisp_release(var_disp);
if(FAILED(hres))
return hres;
hres = exec_source(exec_ctx, function->parser, function->source, ei, retv);
hres = exec_source(exec_ctx, function->parser, function->source, EXECT_FUNCTION, ei, retv);
exec_release(exec_ctx);
return hres;
@ -226,20 +227,27 @@ static HRESULT invoke_constructor(script_ctx_t *ctx, FunctionInstance *function,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
DispatchEx *this_obj;
VARIANT var;
HRESULT hres;
hres = create_object(ctx, &function->dispex, &this_obj);
if(FAILED(hres))
return hres;
hres = invoke_source(ctx, function, (IDispatch*)_IDispatchEx_(this_obj), dp, retv, ei, caller);
hres = invoke_source(ctx, function, (IDispatch*)_IDispatchEx_(this_obj), dp, &var, ei, caller);
if(FAILED(hres)) {
jsdisp_release(this_obj);
return hres;
}
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(this_obj);
if(V_VT(&var) == VT_DISPATCH) {
jsdisp_release(this_obj);
V_DISPATCH(retv) = V_DISPATCH(&var);
}else {
VariantClear(&var);
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(this_obj);
}
return S_OK;
}
@ -366,8 +374,10 @@ static HRESULT array_to_args(script_ctx_t *ctx, DispatchEx *arg_array, jsexcept_
return E_OUTOFMEMORY;
for(i=0; i<length; i++) {
hres = jsdisp_propget_idx(arg_array, i, argv+i, ei, caller);
if(FAILED(hres)) {
hres = jsdisp_get_idx(arg_array, i, argv+i, ei, caller);
if(hres == DISP_E_UNKNOWNNAME)
V_VT(argv+i) = VT_EMPTY;
else if(FAILED(hres)) {
while(i--)
VariantClear(argv+i);
heap_free(argv);
@ -396,9 +406,13 @@ static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI
argc = arg_cnt(dp);
if(argc) {
hres = to_object(ctx, get_arg(dp,0), &this_obj);
if(FAILED(hres))
return hres;
VARIANT *v = get_arg(dp,0);
if(V_VT(v) != VT_EMPTY && V_VT(v) != VT_NULL) {
hres = to_object(ctx, v, &this_obj);
if(FAILED(hres))
return hres;
}
}
if(argc >= 2) {
@ -406,8 +420,8 @@ static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI
if(V_VT(get_arg(dp,1)) == VT_DISPATCH) {
arg_array = iface_to_jsdisp((IUnknown*)V_DISPATCH(get_arg(dp,1)));
if(arg_array && (
!is_class(arg_array, JSCLASS_ARRAY) && !is_class(arg_array, JSCLASS_ARGUMENTS) )) {
if(arg_array &&
(!is_class(arg_array, JSCLASS_ARRAY) && !is_class(arg_array, JSCLASS_ARGUMENTS) )) {
jsdisp_release(arg_array);
arg_array = NULL;
}
@ -448,9 +462,14 @@ static HRESULT Function_call(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DIS
argc = arg_cnt(dp);
if(argc) {
hres = to_object(ctx, get_arg(dp,0), &this_obj);
if(FAILED(hres))
return hres;
VARIANT *v = get_arg(dp,0);
if(V_VT(v) != VT_EMPTY && V_VT(v) != VT_NULL) {
hres = to_object(ctx, v, &this_obj);
if(FAILED(hres))
return hres;
}
args.cArgs = argc-1;
}
@ -539,20 +558,6 @@ static const builtin_info_t Function_info = {
NULL
};
static HRESULT FunctionConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT FunctionProt_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT create_function(script_ctx_t *ctx, const builtin_info_t *builtin_info, DWORD flags,
BOOL funcprot, DispatchEx *prototype, FunctionInstance **ret)
{
@ -659,6 +664,131 @@ HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, sourc
return S_OK;
}
static HRESULT construct_function(script_ctx_t *ctx, DISPPARAMS *dp, jsexcept_t *ei, IDispatch **ret)
{
function_expression_t *expr;
WCHAR *str = NULL, *ptr;
DWORD argc, len = 0, l;
parser_ctx_t *parser;
DispatchEx *function;
BSTR *params = NULL;
int i=0, j=0;
HRESULT hres = S_OK;
static const WCHAR function_anonymousW[] = {'f','u','n','c','t','i','o','n',' ','a','n','o','n','y','m','o','u','s','('};
static const WCHAR function_beginW[] = {')',' ','{','\n'};
static const WCHAR function_endW[] = {'\n','}',0};
argc = arg_cnt(dp);
if(argc) {
params = heap_alloc(argc*sizeof(BSTR));
if(!params)
return E_OUTOFMEMORY;
if(argc > 2)
len = (argc-2)*2; /* separating commas */
for(i=0; i < argc; i++) {
hres = to_string(ctx, get_arg(dp,i), ei, params+i);
if(FAILED(hres))
break;
len += SysStringLen(params[i]);
}
}
if(SUCCEEDED(hres)) {
len += (sizeof(function_anonymousW) + sizeof(function_beginW) + sizeof(function_endW)) / sizeof(WCHAR);
str = heap_alloc(len*sizeof(WCHAR));
if(str) {
memcpy(str, function_anonymousW, sizeof(function_anonymousW));
ptr = str + sizeof(function_anonymousW)/sizeof(WCHAR);
if(argc > 1) {
while(1) {
l = SysStringLen(params[j]);
memcpy(ptr, params[j], l*sizeof(WCHAR));
ptr += l;
if(++j == argc-1)
break;
*ptr++ = ',';
*ptr++ = ' ';
}
}
memcpy(ptr, function_beginW, sizeof(function_beginW));
ptr += sizeof(function_beginW)/sizeof(WCHAR);
if(argc) {
l = SysStringLen(params[argc-1]);
memcpy(ptr, params[argc-1], l*sizeof(WCHAR));
ptr += l;
}
memcpy(ptr, function_endW, sizeof(function_endW));
TRACE("%s\n", debugstr_w(str));
}else {
hres = E_OUTOFMEMORY;
}
}
while(--i >= 0)
SysFreeString(params[i]);
heap_free(params);
if(FAILED(hres))
return hres;
hres = script_parse(ctx, str, NULL, &parser);
heap_free(str);
if(FAILED(hres))
return hres;
if(!parser->source || !parser->source->functions || parser->source->functions->next || parser->source->variables) {
ERR("Invalid parser result!\n");
parser_release(parser);
return E_UNEXPECTED;
}
expr = parser->source->functions->expr;
hres = create_source_function(parser, expr->parameter_list, expr->source_elements, NULL, expr->src_str,
expr->src_len, &function);
parser_release(parser);
if(FAILED(hres))
return hres;
*ret = (IDispatch*)_IDispatchEx_(function);
return S_OK;
}
static HRESULT FunctionConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
HRESULT hres;
TRACE("\n");
switch(flags) {
case DISPATCH_CONSTRUCT: {
IDispatch *ret;
hres = construct_function(ctx, dp, ei, &ret);
if(FAILED(hres))
return hres;
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = ret;
break;
}
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
return S_OK;
}
static HRESULT FunctionProt_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
HRESULT init_function_constr(script_ctx_t *ctx, DispatchEx *object_prototype)
{
FunctionInstance *prot, *constr;
@ -673,7 +803,7 @@ HRESULT init_function_constr(script_ctx_t *ctx, DispatchEx *object_prototype)
prot->value_proc = FunctionProt_value;
prot->name = prototypeW;
hres = create_function(ctx, NULL, PROPF_CONSTR, TRUE, &prot->dispex, &constr);
hres = create_function(ctx, NULL, PROPF_CONSTR|1, TRUE, &prot->dispex, &constr);
if(SUCCEEDED(hres)) {
constr->value_proc = FunctionConstr_value;
constr->name = FunctionW;

View file

@ -334,8 +334,10 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, D
}
ret = SysAllocStringLen(NULL, len);
if(!ret)
if(!ret) {
SysFreeString(str);
return E_OUTOFMEMORY;
}
len = 0;
for(ptr=str; *ptr; ptr++) {
@ -357,6 +359,8 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, D
}
}
SysFreeString(str);
if(retv) {
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = ret;
@ -404,7 +408,7 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DIS
return throw_syntax_error(ctx, ei, hres, NULL);
}
hres = exec_source(ctx->exec_ctx, parser_ctx, parser_ctx->source, ei, retv);
hres = exec_source(ctx->exec_ctx, parser_ctx, parser_ctx->source, EXECT_EVAL, ei, retv);
parser_release(parser_ctx);
return hres;
@ -690,8 +694,10 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
}
ret = SysAllocStringLen(NULL, len);
if(!ret)
if(!ret) {
SysFreeString(str);
return E_OUTOFMEMORY;
}
len = 0;
for(ptr=str; *ptr; ptr++) {
@ -715,6 +721,8 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
len++;
}
SysFreeString(str);
if(retv) {
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = ret;
@ -802,8 +810,8 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
}else {
i = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, NULL, 0, NULL, NULL)*3;
if(!i) {
FIXME("throw URIError\n");
return E_FAIL;
SysFreeString(str);
return throw_uri_error(ctx, ei, IDS_URI_INVALID_CHAR, NULL);
}
len += i;
@ -811,8 +819,10 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
}
rptr = ret = SysAllocStringLen(NULL, len);
if(!ret)
if(!ret) {
SysFreeString(str);
return E_OUTOFMEMORY;
}
for(ptr = str; *ptr; ptr++) {
if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') {
@ -827,6 +837,8 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
}
}
SysFreeString(str);
TRACE("%s -> %s\n", debugstr_w(str), debugstr_w(ret));
if(retv) {
V_VT(retv) = VT_BSTR;
@ -847,56 +859,239 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
BSTR str, ret;
char buf[4];
const WCHAR *ptr;
DWORD len = 0, size, i;
HRESULT hres;
TRACE("\n");
if(!arg_cnt(dp)) {
if(retv) {
ret = SysAllocString(undefinedW);
if(!ret)
return E_OUTOFMEMORY;
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = ret;
}
return S_OK;
}
hres = to_string(ctx, get_arg(dp, 0), ei, &str);
if(FAILED(hres))
return hres;
for(ptr=str; *ptr; ptr++) {
if(is_uri_unescaped(*ptr))
len++;
else {
size = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, NULL, 0, NULL, NULL);
if(!size) {
SysFreeString(str);
FIXME("throw Error\n");
return E_FAIL;
}
len += size*3;
}
}
ret = SysAllocStringLen(NULL, len);
if(!ret) {
SysFreeString(str);
return E_OUTOFMEMORY;
}
len = 0;
for(ptr=str; *ptr; ptr++) {
if(is_uri_unescaped(*ptr))
ret[len++] = *ptr;
else {
size = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, buf, sizeof(buf), NULL, NULL);
for(i=0; i<size; i++) {
ret[len++] = '%';
ret[len++] = int_to_char((BYTE)buf[i] >> 4);
ret[len++] = int_to_char(buf[i] & 0x0f);
}
}
}
SysFreeString(str);
if(retv) {
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = ret;
} else {
SysFreeString(ret);
}
return S_OK;
}
/* ECMA-262 3rd Edition 15.1.3.2 */
static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
BSTR str, ret;
const WCHAR *ptr;
WCHAR *out_ptr;
DWORD len = 0;
HRESULT hres;
TRACE("\n");
if(!arg_cnt(dp)) {
if(retv) {
ret = SysAllocString(undefinedW);
if(!ret)
return E_OUTOFMEMORY;
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = ret;
}
return S_OK;
}
hres = to_string(ctx, get_arg(dp, 0), ei, &str);
if(FAILED(hres))
return hres;
ptr = str;
while(*ptr) {
if(*ptr == '%') {
char octets[4];
unsigned char mask = 0x80;
int i, size, num_bytes = 0;
if(hex_to_int(*(ptr+1)) < 0 || hex_to_int(*(ptr+2)) < 0) {
FIXME("Throw URIError: Invalid hex sequence\n");
SysFreeString(str);
return E_FAIL;
}
octets[0] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
ptr += 3;
while(octets[0] & mask) {
mask = mask >> 1;
++num_bytes;
}
if(num_bytes == 1 || num_bytes > 4) {
FIXME("Throw URIError: Invalid initial UTF character\n");
SysFreeString(str);
return E_FAIL;
}
for(i = 1; i < num_bytes; ++i) {
if(*ptr != '%'){
FIXME("Throw URIError: Incomplete UTF sequence\n");
SysFreeString(str);
return E_FAIL;
}
if(hex_to_int(*(ptr+1)) < 0 || hex_to_int(*(ptr+2)) < 0) {
FIXME("Throw URIError: Invalid hex sequence\n");
SysFreeString(str);
return E_FAIL;
}
octets[i] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
ptr += 3;
}
size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, octets,
num_bytes ? num_bytes : 1, NULL, 0);
if(size == 0) {
FIXME("Throw URIError: Invalid UTF sequence\n");
SysFreeString(str);
return E_FAIL;
}
len += size;
}else {
++ptr;
++len;
}
}
out_ptr = ret = SysAllocStringLen(NULL, len);
if(!ret) {
SysFreeString(str);
return E_OUTOFMEMORY;
}
ptr = str;
while(*ptr) {
if(*ptr == '%') {
char octets[4];
unsigned char mask = 0x80;
int i, size, num_bytes = 0;
octets[0] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
ptr += 3;
while(octets[0] & mask) {
mask = mask >> 1;
++num_bytes;
}
for(i = 1; i < num_bytes; ++i) {
octets[i] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
ptr += 3;
}
size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, octets,
num_bytes ? num_bytes : 1, out_ptr, len);
len -= size;
out_ptr += size;
}else {
*out_ptr++ = *ptr++;
--len;
}
}
SysFreeString(str);
if(retv) {
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = ret;
}else {
SysFreeString(ret);
}
return S_OK;
}
static const builtin_prop_t JSGlobal_props[] = {
{ActiveXObjectW, JSGlobal_ActiveXObject, PROPF_CONSTR},
{ArrayW, JSGlobal_Array, PROPF_CONSTR},
{BooleanW, JSGlobal_Boolean, PROPF_CONSTR},
{ActiveXObjectW, JSGlobal_ActiveXObject, PROPF_CONSTR|1},
{ArrayW, JSGlobal_Array, PROPF_CONSTR|1},
{BooleanW, JSGlobal_Boolean, PROPF_CONSTR|1},
{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},
{DateW, JSGlobal_Date, PROPF_CONSTR|7},
{EnumeratorW, JSGlobal_Enumerator, PROPF_METHOD|7},
{ErrorW, JSGlobal_Error, PROPF_CONSTR|1},
{EvalErrorW, JSGlobal_EvalError, PROPF_CONSTR|1},
{FunctionW, JSGlobal_Function, PROPF_CONSTR|1},
{_GetObjectW, JSGlobal_GetObject, PROPF_METHOD|2},
{InfinityW, JSGlobal_Infinity, 0},
/* {MathW, JSGlobal_Math, 0}, */
{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},
{NumberW, JSGlobal_Number, PROPF_CONSTR|1},
{ObjectW, JSGlobal_Object, PROPF_CONSTR|1},
{RangeErrorW, JSGlobal_RangeError, PROPF_CONSTR|1},
{ReferenceErrorW, JSGlobal_ReferenceError, PROPF_CONSTR|1},
{RegExpW, JSGlobal_RegExp, PROPF_CONSTR|2},
{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},
{decodeURIW, JSGlobal_decodeURI, PROPF_METHOD},
{decodeURIComponentW, JSGlobal_decodeURIComponent, PROPF_METHOD},
{encodeURIW, JSGlobal_encodeURI, PROPF_METHOD},
{encodeURIComponentW, JSGlobal_encodeURIComponent, PROPF_METHOD},
{escapeW, JSGlobal_escape, PROPF_METHOD},
{StringW, JSGlobal_String, PROPF_CONSTR|1},
{SyntaxErrorW, JSGlobal_SyntaxError, PROPF_CONSTR|1},
{TypeErrorW, JSGlobal_TypeError, PROPF_CONSTR|1},
{URIErrorW, JSGlobal_URIError, PROPF_CONSTR|1},
{VBArrayW, JSGlobal_VBArray, PROPF_METHOD|1},
{decodeURIW, JSGlobal_decodeURI, PROPF_METHOD|1},
{decodeURIComponentW, JSGlobal_decodeURIComponent, PROPF_METHOD|1},
{encodeURIW, JSGlobal_encodeURI, PROPF_METHOD|1},
{encodeURIComponentW, JSGlobal_encodeURIComponent, PROPF_METHOD|1},
{escapeW, JSGlobal_escape, PROPF_METHOD|1},
{evalW, JSGlobal_eval, PROPF_METHOD|1},
{isFiniteW, JSGlobal_isFinite, PROPF_METHOD},
{isNaNW, JSGlobal_isNaN, PROPF_METHOD},
{parseFloatW, JSGlobal_parseFloat, PROPF_METHOD},
{isFiniteW, JSGlobal_isFinite, PROPF_METHOD|1},
{isNaNW, JSGlobal_isNaN, PROPF_METHOD|1},
{parseFloatW, JSGlobal_parseFloat, PROPF_METHOD|1},
{parseIntW, JSGlobal_parseInt, PROPF_METHOD|2},
{unescapeW, JSGlobal_unescape, PROPF_METHOD}
{unescapeW, JSGlobal_unescape, PROPF_METHOD|1}
};
static const builtin_info_t JSGlobal_info = {
@ -981,6 +1176,11 @@ HRESULT init_global(script_ctx_t *ctx)
if(FAILED(hres))
return hres;
V_VT(&var) = VT_EMPTY;
hres = jsdisp_propput_name(ctx->global, undefinedW, &var, NULL/*FIXME*/, NULL/*FIXME*/);
if(FAILED(hres))
return hres;
V_VT(&var) = VT_DISPATCH;
V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(math);
hres = jsdisp_propput_name(ctx->global, MathW, &var, NULL/*FIXME*/, NULL/*FIXME*/);

View file

@ -51,6 +51,7 @@ typedef struct {
script_ctx_t *ctx;
LONG thread_id;
LCID lcid;
DWORD version;
IActiveScriptSite *site;
@ -93,7 +94,6 @@ static HRESULT exec_global_code(JScript *This, parser_ctx_t *parser_ctx)
{
exec_ctx_t *exec_ctx;
jsexcept_t jsexcept;
VARIANT var;
HRESULT hres;
hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, &exec_ctx);
@ -103,14 +103,11 @@ static HRESULT exec_global_code(JScript *This, parser_ctx_t *parser_ctx)
IActiveScriptSite_OnEnterScript(This->site);
memset(&jsexcept, 0, sizeof(jsexcept));
hres = exec_source(exec_ctx, parser_ctx, parser_ctx->source, &jsexcept, &var);
hres = exec_source(exec_ctx, parser_ctx, parser_ctx->source, EXECT_PROGRAM, &jsexcept, NULL);
VariantClear(&jsexcept.var);
exec_release(exec_ctx);
if(SUCCEEDED(hres))
VariantClear(&var);
IActiveScriptSite_OnLeaveScript(This->site);
return hres;
}
@ -659,6 +656,7 @@ static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
ctx->ref = 1;
ctx->state = SCRIPTSTATE_UNINITIALIZED;
ctx->safeopt = This->safeopt;
ctx->version = This->version;
jsheap_init(&ctx->tmp_heap);
ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL);
@ -822,8 +820,27 @@ static HRESULT WINAPI JScriptProperty_SetProperty(IActiveScriptProperty *iface,
VARIANT *pvarIndex, VARIANT *pvarValue)
{
JScript *This = ACTSCPPROP_THIS(iface);
FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
return E_NOTIMPL;
TRACE("(%p)->(%x %s %s)\n", This, dwProperty, debugstr_variant(pvarIndex), debugstr_variant(pvarValue));
if(pvarIndex)
FIXME("unsupported pvarIndex\n");
switch(dwProperty) {
case SCRIPTPROP_INVOKEVERSIONING:
if(V_VT(pvarValue) != VT_I4 || V_I4(pvarValue) < 0 || V_I4(pvarValue) > 15) {
WARN("invalid value %s\n", debugstr_variant(pvarValue));
return E_INVALIDARG;
}
This->version = V_I4(pvarValue);
break;
default:
FIXME("Unimplemented property %x\n", dwProperty);
return E_NOTIMPL;
}
return S_OK;
}
#undef ACTSCPPROP_THIS

View file

@ -205,7 +205,7 @@ HRESULT jsdisp_propget(DispatchEx*,DISPID,VARIANT*,jsexcept_t*,IServiceProvider*
HRESULT jsdisp_propput_name(DispatchEx*,const WCHAR*,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_propput_idx(DispatchEx*,DWORD,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_propget_name(DispatchEx*,LPCWSTR,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_propget_idx(DispatchEx*,DWORD,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_get_idx(DispatchEx*,DWORD,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_get_id(DispatchEx*,const WCHAR*,DWORD,DISPID*);
HRESULT jsdisp_delete_idx(DispatchEx*,DWORD);
@ -225,7 +225,8 @@ 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**);
HRESULT create_array(script_ctx_t*,DWORD,DispatchEx**);
HRESULT create_regexp_str(script_ctx_t*,const WCHAR*,DWORD,const WCHAR*,DWORD,DispatchEx**);
HRESULT create_regexp(script_ctx_t*,const WCHAR *,int,DWORD,DispatchEx**);
HRESULT create_regexp_var(script_ctx_t*,VARIANT*,VARIANT*,DispatchEx**);
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**);
@ -262,6 +263,7 @@ struct _script_ctx_t {
IActiveScriptSite *site;
IInternetHostSecurityManager *secmgr;
DWORD safeopt;
DWORD version;
LCID lcid;
jsheap_t tmp_heap;
@ -316,9 +318,12 @@ typedef struct {
DWORD len;
} match_result_t;
HRESULT regexp_match_next(script_ctx_t*,DispatchEx*,BOOL,const WCHAR*,DWORD,const WCHAR**,match_result_t**,
#define REM_CHECK_GLOBAL 0x0001
#define REM_RESET_INDEX 0x0002
HRESULT regexp_match_next(script_ctx_t*,DispatchEx*,DWORD,const WCHAR*,DWORD,const WCHAR**,match_result_t**,
DWORD*,DWORD*,match_result_t*);
HRESULT regexp_match(script_ctx_t*,DispatchEx*,const WCHAR*,DWORD,BOOL,match_result_t**,DWORD*);
HRESULT parse_regexp_flags(const WCHAR*,DWORD,DWORD*);
static inline VARIANT *get_arg(DISPPARAMS *dp, DWORD i)
{
@ -390,6 +395,11 @@ static inline void num_set_inf(VARIANT *v, BOOL positive)
#endif
}
static inline DWORD make_grfdex(script_ctx_t *ctx, DWORD flags)
{
return (ctx->version << 28) | flags;
}
const char *debugstr_variant(const VARIANT*);
HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**);

View file

@ -12,27 +12,27 @@ DelReg=Classes.Reg
[Classes.Reg]
HKCR,"CLSID\%CLSID_JScript%",,,"JScript Language"
HKCR,"CLSID\%CLSID_JScript%\Implemented Categories\%CATID_ActiveScript%",,,
HKCR,"CLSID\%CLSID_JScript%\Implemented Categories\%CATID_ActiveScriptParse%",,,
HKCR,"CLSID\%CLSID_JScript%\Implemented Categories\%CATID_ActiveScript%",,16
HKCR,"CLSID\%CLSID_JScript%\Implemented Categories\%CATID_ActiveScriptParse%",,16
HKCR,"CLSID\%CLSID_JScript%\InprocServer32",,,"%MODULE%"
HKCR,"CLSID\%CLSID_JScript%\InprocServer32","ThreadingModel",,"Both"
HKCR,"CLSID\%CLSID_JScript%\OLEScript",,,
HKCR,"CLSID\%CLSID_JScript%\OLEScript",,16
HKCR,"CLSID\%CLSID_JScript%\ProgID",,,"JScript"
HKCR,"CLSID\%CLSID_JScriptAuthor%",,,"JScript Language Authoring"
HKCR,"CLSID\%CLSID_JScriptAuthor%\Implemented Categories\%CATID_ActiveScriptAuthor%",,,
HKCR,"CLSID\%CLSID_JScriptAuthor%\Implemented Categories\%CATID_ActiveScriptAuthor%",,16
HKCR,"CLSID\%CLSID_JScriptAuthor%\InprocServer32",,,"%MODULE%"
HKCR,"CLSID\%CLSID_JScriptAuthor%\InprocServer32","ThreadingModel",,"Both"
HKCR,"CLSID\%CLSID_JScriptAuthor%\OLEScript",,,
HKCR,"CLSID\%CLSID_JScriptAuthor%\OLEScript",,16
HKCR,"CLSID\%CLSID_JScriptAuthor%\ProgID",,,"JScript Author"
HKCR,"CLSID\%CLSID_JScriptEncode%",,,"JScript Language Encoding"
HKCR,"CLSID\%CLSID_JScriptEncode%\Implemented Categories\%CATID_ActiveScript%",,,
HKCR,"CLSID\%CLSID_JScriptEncode%\Implemented Categories\%CATID_ActiveScriptParse%",,,
HKCR,"CLSID\%CLSID_JScriptEncode%\Implemented Categories\%CATID_ActiveScriptEncode%",,,
HKCR,"CLSID\%CLSID_JScriptEncode%\Implemented Categories\%CATID_ActiveScript%",,16
HKCR,"CLSID\%CLSID_JScriptEncode%\Implemented Categories\%CATID_ActiveScriptParse%",,16
HKCR,"CLSID\%CLSID_JScriptEncode%\Implemented Categories\%CATID_ActiveScriptEncode%",,16
HKCR,"CLSID\%CLSID_JScriptEncode%\InprocServer32",,,"%MODULE%"
HKCR,"CLSID\%CLSID_JScriptEncode%\InprocServer32","ThreadingModel",,"Both"
HKCR,"CLSID\%CLSID_JScriptEncode%\OLEScript",,,
HKCR,"CLSID\%CLSID_JScriptEncode%\OLEScript",,16
HKCR,"CLSID\%CLSID_JScriptEncode%\ProgID",,,"JScript.Encode"
HKCR,"Component Categories\%CATID_ActiveScriptAuthor%","409",,"Active Scripting Engine with Authoring"
@ -42,55 +42,55 @@ HKCR,"Component Categories\%CATID_ActiveScriptEncode%","409",,"Active Scripting
HKCR,"ECMAScript",,,"JScript Language"
HKCR,"ECMAScript\CLSID",,,"%CLSID_JScript%"
HKCR,"ECMAScript\OLEScript",,,
HKCR,"ECMAScript\OLEScript",,16
HKCR,"JavaScript",,,"JScript Language"
HKCR,"JavaScript\CLSID",,,"%CLSID_JScript%"
HKCR,"JavaScript\OLEScript",,,
HKCR,"JavaScript\OLEScript",,16
HKCR,"JavaScript Author",,,"JScript Language Authoring"
HKCR,"JavaScript Author\CLSID",,,"%CLSID_JScriptAuthor%"
HKCR,"JavaScript Author\OLEScript",,,
HKCR,"JavaScript Author\OLEScript",,16
HKCR,"JavaScript1.1",,,"JScript Language"
HKCR,"JavaScript1.1\CLSID",,,"%CLSID_JScript%"
HKCR,"JavaScript1.1\OLEScript",,,
HKCR,"JavaScript1.1\OLEScript",,16
HKCR,"JavaScript1.1 Author",,,"JScript Language Authoring"
HKCR,"JavaScript1.1 Author\CLSID",,,"%CLSID_JScriptAuthor%"
HKCR,"JavaScript1.1 Author\OLEScript",,,
HKCR,"JavaScript1.1 Author\OLEScript",,16
HKCR,"JavaScript1.2",,,"JScript Language"
HKCR,"JavaScript1.2\CLSID",,,"%CLSID_JScript%"
HKCR,"JavaScript1.2\OLEScript",,,
HKCR,"JavaScript1.2\OLEScript",,16
HKCR,"JavaScript1.2 Author",,,"JScript Language Authoring"
HKCR,"JavaScript1.2 Author\CLSID",,,"%CLSID_JScriptAuthor%"
HKCR,"JavaScript1.2 Author\OLEScript",,,
HKCR,"JavaScript1.2 Author\OLEScript",,16
HKCR,"JavaScript1.3",,,"JScript Language"
HKCR,"JavaScript1.3\CLSID",,,"%CLSID_JScript%"
HKCR,"JavaScript1.3\OLEScript",,,
HKCR,"JavaScript1.3\OLEScript",,16
HKCR,"JScript",,,"JScript Language"
HKCR,"JScript\CLSID",,,"%CLSID_JScript%"
HKCR,"JScript\OLEScript",,,
HKCR,"JScript\OLEScript",,16
HKCR,"JScript Author",,,"JScript Language Authoring"
HKCR,"JScript Author\CLSID",,,"%CLSID_JScriptAuthor%"
HKCR,"JScript Author\OLEScript",,,
HKCR,"JScript Author\OLEScript",,16
HKCR,"JScript.Encode",,,"JScript Language Encoding"
HKCR,"JScript.Encode\CLSID",,,"%CLSID_JScriptEncode%"
HKCR,"JScript.Encode\OLEScript",,,
HKCR,"JScript.Encode\OLEScript",,16
HKCR,"LiveScript",,,"JScript Language"
HKCR,"LiveScript\CLSID",,,"%CLSID_JScript%"
HKCR,"LiveScript\OLEScript",,,
HKCR,"LiveScript\OLEScript",,16
HKCR,"LiveScript Author",,,"JScript Language Authoring"
HKCR,"LiveScript Author\CLSID",,,"%CLSID_JScriptAuthor%"
HKCR,"LiveScript Author\OLEScript",,,
HKCR,"LiveScript Author\OLEScript",,16
[Strings]

View file

@ -43,6 +43,7 @@ STRINGTABLE DISCARDABLE
IDS_NOT_BOOL "Boolisches Objekt erwartet"
IDS_JSCRIPT_EXPECTED "JScript Objekt erwartet"
IDS_REGEXP_SYNTAX_ERROR "Syntax Fehler in regulärem Ausdruck"
IDS_URI_INVALID_CHAR "Zu verschlüsselnde URI enthält ungültige Zeichen"
IDS_INVALID_LENGTH "Array-Größe muss eine endliche, positive Ganzzahl sein"
IDS_ARRAY_EXPECTED "Array Objekt erwartet"
}

View file

@ -41,6 +41,7 @@ STRINGTABLE DISCARDABLE
IDS_NOT_BOOL "Boolean object expected"
IDS_JSCRIPT_EXPECTED "JScript object expected"
IDS_REGEXP_SYNTAX_ERROR "Syntax error in regular expression"
IDS_URI_INVALID_CHAR "URI to be encoded contains invalid characters"
IDS_INVALID_LENGTH "Array length must be a finite positive integer"
IDS_ARRAY_EXPECTED "Array object expected"
}

View file

@ -46,6 +46,7 @@ STRINGTABLE DISCARDABLE
IDS_NOT_BOOL "Objet booléen attendu"
IDS_JSCRIPT_EXPECTED "Objet JScript attendu"
IDS_REGEXP_SYNTAX_ERROR "Erreur de syntaxe dans l'expression rationnelle"
IDS_URI_INVALID_CHAR "L'URI à coder contient des caractères invalides"
IDS_INVALID_LENGTH "La longueur d'un tableau doit être un entier positif"
IDS_ARRAY_EXPECTED "Objet tableau attendu"
}

View file

@ -0,0 +1,51 @@
/*
* Copyright 2009 Piotr Caban
* Copyright 2010 YunSong Hwang
*
* 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_KOREAN, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
IDS_TO_PRIMITIVE "객페를 기본 형식으로 변환하는 중에 에러 발생"
IDS_INVALID_CALL_ARG "올바르지 않은 프로시져 호출이나 인수"
IDS_CREATE_OBJ_ERROR "자동화 서버가 객체를 만들 수 없습니다"
IDS_NO_PROPERTY "객체는 이 속성이나 메소드를 지원하지 않습니다"
IDS_ARG_NOT_OPT "인수는 옵션이 아닙니다"
IDS_SYNTAX_ERROR "문법 에러"
IDS_SEMICOLON "';' 가 필요합니다"
IDS_LBRACKET "'(' 가 필요합니다"
IDS_RBRACKET "')' 가 필요합니다"
IDS_UNTERMINATED_STR "띁나지 않은 문자열 상수"
IDS_NOT_FUNC "함수가 필요합니다"
IDS_NOT_DATE "'[객체]' 는 날짜 객체가 아닙니다"
IDS_NOT_NUM "숫자가 필요합니다"
IDS_OBJECT_EXPECTED "객체가 필요합니다"
IDS_ILLEGAL_ASSIGN "잘못된 할당"
IDS_UNDEFINED "'|' 는 정의되지 않았습니다"
IDS_NOT_BOOL "볼린 객제가 필요합니다"
IDS_JSCRIPT_EXPECTED "JScript 객체가 필요합니다"
IDS_REGEXP_SYNTAX_ERROR "정규 표현식에 문법에러가 있습니다"
IDS_URI_INVALID_CHAR "URI 는 올바르지 않은 문자를 포함해서 인코딩되었습니다"
IDS_INVALID_LENGTH "배열 길이는 반드시 한정된 양의 정수이어야 합니다"
IDS_ARRAY_EXPECTED "배열 객체가 필요합니다"
}

View file

@ -44,6 +44,7 @@ STRINGTABLE DISCARDABLE
IDS_NOT_BOOL "Tikėtasi loginio objekto"
IDS_JSCRIPT_EXPECTED "Tikėtasi JScript objekto"
IDS_REGEXP_SYNTAX_ERROR "Sintaksės klaida reguliariajame reiškinyje"
IDS_URI_INVALID_CHAR "Koduotiname URI yra netinkamų simbolių"
IDS_INVALID_LENGTH "Masyvo dydis turi būti teigiamas sveikasis skaičius"
IDS_ARRAY_EXPECTED "Tikėtasi masyvo objekto"
}

View file

@ -0,0 +1,50 @@
/*
* Copyright 2009 Vladimir Pankratov
*
* 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_RUSSIAN, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
IDS_TO_PRIMITIVE "Ошибка конвертирования объекта в примитивный тип"
IDS_INVALID_CALL_ARG "Неверный вызов процедуры или аргумент"
IDS_CREATE_OBJ_ERROR "Сервер автоматизации не может создать объект"
IDS_NO_PROPERTY "Объект не поддерживает это свойство или метод"
IDS_ARG_NOT_OPT "Отсутствует обязательный аргумент"
IDS_SYNTAX_ERROR "Синтаксическая ошибка"
IDS_SEMICOLON "Ожидается ';'"
IDS_LBRACKET "Ожидается '('"
IDS_RBRACKET "Ожидается ')'"
IDS_UNTERMINATED_STR "Незавершённая строковая константа"
IDS_NOT_FUNC "Ожидается функция"
IDS_NOT_DATE "'[object]' не объект типа 'date'"
IDS_NOT_NUM "Ожидается число"
IDS_OBJECT_EXPECTED "Ожидается объект"
IDS_ILLEGAL_ASSIGN "Неверное присваивание"
IDS_UNDEFINED "'|' не определён"
IDS_NOT_BOOL "Ожидается объект типа 'bool'"
IDS_JSCRIPT_EXPECTED "Ожидается объект типа 'JScript'"
IDS_REGEXP_SYNTAX_ERROR "Синтаксическая ошибка в регулярном выражении"
IDS_URI_INVALID_CHAR "URI содержит неверные символы"
IDS_INVALID_LENGTH "Длиной массива должно быть конечное положительное число"
IDS_ARRAY_EXPECTED "Ожидается объект типа 'Array'"
}

View file

@ -449,10 +449,14 @@ HRESULT to_integer(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
if(FAILED(hres))
return hres;
if(V_VT(&num) == VT_I4)
if(V_VT(&num) == VT_I4) {
*ret = num;
else
}else if(isnan(V_R8(&num))) {
V_VT(ret) = VT_I4;
V_I4(ret) = 0;
}else {
num_set_val(ret, V_R8(&num) >= 0.0 ? floor(V_R8(&num)) : -floor(-V_R8(&num)));
}
return S_OK;
}
@ -467,7 +471,10 @@ HRESULT to_int32(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, INT *ret)
if(FAILED(hres))
return hres;
*ret = V_VT(&num) == VT_I4 ? V_I4(&num) : (INT)V_R8(&num);
if(V_VT(&num) == VT_I4)
*ret = V_I4(&num);
else
*ret = isnan(V_R8(&num)) || isinf(V_R8(&num)) ? 0 : (INT)V_R8(&num);
return S_OK;
}
@ -481,7 +488,10 @@ HRESULT to_uint32(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, DWORD *ret)
if(FAILED(hres))
return hres;
*ret = V_VT(&num) == VT_I4 ? V_I4(&num) : (DWORD)V_R8(&num);
if(V_VT(&num) == VT_I4)
*ret = V_I4(&num);
else
*ret = isnan(V_R8(&num)) || isinf(V_R8(&num)) ? 0 : (DWORD)V_R8(&num);
return S_OK;
}

View file

@ -91,7 +91,6 @@ static const struct {
{trueW, kTRUE},
{tryW, kTRY},
{typeofW, kTYPEOF},
{undefinedW, kUNDEFINED},
{varW, kVAR},
{voidW, kVOID},
{whileW, kWHILE},
@ -369,7 +368,7 @@ static literal_t *alloc_int_literal(parser_ctx_t *ctx, LONG l)
{
literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
ret->vt = VT_I4;
ret->type = LT_INT;
ret->u.lval = l;
return ret;
@ -447,7 +446,7 @@ static int parse_double_literal(parser_ctx_t *ctx, LONG int_part, literal_t **li
}
*literal = parser_alloc(ctx, sizeof(literal_t));
(*literal)->vt = VT_R8;
(*literal)->type = LT_DOUBLE;
(*literal)->u.dval = (double)d*pow(10, exp);
return tNumericLiteral;
@ -755,21 +754,11 @@ int parser_lex(void *lval, parser_ctx_t *ctx)
return 0;
}
static void add_object_literal(parser_ctx_t *ctx, DispatchEx *obj)
{
obj_literal_t *literal = parser_alloc(ctx, sizeof(obj_literal_t));
literal->obj = obj;
literal->next = ctx->obj_literals;
ctx->obj_literals = literal;
}
literal_t *parse_regexp(parser_ctx_t *ctx)
{
const WCHAR *re, *flags;
DispatchEx *regexp;
const WCHAR *re, *flags_ptr;
DWORD re_len, flags;
literal_t *ret;
DWORD re_len;
HRESULT hres;
TRACE("\n");
@ -790,18 +779,18 @@ literal_t *parse_regexp(parser_ctx_t *ctx)
re_len = ctx->ptr-re;
flags = ++ctx->ptr;
flags_ptr = ++ctx->ptr;
while(ctx->ptr < ctx->end && isalnumW(*ctx->ptr))
ctx->ptr++;
hres = create_regexp_str(ctx->script, re, re_len, flags, ctx->ptr-flags, &regexp);
hres = parse_regexp_flags(flags_ptr, ctx->ptr-flags_ptr, &flags);
if(FAILED(hres))
return NULL;
add_object_literal(ctx, regexp);
ret = parser_alloc(ctx, sizeof(literal_t));
ret->vt = VT_DISPATCH;
ret->u.disp = (IDispatch*)_IDispatchEx_(regexp);
ret->type = LT_REGEXP;
ret->u.regexp.str = re;
ret->u.regexp.str_len = re_len;
ret->u.regexp.flags = flags;
return ret;
}

View file

@ -346,7 +346,8 @@ HRESULT create_number_constr(script_ctx_t *ctx, DispatchEx *object_prototype, Di
return hres;
V_VT(&number->num) = VT_I4;
hres = create_builtin_function(ctx, NumberConstr_value, NumberW, NULL, PROPF_CONSTR, &number->dispex, ret);
hres = create_builtin_function(ctx, NumberConstr_value, NumberW, NULL,
PROPF_CONSTR|1, &number->dispex, ret);
jsdisp_release(&number->dispex);
return hres;

File diff suppressed because it is too large Load diff

View file

@ -54,34 +54,33 @@
kINSTANCEOF = 270,
kNEW = 271,
kNULL = 272,
kUNDEFINED = 273,
kRETURN = 274,
kSWITCH = 275,
kTHIS = 276,
kTHROW = 277,
kTRUE = 278,
kFALSE = 279,
kTRY = 280,
kTYPEOF = 281,
kVAR = 282,
kVOID = 283,
kWHILE = 284,
kWITH = 285,
tANDAND = 286,
tOROR = 287,
tINC = 288,
tDEC = 289,
tHTMLCOMMENT = 290,
kDIVEQ = 291,
kFUNCTION = 292,
tIdentifier = 293,
tAssignOper = 294,
tEqOper = 295,
tShiftOper = 296,
tRelOper = 297,
tNumericLiteral = 298,
tStringLiteral = 299,
LOWER_THAN_ELSE = 300
kRETURN = 273,
kSWITCH = 274,
kTHIS = 275,
kTHROW = 276,
kTRUE = 277,
kFALSE = 278,
kTRY = 279,
kTYPEOF = 280,
kVAR = 281,
kVOID = 282,
kWHILE = 283,
kWITH = 284,
tANDAND = 285,
tOROR = 286,
tINC = 287,
tDEC = 288,
tHTMLCOMMENT = 289,
kDIVEQ = 290,
kFUNCTION = 291,
tIdentifier = 292,
tAssignOper = 293,
tEqOper = 294,
tShiftOper = 295,
tRelOper = 296,
tNumericLiteral = 297,
tStringLiteral = 298,
LOWER_THAN_ELSE = 299
};
#endif
@ -92,7 +91,7 @@ typedef union YYSTYPE
{
/* Line 1676 of yacc.c */
#line 151 "parser.y"
#line 150 "parser.y"
int ival;
const WCHAR *srcptr;
@ -116,7 +115,7 @@ typedef union YYSTYPE
/* Line 1676 of yacc.c */
#line 120 "parser.tab.h"
#line 119 "parser.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */

View file

@ -38,7 +38,6 @@ typedef struct _statement_list_t {
static literal_t *new_string_literal(parser_ctx_t*,const WCHAR*);
static literal_t *new_null_literal(parser_ctx_t*);
static literal_t *new_undefined_literal(parser_ctx_t*);
static literal_t *new_boolean_literal(parser_ctx_t*,VARIANT_BOOL);
typedef struct _property_list_t {
@ -171,7 +170,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state
/* keywords */
%token kBREAK kCASE kCATCH kCONTINUE kDEFAULT kDELETE kDO kELSE kIF kFINALLY kFOR kIN
%token kINSTANCEOF kNEW kNULL kUNDEFINED kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE kTRY kTYPEOF kVAR kVOID kWHILE kWITH
%token kINSTANCEOF kNEW kNULL kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE kTRY kTYPEOF kVAR kVOID kWHILE kWITH
%token tANDAND tOROR tINC tDEC tHTMLCOMMENT kDIVEQ
%token <srcptr> kFUNCTION '}'
@ -800,7 +799,6 @@ Identifier_opt
/* ECMA-262 3rd Edition 7.8 */
Literal
: kNULL { $$ = new_null_literal(ctx); }
| kUNDEFINED { $$ = new_undefined_literal(ctx); }
| BooleanLiteral { $$ = $1; }
| tNumericLiteral { $$ = $1; }
| tStringLiteral { $$ = new_string_literal(ctx, $1); }
@ -841,7 +839,7 @@ static literal_t *new_string_literal(parser_ctx_t *ctx, const WCHAR *str)
{
literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
ret->vt = VT_BSTR;
ret->type = LT_STRING;
ret->u.wstr = str;
return ret;
@ -851,16 +849,7 @@ static literal_t *new_null_literal(parser_ctx_t *ctx)
{
literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
ret->vt = VT_NULL;
return ret;
}
static literal_t *new_undefined_literal(parser_ctx_t *ctx)
{
literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
ret->vt = VT_EMPTY;
ret->type = LT_NULL;
return ret;
}
@ -869,7 +858,7 @@ static literal_t *new_boolean_literal(parser_ctx_t *ctx, VARIANT_BOOL bval)
{
literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
ret->vt = VT_BOOL;
ret->type = LT_BOOL;
ret->u.bval = bval;
return ret;
@ -1591,14 +1580,11 @@ static void program_parsed(parser_ctx_t *ctx, source_elements_t *source)
void parser_release(parser_ctx_t *ctx)
{
obj_literal_t *iter;
if(--ctx->ref)
return;
for(iter = ctx->obj_literals; iter; iter = iter->next)
jsdisp_release(iter->obj);
script_release(ctx->script);
heap_free(ctx->begin);
jsheap_free(&ctx->heap);
heap_free(ctx);
}
@ -1620,8 +1606,14 @@ HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimite
parser_ctx->hres = JSCRIPT_ERROR|IDS_SYNTAX_ERROR;
parser_ctx->is_html = delimiter && !strcmpiW(delimiter, html_tagW);
parser_ctx->begin = parser_ctx->ptr = code;
parser_ctx->end = code + strlenW(code);
parser_ctx->begin = heap_strdupW(code);
if(!parser_ctx->begin) {
heap_free(parser_ctx);
return E_OUTOFMEMORY;
}
parser_ctx->ptr = parser_ctx->begin;
parser_ctx->end = parser_ctx->begin + strlenW(parser_ctx->begin);
script_addref(ctx);
parser_ctx->script = ctx;

View file

@ -32,6 +32,7 @@
*/
#include <assert.h>
#include <math.h>
#include "jscript.h"
@ -82,7 +83,8 @@ typedef struct {
JSRegExp *jsregexp;
BSTR str;
DWORD last_index;
INT last_index;
VARIANT last_index_var;
} RegExpInstance;
static const WCHAR sourceW[] = {'s','o','u','r','c','e',0};
@ -3299,8 +3301,16 @@ static inline RegExpInstance *regexp_from_vdisp(vdisp_t *vdisp)
return (RegExpInstance*)vdisp->u.jsdisp;
}
static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, const WCHAR *str, DWORD len,
const WCHAR **cp, match_result_t **parens, DWORD *parens_size, DWORD *parens_cnt, match_result_t *ret)
static void set_last_index(RegExpInstance *This, DWORD last_index)
{
This->last_index = last_index;
VariantClear(&This->last_index_var);
num_set_val(&This->last_index_var, last_index);
}
static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, DWORD rem_flags,
const WCHAR *str, DWORD len, const WCHAR **cp, match_result_t **parens, DWORD *parens_size,
DWORD *parens_cnt, match_result_t *ret)
{
REMatchState *x, *result;
REGlobalData gData;
@ -3325,8 +3335,11 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, c
return E_FAIL;
}
if(!result)
if(!result) {
if(rem_flags & REM_RESET_INDEX)
set_last_index(regexp, 0);
return S_FALSE;
}
if(parens) {
DWORD i;
@ -3347,8 +3360,13 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, c
*parens_cnt = regexp->jsregexp->parenCount;
for(i=0; i < regexp->jsregexp->parenCount; i++) {
(*parens)[i].str = *cp + result->parens[i].index;
(*parens)[i].len = result->parens[i].length;
if(result->parens[i].index == -1) {
(*parens)[i].str = NULL;
(*parens)[i].len = 0;
}else {
(*parens)[i].str = *cp + result->parens[i].index;
(*parens)[i].len = result->parens[i].length;
}
}
}
@ -3356,23 +3374,25 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, c
*cp = result->cp;
ret->str = result->cp-matchlen;
ret->len = matchlen;
set_last_index(regexp, result->cp-str);
return S_OK;
}
HRESULT regexp_match_next(script_ctx_t *ctx, DispatchEx *dispex, BOOL gcheck, const WCHAR *str, DWORD len,
const WCHAR **cp, match_result_t **parens, DWORD *parens_size, DWORD *parens_cnt, match_result_t *ret)
HRESULT regexp_match_next(script_ctx_t *ctx, DispatchEx *dispex, DWORD rem_flags, const WCHAR *str,
DWORD len, const WCHAR **cp, match_result_t **parens, DWORD *parens_size, DWORD *parens_cnt,
match_result_t *ret)
{
RegExpInstance *regexp = (RegExpInstance*)dispex;
jsheap_t *mark;
HRESULT hres;
if(gcheck && !(regexp->jsregexp->flags & JSREG_GLOB))
if((rem_flags & REM_CHECK_GLOBAL) && !(regexp->jsregexp->flags & JSREG_GLOB))
return S_FALSE;
mark = jsheap_mark(&ctx->tmp_heap);
hres = do_regexp_match_next(ctx, regexp, str, len, cp, parens, parens_size, parens_cnt, ret);
hres = do_regexp_match_next(ctx, regexp, rem_flags, str, len, cp, parens, parens_size, parens_cnt, ret);
jsheap_clear(mark);
return hres;
@ -3391,7 +3411,7 @@ HRESULT regexp_match(script_ctx_t *ctx, DispatchEx *dispex, const WCHAR *str, DW
mark = jsheap_mark(&ctx->tmp_heap);
while(1) {
hres = do_regexp_match_next(ctx, This, str, len, &cp, NULL, NULL, NULL, &cres);
hres = do_regexp_match_next(ctx, This, 0, str, len, &cp, NULL, NULL, NULL, &cres);
if(hres == S_FALSE) {
hres = S_OK;
break;
@ -3474,6 +3494,27 @@ static HRESULT RegExp_multiline(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
return E_NOTIMPL;
}
static INT index_from_var(script_ctx_t *ctx, VARIANT *v)
{
jsexcept_t ei;
VARIANT num;
HRESULT hres;
memset(&ei, 0, sizeof(ei));
hres = to_number(ctx, v, &ei, &num);
if(FAILED(hres)) { /* FIXME: Move ignoring exceptions to to_promitive */
VariantClear(&ei.var);
return 0;
}
if(V_VT(&num) == VT_R8) {
DOUBLE d = floor(V_R8(&num));
return (DOUBLE)(INT)d == d ? d : 0;
}
return V_I4(&num);
}
static HRESULT RegExp_lastIndex(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
@ -3482,8 +3523,21 @@ static HRESULT RegExp_lastIndex(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
switch(flags) {
case DISPATCH_PROPERTYGET: {
RegExpInstance *regexp = regexp_from_vdisp(jsthis);
V_VT(retv) = VT_I4;
V_I4(retv) = regexp->last_index;
V_VT(retv) = VT_EMPTY;
return VariantCopy(retv, &regexp->last_index_var);
}
case DISPATCH_PROPERTYPUT: {
RegExpInstance *regexp = regexp_from_vdisp(jsthis);
VARIANT *arg;
HRESULT hres;
arg = get_arg(dp,0);
hres = VariantCopy(&regexp->last_index_var, arg);
if(FAILED(hres))
return hres;
regexp->last_index = index_from_var(ctx, arg);
break;
}
default:
@ -3589,28 +3643,34 @@ static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, VARIANT *arg, jsexce
return E_OUTOFMEMORY;
}
if(regexp->last_index < 0) {
SysFreeString(string);
set_last_index(regexp, 0);
*ret = VARIANT_FALSE;
if(input) {
*input = NULL;
}
return S_OK;
}
length = SysStringLen(string);
if(regexp->jsregexp->flags & JSREG_GLOB)
last_index = regexp->last_index;
cp = string + last_index;
hres = regexp_match_next(ctx, &regexp->dispex, FALSE, string, length, &cp, parens, parens ? &parens_size : NULL,
parens_cnt, match);
hres = regexp_match_next(ctx, &regexp->dispex, REM_RESET_INDEX, string, length, &cp, parens,
parens ? &parens_size : NULL, parens_cnt, match);
if(FAILED(hres)) {
SysFreeString(string);
return hres;
}
if(hres == S_OK) {
regexp->last_index = cp-string;
*ret = VARIANT_TRUE;
}else {
regexp->last_index = 0;
*ret = VARIANT_FALSE;
}
if(input)
*ret = hres == S_OK ? VARIANT_TRUE : VARIANT_FALSE;
if(input) {
*input = string;
}else {
SysFreeString(string);
}
return S_OK;
}
@ -3690,6 +3750,7 @@ static void RegExp_destructor(DispatchEx *dispex)
if(This->jsregexp)
js_DestroyRegExp(This->jsregexp);
VariantClear(&This->last_index_var);
SysFreeString(This->str);
heap_free(This);
}
@ -3737,7 +3798,7 @@ static HRESULT alloc_regexp(script_ctx_t *ctx, DispatchEx *object_prototype, Reg
return S_OK;
}
static HRESULT create_regexp(script_ctx_t *ctx, const WCHAR *exp, int len, DWORD flags, DispatchEx **ret)
HRESULT create_regexp(script_ctx_t *ctx, const WCHAR *exp, int len, DWORD flags, DispatchEx **ret)
{
RegExpInstance *regexp;
HRESULT hres;
@ -3764,73 +3825,57 @@ static HRESULT create_regexp(script_ctx_t *ctx, const WCHAR *exp, int len, DWORD
return E_FAIL;
}
V_VT(&regexp->last_index_var) = VT_I4;
V_I4(&regexp->last_index_var) = 0;
*ret = &regexp->dispex;
return S_OK;
}
static HRESULT regexp_constructor(script_ctx_t *ctx, DISPPARAMS *dp, VARIANT *retv)
HRESULT create_regexp_var(script_ctx_t *ctx, VARIANT *src_arg, VARIANT *flags_arg, DispatchEx **ret)
{
const WCHAR *opt = emptyW, *src;
DispatchEx *ret;
VARIANT *arg;
DWORD flags;
HRESULT hres;
if(!arg_cnt(dp)) {
FIXME("no args\n");
return E_NOTIMPL;
}
arg = get_arg(dp,0);
if(V_VT(arg) == VT_DISPATCH) {
if(V_VT(src_arg) == VT_DISPATCH) {
DispatchEx *obj;
obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(src_arg));
if(obj) {
if(is_class(obj, JSCLASS_REGEXP)) {
RegExpInstance *regexp = (RegExpInstance*)obj;
hres = create_regexp(ctx, regexp->str, -1, regexp->jsregexp->flags, &ret);
hres = create_regexp(ctx, regexp->str, -1, regexp->jsregexp->flags, ret);
jsdisp_release(obj);
if(FAILED(hres))
return hres;
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret);
return S_OK;
return hres;
}
jsdisp_release(obj);
}
}
if(V_VT(arg) != VT_BSTR) {
FIXME("vt arg0 = %d\n", V_VT(arg));
if(V_VT(src_arg) != VT_BSTR) {
FIXME("flags_arg = %s\n", debugstr_variant(flags_arg));
return E_NOTIMPL;
}
src = V_BSTR(arg);
src = V_BSTR(src_arg);
if(arg_cnt(dp) >= 2) {
arg = get_arg(dp,1);
if(V_VT(arg) != VT_BSTR) {
FIXME("unimplemented for vt %d\n", V_VT(arg));
if(flags_arg) {
if(V_VT(flags_arg) != VT_BSTR) {
FIXME("unimplemented for vt %d\n", V_VT(flags_arg));
return E_NOTIMPL;
}
opt = V_BSTR(arg);
opt = V_BSTR(flags_arg);
}
hres = create_regexp_str(ctx, src, -1, opt, strlenW(opt), &ret);
hres = parse_regexp_flags(opt, strlenW(opt), &flags);
if(FAILED(hres))
return hres;
if(retv) {
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret);
}else {
jsdisp_release(ret);
}
return S_OK;
return create_regexp(ctx, src, -1, flags, ret);
}
static HRESULT RegExpConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
@ -3864,8 +3909,27 @@ static HRESULT RegExpConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
}
}
/* fall through */
case DISPATCH_CONSTRUCT:
return regexp_constructor(ctx, dp, retv);
case DISPATCH_CONSTRUCT: {
DispatchEx *ret;
HRESULT hres;
if(!arg_cnt(dp)) {
FIXME("no args\n");
return E_NOTIMPL;
}
hres = create_regexp_var(ctx, get_arg(dp,0), arg_cnt(dp) > 1 ? get_arg(dp,1) : NULL, &ret);
if(FAILED(hres))
return hres;
if(retv) {
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret);
}else {
jsdisp_release(ret);
}
return S_OK;
}
default:
FIXME("unimplemented flags: %x\n", flags);
return E_NOTIMPL;
@ -3885,39 +3949,38 @@ HRESULT create_regexp_constr(script_ctx_t *ctx, DispatchEx *object_prototype, Di
if(FAILED(hres))
return hres;
hres = create_builtin_function(ctx, RegExpConstr_value, RegExpW, NULL, PROPF_CONSTR, &regexp->dispex, ret);
hres = create_builtin_function(ctx, RegExpConstr_value, RegExpW, NULL,
PROPF_CONSTR|2, &regexp->dispex, ret);
jsdisp_release(&regexp->dispex);
return hres;
}
HRESULT create_regexp_str(script_ctx_t *ctx, const WCHAR *exp, DWORD exp_len, const WCHAR *opt,
DWORD opt_len, DispatchEx **ret)
HRESULT parse_regexp_flags(const WCHAR *str, DWORD str_len, DWORD *ret)
{
const WCHAR *p;
DWORD flags = 0;
if(opt) {
for (p = opt; p < opt+opt_len; p++) {
switch (*p) {
case 'g':
flags |= JSREG_GLOB;
break;
case 'i':
flags |= JSREG_FOLD;
break;
case 'm':
flags |= JSREG_MULTILINE;
break;
case 'y':
flags |= JSREG_STICKY;
break;
default:
WARN("wrong flag %c\n", *p);
return E_FAIL;
}
for (p = str; p < str+str_len; p++) {
switch (*p) {
case 'g':
flags |= JSREG_GLOB;
break;
case 'i':
flags |= JSREG_FOLD;
break;
case 'm':
flags |= JSREG_MULTILINE;
break;
case 'y':
flags |= JSREG_STICKY;
break;
default:
WARN("wrong flag %c\n", *p);
return E_FAIL;
}
}
return create_regexp(ctx, exp, exp_len, flags, ret);
*ret = flags;
return S_OK;
}

View file

@ -37,5 +37,6 @@
#define IDS_NOT_BOOL 0x1392
#define IDS_JSCRIPT_EXPECTED 0x1396
#define IDS_REGEXP_SYNTAX_ERROR 0x1399
#define IDS_URI_INVALID_CHAR 0x13A0
#define IDS_INVALID_LENGTH 0x13A5
#define IDS_ARRAY_EXPECTED 0x13A7

View file

@ -25,6 +25,8 @@ REGINST REGINST jscript.inf
#include "jscript_De.rc"
#include "jscript_En.rc"
#include "jscript_Fr.rc"
#include "jscript_Ko.rc"
#include "jscript_Lt.rc"
#include "jscript_Nl.rc"
#include "jscript_Pt.rc"
#include "jscript_Ru.rc"

View file

@ -656,7 +656,7 @@ static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP
if(FAILED(hres))
return hres;
hres = create_regexp_str(ctx, match_str, SysStringLen(match_str), NULL, 0, &regexp);
hres = create_regexp(ctx, match_str, SysStringLen(match_str), 0, &regexp);
SysFreeString(match_str);
if(FAILED(hres))
return hres;
@ -703,6 +703,7 @@ static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP
break;
}
heap_free(match_result);
SysFreeString(val_str);
if(SUCCEEDED(hres) && retv) {
@ -795,7 +796,7 @@ static HRESULT rep_call(script_ctx_t *ctx, DispatchEx *func, const WCHAR *str, m
if(SUCCEEDED(hres))
hres = jsdisp_call_value(func, DISPATCH_METHOD, &dp, &var, ei, caller);
for(i=0; i < parens_cnt+1; i++) {
for(i=0; i < parens_cnt+3; i++) {
if(i != parens_cnt+1)
SysFreeString(V_BSTR(get_arg(&dp,i)));
}
@ -819,7 +820,7 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI
DispatchEx *rep_func = NULL, *regexp = NULL;
match_result_t *parens = NULL, match, **parens_ptr = &parens;
strbuf_t ret = {NULL,0,0};
BOOL gcheck = FALSE;
DWORD re_flags = 0;
VARIANT *arg_var;
HRESULT hres = S_OK;
@ -896,9 +897,9 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI
while(1) {
if(regexp) {
hres = regexp_match_next(ctx, regexp, gcheck, str, length, &cp, parens_ptr,
hres = regexp_match_next(ctx, regexp, re_flags, str, length, &cp, parens_ptr,
&parens_size, &parens_cnt, &match);
gcheck = TRUE;
re_flags = REM_CHECK_GLOBAL;
if(hres == S_FALSE) {
hres = S_OK;
@ -965,7 +966,7 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI
}
idx = ptr2[1] - '0';
if(isdigitW(ptr[3]) && idx*10 + (ptr[2]-'0') <= parens_cnt) {
if(isdigitW(ptr2[2]) && idx*10 + (ptr2[2]-'0') <= parens_cnt) {
idx = idx*10 + (ptr[2]-'0');
ptr = ptr2+3;
}else if(idx && idx <= parens_cnt) {
@ -1031,8 +1032,58 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI
static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
DispatchEx *regexp = NULL;
const WCHAR *str, *cp;
match_result_t match;
VARIANT *arg;
DWORD length;
BSTR val_str;
HRESULT hres;
TRACE("\n");
hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
if(FAILED(hres))
return hres;
if(!arg_cnt(dp)) {
if(retv)
V_VT(retv) = VT_NULL;
SysFreeString(val_str);
return S_OK;
}
arg = get_arg(dp,0);
if(V_VT(arg) == VT_DISPATCH) {
regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
if(regexp) {
if(!is_class(regexp, JSCLASS_REGEXP)) {
jsdisp_release(regexp);
regexp = NULL;
}
}
}
if(!regexp) {
hres = create_regexp_var(ctx, arg, NULL, &regexp);
if(FAILED(hres)) {
SysFreeString(val_str);
return hres;
}
}
cp = str;
hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX, str, length, &cp, NULL, NULL, NULL, &match);
SysFreeString(val_str);
jsdisp_release(regexp);
if(FAILED(hres))
return hres;
if(retv) {
V_VT(retv) = VT_I4;
V_I4(retv) = hres == S_OK ? match.str-str : -1;
}
return S_OK;
}
/* ECMA-262 3rd Edition 15.5.4.13 */
@ -1129,6 +1180,7 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP
match_result_t *match_result = NULL;
DWORD length, match_cnt, i, match_len = 0;
const WCHAR *str, *ptr, *ptr2;
BOOL use_regexp = FALSE;
VARIANT *arg, var;
DispatchEx *array;
BSTR val_str, match_str = NULL;
@ -1153,6 +1205,7 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP
regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
if(regexp) {
if(is_class(regexp, JSCLASS_REGEXP)) {
use_regexp = TRUE;
hres = regexp_match(ctx, regexp, str, length, TRUE, &match_result, &match_cnt);
jsdisp_release(regexp);
if(FAILED(hres)) {
@ -1183,7 +1236,7 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP
if(SUCCEEDED(hres)) {
ptr = str;
for(i=0;; i++) {
if(match_result) {
if(use_regexp) {
if(i == match_cnt)
break;
ptr2 = match_result[i].str;
@ -1209,7 +1262,7 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP
if(FAILED(hres))
break;
if(match_result)
if(use_regexp)
ptr = match_result[i].str + match_result[i].len;
else if(match_str)
ptr = ptr2 + match_len;
@ -1218,7 +1271,7 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP
}
}
if(SUCCEEDED(hres) && (match_str || match_result)) {
if(SUCCEEDED(hres) && (match_str || use_regexp)) {
DWORD len = (str+length) - ptr;
if(len || match_str) {
@ -1705,7 +1758,7 @@ HRESULT create_string_constr(script_ctx_t *ctx, DispatchEx *object_prototype, Di
return hres;
hres = create_builtin_function(ctx, StringConstr_value, StringW, &StringConstr_info,
PROPF_CONSTR, &string->dispex, ret);
PROPF_CONSTR|1, &string->dispex, ret);
jsdisp_release(&string->dispex);
return hres;