sync jscript with wine 1.1.5

svn path=/trunk/; revision=36376
This commit is contained in:
Christoph von Wittich
2008-09-21 13:24:00 +00:00
parent 3415a605e5
commit fff44b9cb5
21 changed files with 10333 additions and 330 deletions
+345
View File
@@ -0,0 +1,345 @@
/*
* Copyright 2008 Jacek Caban for CodeWeavers
*
* 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 "jscript.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
typedef struct {
DispatchEx dispex;
DWORD length;
} ArrayInstance;
static const WCHAR lengthW[] = {'l','e','n','g','t','h',0};
static const WCHAR concatW[] = {'c','o','n','c','a','t',0};
static const WCHAR joinW[] = {'j','o','i','n',0};
static const WCHAR popW[] = {'p','o','p',0};
static const WCHAR pushW[] = {'p','u','s','h',0};
static const WCHAR reverseW[] = {'r','e','v','e','r','s','e',0};
static const WCHAR shiftW[] = {'s','h','i','f','t',0};
static const WCHAR sliceW[] = {'s','l','i','c','e',0};
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[] =
{'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 Array_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
ArrayInstance *This = (ArrayInstance*)dispex;
TRACE("%p %d\n", This, This->length);
switch(flags) {
case DISPATCH_PROPERTYGET:
V_VT(retv) = VT_I4;
V_I4(retv) = This->length;
break;
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
return S_OK;
}
static HRESULT Array_concat(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_join(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_pop(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_push(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_reverse(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_shift(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_slice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_sort(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_splice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
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)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Array_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static void Array_destructor(DispatchEx *dispex)
{
heap_free(dispex);
}
static void Array_on_put(DispatchEx *dispex, const WCHAR *name)
{
ArrayInstance *array = (ArrayInstance*)dispex;
const WCHAR *ptr = name;
DWORD id = 0;
if(!isdigitW(*ptr))
return;
while(*ptr && isdigitW(*ptr)) {
id = id*10 + (*ptr-'0');
ptr++;
}
if(*ptr)
return;
if(id >= array->length)
array->length = id+1;
}
static const builtin_prop_t Array_props[] = {
{concatW, Array_concat, PROPF_METHOD},
{hasOwnPropertyW, Array_hasOwnProperty, PROPF_METHOD},
{isPrototypeOfW, Array_isPrototypeOf, PROPF_METHOD},
{joinW, Array_join, PROPF_METHOD},
{lengthW, Array_length, 0},
{popW, Array_pop, PROPF_METHOD},
{propertyIsEnumerableW, Array_propertyIsEnumerable, PROPF_METHOD},
{pushW, Array_push, PROPF_METHOD},
{reverseW, Array_reverse, PROPF_METHOD},
{shiftW, Array_shift, PROPF_METHOD},
{sliceW, Array_slice, PROPF_METHOD},
{sortW, Array_sort, PROPF_METHOD},
{spliceW, Array_splice, PROPF_METHOD},
{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 = {
JSCLASS_ARRAY,
{NULL, Array_value, 0},
sizeof(Array_props)/sizeof(*Array_props),
Array_props,
Array_destructor,
Array_on_put
};
static HRESULT ArrayConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
DispatchEx *obj;
VARIANT *arg_var;
DWORD i;
HRESULT hres;
TRACE("\n");
switch(flags) {
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;
}
hres = create_array(dispex->ctx, V_I4(arg_var), &obj);
if(FAILED(hres))
return hres;
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj);
return S_OK;
}
hres = create_array(dispex->ctx, arg_cnt(dp), &obj);
if(FAILED(hres))
return hres;
for(i=0; i < arg_cnt(dp); i++) {
hres = jsdisp_propput_idx(obj, i, lcid, get_arg(dp, i), ei, caller);
if(FAILED(hres))
break;
}
if(FAILED(hres)) {
jsdisp_release(obj);
return hres;
}
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj);
break;
}
default:
FIXME("unimplemented flags: %x\n", flags);
return E_NOTIMPL;
}
return S_OK;
}
static HRESULT alloc_array(script_ctx_t *ctx, BOOL use_constr, ArrayInstance **ret)
{
ArrayInstance *array = heap_alloc_zero(sizeof(ArrayInstance));
HRESULT hres;
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);
if(FAILED(hres)) {
heap_free(array);
return hres;
}
*ret = array;
return S_OK;
}
HRESULT create_array_constr(script_ctx_t *ctx, DispatchEx **ret)
{
ArrayInstance *array;
HRESULT hres;
hres = alloc_array(ctx, FALSE, &array);
if(FAILED(hres))
return hres;
hres = create_builtin_function(ctx, ArrayConstr_value, PROPF_CONSTR, &array->dispex, ret);
IDispatchEx_Release(_IDispatchEx_(&array->dispex));
return hres;
}
HRESULT create_array(script_ctx_t *ctx, DWORD length, DispatchEx **ret)
{
ArrayInstance *array;
HRESULT hres;
hres = alloc_array(ctx, TRUE, &array);
if(FAILED(hres))
return hres;
array->length = length;
*ret = &array->dispex;
return S_OK;
}
+164
View File
@@ -0,0 +1,164 @@
/*
* Copyright 2008 Jacek Caban for CodeWeavers
*
* 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 "jscript.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
typedef struct {
DispatchEx dispex;
VARIANT_BOOL val;
} BoolInstance;
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 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 Bool_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Bool_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Bool_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Bool_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Bool_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Bool_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Bool_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static const builtin_prop_t Bool_props[] = {
{hasOwnPropertyW, Bool_hasOwnProperty, PROPF_METHOD},
{isPrototypeOfW, Bool_isPrototypeOf, PROPF_METHOD},
{propertyIsEnumerableW, Bool_propertyIsEnumerable, PROPF_METHOD},
{toLocaleStringW, Bool_toLocaleString, PROPF_METHOD},
{toStringW, Bool_toString, PROPF_METHOD},
{valueOfW, Bool_valueOf, PROPF_METHOD}
};
static const builtin_info_t Bool_info = {
JSCLASS_BOOLEAN,
{NULL, Bool_value, 0},
sizeof(Bool_props)/sizeof(*Bool_props),
Bool_props,
NULL,
NULL
};
static HRESULT BoolConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT alloc_bool(script_ctx_t *ctx, BOOL use_constr, BoolInstance **ret)
{
BoolInstance *bool;
HRESULT hres;
bool = heap_alloc_zero(sizeof(BoolInstance));
if(!bool)
return E_OUTOFMEMORY;
if(use_constr)
hres = init_dispex_from_constr(&bool->dispex, ctx, &Bool_info, ctx->bool_constr);
else
hres = init_dispex(&bool->dispex, ctx, &Bool_info, NULL);
if(FAILED(hres)) {
heap_free(bool);
return hres;
}
*ret = bool;
return S_OK;
}
HRESULT create_bool_constr(script_ctx_t *ctx, DispatchEx **ret)
{
BoolInstance *bool;
HRESULT hres;
hres = alloc_bool(ctx, FALSE, &bool);
if(FAILED(hres))
return hres;
hres = create_builtin_function(ctx, BoolConstr_value, PROPF_CONSTR, &bool->dispex, ret);
jsdisp_release(&bool->dispex);
return hres;
}
HRESULT create_bool(script_ctx_t *ctx, VARIANT_BOOL b, DispatchEx **ret)
{
BoolInstance *bool;
HRESULT hres;
hres = alloc_bool(ctx, TRUE, &bool);
if(FAILED(hres))
return hres;
bool->val = b;
*ret = &bool->dispex;
return S_OK;
}
+751 -14
View File
@@ -23,6 +23,379 @@
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
/*
* This IID is used to get DispatchEx objecto from interface.
* We might consider using private insteface instead.
*/
static const IID IID_IDispatchJS =
{0x719c3050,0xf9d3,0x11cf,{0xa4,0x93,0x00,0x40,0x05,0x23,0xa8,0xa6}};
typedef enum {
PROP_VARIANT,
PROP_BUILTIN,
PROP_PROTREF,
PROP_DELETED
} prop_type_t;
struct _dispex_prop_t {
WCHAR *name;
prop_type_t type;
DWORD flags;
union {
VARIANT var;
const builtin_prop_t *p;
DWORD ref;
} u;
};
static inline DISPID prop_to_id(DispatchEx *This, dispex_prop_t *prop)
{
return prop - This->props;
}
static inline dispex_prop_t *get_prop(DispatchEx *This, DISPID id)
{
if(id < 0 || id >= This->prop_cnt || This->props[id].type == PROP_DELETED)
return NULL;
return This->props+id;
}
static DWORD get_flags(DispatchEx *This, dispex_prop_t *prop)
{
if(prop->type == PROP_PROTREF) {
dispex_prop_t *parent = get_prop(This->prototype, prop->u.ref);
if(!parent) {
prop->type = PROP_DELETED;
return 0;
}
return get_flags(This->prototype, parent);
}
return prop->flags;
}
static const builtin_prop_t *find_builtin_prop(DispatchEx *This, const WCHAR *name)
{
int min = 0, max, i, r;
max = This->builtin_info->props_cnt-1;
while(min <= max) {
i = (min+max)/2;
r = strcmpW(name, This->builtin_info->props[i].name);
if(!r)
return This->builtin_info->props + i;
if(r < 0)
max = i-1;
else
min = i+1;
}
return NULL;
}
static dispex_prop_t *alloc_prop(DispatchEx *This, const WCHAR *name, prop_type_t type, DWORD flags)
{
dispex_prop_t *ret;
if(This->buf_size == This->prop_cnt) {
dispex_prop_t *tmp = heap_realloc(This->props, (This->buf_size<<=1)*sizeof(*This->props));
if(!tmp)
return NULL;
This->props = tmp;
}
ret = This->props + This->prop_cnt++;
ret->type = type;
ret->flags = flags;
ret->name = heap_strdupW(name);
if(!ret->name)
return NULL;
return ret;
}
static dispex_prop_t *alloc_protref(DispatchEx *This, const WCHAR *name, DWORD ref)
{
dispex_prop_t *ret;
ret = alloc_prop(This, name, PROP_PROTREF, 0);
if(!ret)
return NULL;
ret->u.ref = ref;
return ret;
}
static HRESULT find_prop_name(DispatchEx *This, const WCHAR *name, dispex_prop_t **ret)
{
const builtin_prop_t *builtin;
dispex_prop_t *prop;
for(prop = This->props; prop < This->props+This->prop_cnt; prop++) {
if(prop->name && !strcmpW(prop->name, name)) {
*ret = prop;
return S_OK;
}
}
builtin = find_builtin_prop(This, name);
if(builtin) {
prop = alloc_prop(This, name, PROP_BUILTIN, builtin->flags);
if(!prop)
return E_OUTOFMEMORY;
prop->u.p = builtin;
*ret = prop;
return S_OK;
}
*ret = NULL;
return S_OK;
}
static HRESULT find_prop_name_prot(DispatchEx *This, const WCHAR *name, BOOL alloc, dispex_prop_t **ret)
{
dispex_prop_t *prop;
HRESULT hres;
hres = find_prop_name(This, name, &prop);
if(FAILED(hres))
return hres;
if(prop) {
*ret = prop;
return S_OK;
}
if(This->prototype) {
hres = find_prop_name_prot(This->prototype, name, FALSE, &prop);
if(FAILED(hres))
return hres;
if(prop) {
prop = alloc_protref(This, prop->name, prop - This->prototype->props);
if(!prop)
return E_OUTOFMEMORY;
*ret = prop;
return S_OK;
}
}
if(alloc) {
TRACE("creating prop %s\n", debugstr_w(name));
prop = alloc_prop(This, name, PROP_VARIANT, PROPF_ENUM);
if(!prop)
return E_OUTOFMEMORY;
VariantInit(&prop->u.var);
}
*ret = prop;
return S_OK;
}
static HRESULT set_this(DISPPARAMS *dp, DISPPARAMS *olddp, IDispatch *jsthis)
{
VARIANTARG *oldargs;
int i;
static DISPID this_id = DISPID_THIS;
*dp = *olddp;
for(i = 0; i < dp->cNamedArgs; i++) {
if(dp->rgdispidNamedArgs[i] == DISPID_THIS)
return S_OK;
}
oldargs = dp->rgvarg;
dp->rgvarg = heap_alloc((dp->cArgs+1) * sizeof(VARIANTARG));
if(!dp->rgvarg)
return E_OUTOFMEMORY;
memcpy(dp->rgvarg+1, oldargs, dp->cArgs*sizeof(VARIANTARG));
V_VT(dp->rgvarg) = VT_DISPATCH;
V_DISPATCH(dp->rgvarg) = jsthis;
dp->cArgs++;
if(dp->cNamedArgs) {
DISPID *old = dp->rgdispidNamedArgs;
dp->rgdispidNamedArgs = heap_alloc((dp->cNamedArgs+1)*sizeof(DISPID));
if(!dp->rgdispidNamedArgs) {
heap_free(dp->rgvarg);
return E_OUTOFMEMORY;
}
memcpy(dp->rgdispidNamedArgs+1, old, dp->cNamedArgs*sizeof(DISPID));
dp->rgdispidNamedArgs[0] = DISPID_THIS;
dp->cNamedArgs++;
}else {
dp->rgdispidNamedArgs = &this_id;
dp->cNamedArgs = 1;
}
return S_OK;
}
static HRESULT invoke_prop_func(DispatchEx *This, DispatchEx *jsthis, dispex_prop_t *prop, LCID lcid, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
HRESULT hres;
switch(prop->type) {
case PROP_BUILTIN:
if(flags == DISPATCH_CONSTRUCT && (prop->flags & DISPATCH_METHOD)) {
WARN("%s is not a constructor\n", debugstr_w(prop->name));
return E_INVALIDARG;
}
return prop->u.p->invoke(jsthis, lcid, flags, dp, retv, ei, caller);
case PROP_PROTREF:
return invoke_prop_func(This->prototype, jsthis, This->prototype->props+prop->u.ref, lcid, flags, dp, retv, ei, caller);
case PROP_VARIANT: {
DISPPARAMS new_dp;
if(V_VT(&prop->u.var) != VT_DISPATCH) {
FIXME("invoke vt %d\n", V_VT(&prop->u.var));
return E_FAIL;
}
TRACE("call %s %p\n", debugstr_w(prop->name), V_DISPATCH(&prop->u.var));
hres = set_this(&new_dp, dp, (IDispatch*)_IDispatchEx_(jsthis));
if(FAILED(hres))
return hres;
hres = disp_call(V_DISPATCH(&prop->u.var), DISPID_VALUE, lcid, flags, &new_dp, retv, ei, caller);
if(new_dp.rgvarg != dp->rgvarg) {
heap_free(new_dp.rgvarg);
if(new_dp.cNamedArgs > 1)
heap_free(new_dp.rgdispidNamedArgs);
}
return hres;
}
default:
ERR("type %d\n", prop->type);
}
return E_FAIL;
}
static HRESULT prop_get(DispatchEx *This, dispex_prop_t *prop, LCID lcid, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
HRESULT hres;
switch(prop->type) {
case PROP_BUILTIN:
if(prop->u.p->flags & PROPF_METHOD) {
DispatchEx *obj;
hres = create_builtin_function(This->ctx, prop->u.p->invoke, prop->u.p->flags, NULL, &obj);
if(FAILED(hres))
break;
prop->type = PROP_VARIANT;
V_VT(&prop->u.var) = VT_DISPATCH;
V_DISPATCH(&prop->u.var) = (IDispatch*)_IDispatchEx_(obj);
hres = VariantCopy(retv, &prop->u.var);
}else {
hres = prop->u.p->invoke(This, lcid, DISPATCH_PROPERTYGET, dp, retv, ei, caller);
}
break;
case PROP_PROTREF:
hres = prop_get(This->prototype, This->prototype->props+prop->u.ref, lcid, dp, retv, ei, caller);
break;
case PROP_VARIANT:
hres = VariantCopy(retv, &prop->u.var);
break;
default:
ERR("type %d\n", prop->type);
return E_FAIL;
}
if(FAILED(hres)) {
TRACE("fail %08x\n", hres);
return hres;
}
TRACE("%s ret %s\n", debugstr_w(prop->name), debugstr_variant(retv));
return hres;
}
static HRESULT prop_put(DispatchEx *This, dispex_prop_t *prop, LCID lcid, DISPPARAMS *dp,
jsexcept_t *ei, IServiceProvider *caller)
{
DWORD i;
HRESULT hres;
switch(prop->type) {
case PROP_BUILTIN:
if(!(prop->flags & PROPF_METHOD))
return prop->u.p->invoke(This, lcid, DISPATCH_PROPERTYPUT, dp, NULL, ei, caller);
case PROP_PROTREF:
prop->type = PROP_VARIANT;
prop->flags = PROPF_ENUM;
V_VT(&prop->u.var) = VT_EMPTY;
break;
case PROP_VARIANT:
VariantClear(&prop->u.var);
break;
default:
ERR("type %d\n", prop->type);
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);
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));
return S_OK;
}
static HRESULT fill_protrefs(DispatchEx *This)
{
dispex_prop_t *iter, *prop;
HRESULT hres;
if(!This->prototype)
return S_OK;
fill_protrefs(This->prototype);
for(iter = This->prototype->props; iter < This->prototype->props+This->prototype->prop_cnt; iter++) {
if(!iter->name)
continue;
hres = find_prop_name(This, iter->name, &prop);
if(FAILED(hres))
return hres;
if(!prop) {
prop = alloc_protref(This, iter->name, iter - This->prototype->props);
if(!prop)
return E_OUTOFMEMORY;
}
}
return S_OK;
}
#define DISPATCHEX_THIS(iface) DEFINE_THIS(DispatchEx, IDispatchEx, iface)
static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
@@ -38,6 +411,11 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid,
}else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
*ppv = _IDispatchEx_(This);
}else if(IsEqualGUID(&IID_IDispatchJS, riid)) {
TRACE("(%p)->(IID_IDispatchJS %p)\n", This, ppv);
IUnknown_AddRef(_IDispatchEx_(This));
*ppv = This;
return S_OK;
}else {
WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
*ppv = NULL;
@@ -66,8 +444,20 @@ static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
TRACE("(%p) ref=%d\n", This, ref);
if(!ref) {
dispex_prop_t *prop;
for(prop = This->props; prop < This->props+This->prop_cnt; prop++) {
if(prop->type == PROP_VARIANT)
VariantClear(&prop->u.var);
heap_free(prop->name);
}
heap_free(This->props);
script_release(This->ctx);
heap_free(This);
if(This->builtin_info->destructor)
This->builtin_info->destructor(This);
else
heap_free(This);
}
return ref;
@@ -127,23 +517,94 @@ static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
{
DispatchEx *This = DISPATCHEX_THIS(iface);
FIXME("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
return E_NOTIMPL;
dispex_prop_t *prop;
HRESULT hres;
TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
if(grfdex & ~(fdexNameCaseSensitive|fdexNameEnsure|fdexNameImplicit)) {
FIXME("Unsupported grfdex %x\n", grfdex);
return E_NOTIMPL;
}
hres = find_prop_name_prot(This, bstrName, (grfdex&fdexNameEnsure) != 0, &prop);
if(FAILED(hres))
return hres;
if(prop) {
*pid = prop_to_id(This, prop);
return S_OK;
}
TRACE("not found %s\n", debugstr_w(bstrName));
return DISP_E_UNKNOWNNAME;
}
static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
{
DispatchEx *This = DISPATCHEX_THIS(iface);
FIXME("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
return E_NOTIMPL;
dispex_prop_t *prop;
jsexcept_t jsexcept;
HRESULT hres;
TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
if(pvarRes)
V_VT(pvarRes) = VT_EMPTY;
prop = get_prop(This, id);
if(!prop || prop->type == PROP_DELETED) {
TRACE("invalid id\n");
return DISP_E_MEMBERNOTFOUND;
}
memset(&jsexcept, 0, sizeof(jsexcept));
switch(wFlags) {
case DISPATCH_METHOD:
case DISPATCH_CONSTRUCT:
hres = invoke_prop_func(This, This, prop, lcid, wFlags, pdp, pvarRes, &jsexcept, pspCaller);
break;
case DISPATCH_PROPERTYGET:
hres = prop_get(This, prop, lcid, pdp, pvarRes, &jsexcept, pspCaller);
break;
case DISPATCH_PROPERTYPUT:
hres = prop_put(This, prop, lcid, pdp, &jsexcept, pspCaller);
break;
default:
FIXME("Unimplemented flags %x\n", wFlags);
return E_INVALIDARG;
}
if(pei)
*pei = jsexcept.ei;
return hres;
}
static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
{
DispatchEx *This = DISPATCHEX_THIS(iface);
FIXME("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex);
return E_NOTIMPL;
dispex_prop_t *prop;
HRESULT hres;
TRACE("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex);
if(grfdex & ~(fdexNameCaseSensitive|fdexNameEnsure|fdexNameImplicit))
FIXME("Unsupported grfdex %x\n", grfdex);
hres = find_prop_name(This, bstrName, &prop);
if(FAILED(hres))
return hres;
if(!prop) {
TRACE("not found\n");
return S_OK;
}
heap_free(prop->name);
prop->name = NULL;
prop->type = PROP_DELETED;
return S_OK;
}
static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
@@ -163,15 +624,51 @@ static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID
static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
{
DispatchEx *This = DISPATCHEX_THIS(iface);
FIXME("(%p)->(%x %p)\n", This, id, pbstrName);
return E_NOTIMPL;
dispex_prop_t *prop;
TRACE("(%p)->(%x %p)\n", This, id, pbstrName);
prop = get_prop(This, id);
if(!prop || !prop->name || prop->type == PROP_DELETED)
return DISP_E_MEMBERNOTFOUND;
*pbstrName = SysAllocString(prop->name);
if(!*pbstrName)
return E_OUTOFMEMORY;
return S_OK;
}
static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
{
DispatchEx *This = DISPATCHEX_THIS(iface);
FIXME("(%p)->(%x %x %p)\n", This, grfdex, id, pid);
return E_NOTIMPL;
dispex_prop_t *iter;
HRESULT hres;
TRACE("(%p)->(%x %x %p)\n", This, grfdex, id, pid);
if(id == DISPID_STARTENUM) {
hres = fill_protrefs(This);
if(FAILED(hres))
return hres;
}
iter = get_prop(This, id+1);
if(!iter) {
*pid = DISPID_STARTENUM;
return S_FALSE;
}
while(iter < This->props + This->prop_cnt) {
if(iter->name && (get_flags(This, iter) & PROPF_ENUM)) {
*pid = prop_to_id(This, iter);
return S_OK;
}
iter++;
}
*pid = DISPID_STARTENUM;
return S_FALSE;
}
static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
@@ -201,10 +698,48 @@ static IDispatchExVtbl DispatchExVtbl = {
DispatchEx_GetNameSpaceParent
};
static HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx)
HRESULT jsdisp_set_prototype(DispatchEx *dispex, DispatchEx *prototype)
{
VARIANT *var;
if(!dispex->props[1].name)
return E_OUTOFMEMORY;
dispex->props[1].type = PROP_VARIANT;
dispex->props[1].flags = 0;
var = &dispex->props[1].u.var;
V_VT(var) = VT_DISPATCH;
V_DISPATCH(var) = (IDispatch*)_IDispatchEx_(prototype);
return S_OK;
}
HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype)
{
TRACE("%p (%p)\n", dispex, prototype);
dispex->lpIDispatchExVtbl = &DispatchExVtbl;
dispex->ref = 1;
dispex->builtin_info = builtin_info;
dispex->props = heap_alloc((dispex->buf_size=4) * sizeof(dispex_prop_t));
if(!dispex->props)
return E_OUTOFMEMORY;
dispex->prototype = prototype;
if(prototype)
IDispatchEx_AddRef(_IDispatchEx_(prototype));
dispex->prop_cnt = 1;
dispex->props[0].name = NULL;
dispex->props[0].flags = 0;
if(builtin_info->value_prop.invoke) {
dispex->props[0].type = PROP_BUILTIN;
dispex->props[0].u.p = &builtin_info->value_prop;
}else {
dispex->props[0].type = PROP_DELETED;
}
script_addref(ctx);
dispex->ctx = ctx;
@@ -212,7 +747,15 @@ static HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx)
return S_OK;
}
HRESULT create_dispex(script_ctx_t *ctx, DispatchEx **dispex)
static const builtin_info_t dispex_info = {
JSCLASS_NONE,
{NULL, NULL, 0},
0, NULL,
NULL,
NULL
};
HRESULT create_dispex(script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype, DispatchEx **dispex)
{
DispatchEx *ret;
HRESULT hres;
@@ -221,10 +764,204 @@ HRESULT create_dispex(script_ctx_t *ctx, DispatchEx **dispex)
if(!ret)
return E_OUTOFMEMORY;
hres = init_dispex(ret, ctx);
hres = init_dispex(ret, ctx, builtin_info ? builtin_info : &dispex_info, prototype);
if(FAILED(hres))
return hres;
*dispex = ret;
return S_OK;
}
HRESULT init_dispex_from_constr(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *constr)
{
DispatchEx *prot = NULL;
dispex_prop_t *prop;
HRESULT hres;
static const WCHAR prototypeW[] = {'p','r','o','t','o','t','y','p','e',0};
hres = find_prop_name_prot(constr, prototypeW, FALSE, &prop);
if(SUCCEEDED(hres) && prop) {
jsexcept_t jsexcept;
VARIANT var;
V_VT(&var) = VT_EMPTY;
memset(&jsexcept, 0, sizeof(jsexcept));
hres = prop_get(constr, prop, ctx->lcid, NULL, &var, &jsexcept, NULL/*FIXME*/);
if(FAILED(hres)) {
ERR("Could not get prototype\n");
return hres;
}
if(V_VT(&var) == VT_DISPATCH)
prot = iface_to_jsdisp((IUnknown*)V_DISPATCH(&var));
VariantClear(&var);
}
hres = init_dispex(dispex, ctx, builtin_info, prot);
if(prot)
IDispatchEx_Release(_IDispatchEx_(prot));
return hres;
}
DispatchEx *iface_to_jsdisp(IUnknown *iface)
{
DispatchEx *ret;
HRESULT hres;
hres = IUnknown_QueryInterface(iface, &IID_IDispatchJS, (void**)&ret);
if(FAILED(hres))
return NULL;
return ret;
}
HRESULT jsdisp_call_value(DispatchEx *disp, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv,
jsexcept_t *ei, IServiceProvider *caller)
{
return disp->builtin_info->value_prop.invoke(disp, lcid, flags, dp, retv, ei, caller);
}
HRESULT jsdisp_call(DispatchEx *disp, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv,
jsexcept_t *ei, IServiceProvider *caller)
{
dispex_prop_t *prop;
memset(ei, 0, sizeof(*ei));
if(retv)
V_VT(retv) = VT_EMPTY;
prop = get_prop(disp, id);
if(!prop)
return DISP_E_MEMBERNOTFOUND;
return invoke_prop_func(disp, disp, prop, lcid, flags, dp, retv, ei, caller);
}
HRESULT disp_call(IDispatch *disp, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv,
jsexcept_t *ei, IServiceProvider *caller)
{
DispatchEx *jsdisp;
IDispatchEx *dispex;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
if(jsdisp) {
hres = jsdisp_call(jsdisp, id, lcid, flags, dp, retv, ei, caller);
IDispatchEx_Release(_IDispatchEx_(jsdisp));
return hres;
}
memset(ei, 0, sizeof(*ei));
if(retv)
V_VT(retv) = VT_EMPTY;
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(FAILED(hres)) {
UINT err = 0;
TRACE("using IDispatch\n");
return IDispatch_Invoke(disp, id, &IID_NULL, lcid, flags, dp, retv, &ei->ei, &err);
}
hres = IDispatchEx_InvokeEx(dispex, id, lcid, flags, dp, retv, &ei->ei, caller);
IDispatchEx_Release(dispex);
return hres;
}
HRESULT jsdisp_propput_name(DispatchEx *obj, const WCHAR *name, LCID lcid, 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);
if(FAILED(hres))
return hres;
return prop_put(obj, prop, lcid, &dp, ei, caller);
}
HRESULT jsdisp_propput_idx(DispatchEx *obj, DWORD idx, LCID lcid, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
{
WCHAR buf[12];
static const WCHAR formatW[] = {'%','d',0};
sprintfW(buf, formatW, idx);
return jsdisp_propput_name(obj, buf, lcid, val, ei, caller);
}
HRESULT disp_propput(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
{
DISPID dispid = DISPID_PROPERTYPUT;
DISPPARAMS dp = {val, &dispid, 1, 1};
IDispatchEx *dispex;
DispatchEx *jsdisp;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
if(jsdisp) {
dispex_prop_t *prop;
prop = get_prop(jsdisp, id);
if(prop)
hres = prop_put(jsdisp, prop, lcid, &dp, ei, caller);
else
hres = DISP_E_MEMBERNOTFOUND;
IDispatchEx_Release(_IDispatchEx_(jsdisp));
return hres;
}
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, DISPATCH_PROPERTYPUT, lcid, &dp, NULL, &ei->ei, &err);
}
hres = IDispatchEx_InvokeEx(dispex, id, lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, caller);
IDispatchEx_Release(dispex);
return hres;
}
HRESULT disp_propget(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
{
DISPPARAMS dp = {NULL,NULL,0,0};
IDispatchEx *dispex;
DispatchEx *jsdisp;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
if(jsdisp) {
dispex_prop_t *prop;
prop = get_prop(jsdisp, id);
if(prop)
hres = prop_get(jsdisp, prop, lcid, &dp, val, ei, caller);
else
hres = DISP_E_MEMBERNOTFOUND;
IDispatchEx_Release(_IDispatchEx_(jsdisp));
return hres;
}
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(FAILED(hres)) {
ULONG err = 0;
TRACE("uding IDispatch\n");
return IDispatchEx_Invoke(dispex, id, &IID_NULL, lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, &err);
}
hres = IDispatchEx_InvokeEx(dispex, id, lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, caller);
IDispatchEx_Release(dispex);
return hres;
}
File diff suppressed because it is too large Load Diff
+50 -8
View File
@@ -18,6 +18,11 @@
typedef struct _source_elements_t source_elements_t;
typedef struct _obj_literal_t {
DispatchEx *obj;
struct _obj_literal_t *next;
} obj_literal_t;
typedef struct _parser_ctx_t {
LONG ref;
@@ -30,9 +35,10 @@ typedef struct _parser_ctx_t {
BOOL nl;
HRESULT hres;
jsheap_t tmp_heap;
jsheap_t heap;
obj_literal_t *obj_literals;
struct _parser_ctx_t *next;
} parser_ctx_t;
@@ -53,13 +59,30 @@ static inline void *parser_alloc(parser_ctx_t *ctx, DWORD size)
static inline void *parser_alloc_tmp(parser_ctx_t *ctx, DWORD size)
{
return jsheap_alloc(&ctx->tmp_heap, size);
return jsheap_alloc(&ctx->script->tmp_heap, size);
}
typedef struct _scope_chain_t {
LONG ref;
DispatchEx *obj;
struct _scope_chain_t *next;
} scope_chain_t;
HRESULT scope_push(scope_chain_t*,DispatchEx*,scope_chain_t**);
void scope_release(scope_chain_t*);
static inline void scope_addref(scope_chain_t *scope)
{
scope->ref++;
}
struct _exec_ctx_t {
LONG ref;
parser_ctx_t *parser;
scope_chain_t *scope_chain;
DispatchEx *var_disp;
IDispatch *this_obj;
};
static inline void exec_addref(exec_ctx_t *ctx)
@@ -68,13 +91,15 @@ static inline void exec_addref(exec_ctx_t *ctx)
}
void exec_release(exec_ctx_t*);
HRESULT create_exec_ctx(exec_ctx_t**);
HRESULT create_exec_ctx(IDispatch*,DispatchEx*,scope_chain_t*,exec_ctx_t**);
HRESULT exec_source(exec_ctx_t*,parser_ctx_t*,source_elements_t*,jsexcept_t*,VARIANT*);
typedef struct _statement_t statement_t;
typedef struct _expression_t expression_t;
typedef struct _parameter_t parameter_t;
HRESULT create_source_function(parser_ctx_t*,parameter_t*,source_elements_t*,scope_chain_t*,DispatchEx**);
typedef struct {
VARTYPE vt;
union {
@@ -86,6 +111,8 @@ typedef struct {
} u;
} literal_t;
literal_t *parse_regexp(parser_ctx_t*);
typedef struct _variable_declaration_t {
const WCHAR *identifier;
expression_t *expr;
@@ -134,6 +161,7 @@ typedef struct {
typedef struct {
statement_t stat;
BOOL do_while;
expression_t *expr;
statement_t *statement;
} while_statement_t;
@@ -202,7 +230,6 @@ HRESULT var_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
HRESULT empty_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
HRESULT expression_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
HRESULT if_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
HRESULT dowhile_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
HRESULT while_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
HRESULT for_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
HRESULT forin_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
@@ -215,7 +242,24 @@ HRESULT switch_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
HRESULT throw_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
HRESULT try_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
typedef struct exprval_t exprval_t;
typedef struct {
enum {
EXPRVAL_VARIANT,
EXPRVAL_IDREF,
EXPRVAL_NAMEREF
} type;
union {
VARIANT var;
struct {
IDispatch *disp;
DISPID id;
} idref;
struct {
IDispatch *disp;
BSTR name;
} nameref;
} u;
} exprval_t;
typedef HRESULT (*expression_eval_t)(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
@@ -351,7 +395,6 @@ typedef enum {
EXPR_POSTDEC,
EXPR_PREINC,
EXPR_PREDEC,
EXPR_NEW,
EXPR_EQ,
EXPR_EQEQ,
EXPR_NOTEQ,
@@ -383,7 +426,7 @@ HRESULT function_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exp
HRESULT conditional_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT array_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT member_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT member_new_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT new_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT call_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT this_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT identifier_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
@@ -413,7 +456,6 @@ HRESULT post_increment_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_
HRESULT post_decrement_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT pre_increment_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT pre_decrement_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT new_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT equal_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT equal2_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
HRESULT not_equal_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
+496
View File
@@ -0,0 +1,496 @@
/*
* Copyright 2008 Jacek Caban for CodeWeavers
*
* 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 "jscript.h"
#include "engine.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
typedef struct {
DispatchEx dispex;
builtin_invoke_t value_proc;
DWORD flags;
source_elements_t *source;
parameter_t *parameters;
scope_chain_t *scope_chain;
parser_ctx_t *parser;
DWORD length;
} FunctionInstance;
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};
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 IDispatch *get_this(DISPPARAMS *dp)
{
DWORD i;
for(i=0; i < dp->cNamedArgs; i++) {
if(dp->rgdispidNamedArgs[i] == DISPID_THIS) {
if(V_VT(dp->rgvarg+i) == VT_DISPATCH)
return V_DISPATCH(dp->rgvarg+i);
WARN("This is not VT_DISPATCH\n");
return NULL;
}
}
TRACE("no this passed\n");
return NULL;
}
static HRESULT init_parameters(DispatchEx *var_disp, FunctionInstance *function, LCID lcid, DISPPARAMS *dp,
jsexcept_t *ei, IServiceProvider *caller)
{
parameter_t *param;
VARIANT var_empty;
DWORD cargs, i=0;
HRESULT hres;
V_VT(&var_empty) = VT_EMPTY;
cargs = dp->cArgs - dp->cNamedArgs;
for(param = function->parameters; param; param = param->next) {
hres = jsdisp_propput_name(var_disp, param->identifier, lcid,
i < cargs ? dp->rgvarg + dp->cArgs-1 - i : &var_empty,
ei, caller);
if(FAILED(hres))
return hres;
i++;
}
return S_OK;
}
static HRESULT init_arguments(DispatchEx *arg_disp, FunctionInstance *function, LCID lcid, DISPPARAMS *dp,
jsexcept_t *ei, IServiceProvider *caller)
{
VARIANT var;
DWORD i;
HRESULT hres;
for(i=0; i < dp->cArgs-dp->cNamedArgs; i++) {
hres = jsdisp_propput_idx(arg_disp, i, lcid, dp->rgvarg+dp->cArgs-1-i, ei, caller);
if(FAILED(hres))
return hres;
}
V_VT(&var) = VT_I4;
V_I4(&var) = dp->cArgs - dp->cNamedArgs;
return jsdisp_propput_name(arg_disp, lengthW, lcid, &var, ei, caller);
}
static HRESULT create_var_disp(FunctionInstance *function, LCID lcid, DISPPARAMS *dp, jsexcept_t *ei,
IServiceProvider *caller, DispatchEx **ret)
{
DispatchEx *var_disp, *arg_disp;
HRESULT hres;
static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0};
hres = create_dispex(function->dispex.ctx, NULL, NULL, &var_disp);
if(FAILED(hres))
return hres;
hres = create_dispex(function->dispex.ctx, NULL, NULL, &arg_disp);
if(SUCCEEDED(hres)) {
hres = init_arguments(arg_disp, function, lcid, dp, ei, caller);
if(SUCCEEDED(hres)) {
VARIANT var;
V_VT(&var) = VT_DISPATCH;
V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(arg_disp);
hres = jsdisp_propput_name(var_disp, argumentsW, lcid, &var, ei, caller);
}
jsdisp_release(arg_disp);
}
if(SUCCEEDED(hres))
hres = init_parameters(var_disp, function, lcid, dp, ei, caller);
if(FAILED(hres)) {
jsdisp_release(var_disp);
return hres;
}
*ret = var_disp;
return S_OK;
}
static HRESULT invoke_source(FunctionInstance *function, IDispatch *this_obj, LCID lcid, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
DispatchEx *var_disp;
exec_ctx_t *exec_ctx;
scope_chain_t *scope;
HRESULT hres;
if(!function->source) {
FIXME("no source\n");
return E_FAIL;
}
hres = create_var_disp(function, lcid, dp, ei, caller, &var_disp);
if(FAILED(hres))
return hres;
hres = scope_push(function->scope_chain, var_disp, &scope);
if(SUCCEEDED(hres)) {
hres = create_exec_ctx(this_obj, var_disp, scope, &exec_ctx);
scope_release(scope);
}
if(FAILED(hres))
return hres;
hres = exec_source(exec_ctx, function->parser, function->source, ei, retv);
exec_release(exec_ctx);
return hres;
}
static HRESULT invoke_function(FunctionInstance *function, LCID lcid, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
IDispatch *this_obj;
if(!(this_obj = get_this(dp)))
this_obj = (IDispatch*)_IDispatchEx_(function->dispex.ctx->script_disp);
return invoke_source(function, this_obj, lcid, dp, retv, ei, caller);
}
static HRESULT invoke_constructor(FunctionInstance *function, LCID lcid, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
DispatchEx *this_obj;
VARIANT var;
HRESULT hres;
hres = create_object(function->dispex.ctx, &function->dispex, &this_obj);
if(FAILED(hres))
return hres;
hres = invoke_source(function, (IDispatch*)_IDispatchEx_(this_obj), lcid, dp, retv, ei, caller);
jsdisp_release(this_obj);
if(FAILED(hres))
return hres;
VariantClear(&var);
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(this_obj);
return S_OK;
}
static HRESULT invoke_value_proc(FunctionInstance *function, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
DispatchEx *this_obj = NULL;
IDispatch *this_disp;
HRESULT hres;
this_disp = get_this(dp);
if(this_disp)
this_obj = iface_to_jsdisp((IUnknown*)this_disp);
hres = function->value_proc(this_obj ? this_obj : function->dispex.ctx->script_disp, lcid,
flags, dp, retv, ei, caller);
if(this_obj)
jsdisp_release(this_obj);
return hres;
}
static HRESULT Function_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FunctionInstance *This = (FunctionInstance*)dispex;
TRACE("%p %d\n", This, This->length);
switch(flags) {
case DISPATCH_PROPERTYGET:
V_VT(retv) = VT_I4;
V_I4(retv) = This->length;
break;
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
return S_OK;
}
static HRESULT Function_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Function_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
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)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Function_call(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Function_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Function_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Function_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
FunctionInstance *function;
TRACE("\n");
if(dispex->builtin_info->class != JSCLASS_FUNCTION) {
ERR("dispex is not a function\n");
return E_FAIL;
}
function = (FunctionInstance*)dispex;
switch(flags) {
case DISPATCH_METHOD:
if(function->value_proc)
return invoke_value_proc(function, lcid, flags, dp, retv, ei, caller);
return invoke_function(function, lcid, dp, retv, ei, caller);
case DISPATCH_CONSTRUCT:
if(function->value_proc)
return invoke_value_proc(function, lcid, flags, dp, retv, ei, caller);
return invoke_constructor(function, lcid, dp, retv, ei, caller);
default:
FIXME("not implemented flags %x\n", flags);
return E_NOTIMPL;
}
return S_OK;
}
static void Function_destructor(DispatchEx *dispex)
{
FunctionInstance *This = (FunctionInstance*)dispex;
if(This->parser)
parser_release(This->parser);
if(This->scope_chain)
scope_release(This->scope_chain);
heap_free(This);
}
static const builtin_prop_t Function_props[] = {
{applyW, Function_apply, PROPF_METHOD},
{callW, Function_call, PROPF_METHOD},
{hasOwnPropertyW, Function_hasOwnProperty, PROPF_METHOD},
{isPrototypeOfW, Function_isPrototypeOf, PROPF_METHOD},
{lengthW, Function_length, 0},
{propertyIsEnumerableW, Function_propertyIsEnumerable, PROPF_METHOD},
{toLocaleStringW, Function_toLocaleString, PROPF_METHOD},
{toStringW, Function_toString, PROPF_METHOD},
{valueOfW, Function_valueOf, PROPF_METHOD}
};
static const builtin_info_t Function_info = {
JSCLASS_FUNCTION,
{NULL, Function_value, 0},
sizeof(Function_props)/sizeof(*Function_props),
Function_props,
Function_destructor,
NULL
};
static HRESULT FunctionConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT FunctionProt_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT create_function(script_ctx_t *ctx, DWORD flags, BOOL funcprot, DispatchEx *prototype, FunctionInstance **ret)
{
FunctionInstance *function;
HRESULT hres;
function = heap_alloc_zero(sizeof(FunctionInstance));
if(!function)
return E_OUTOFMEMORY;
if(funcprot)
hres = init_dispex(&function->dispex, ctx, &Function_info, prototype);
else
hres = init_dispex_from_constr(&function->dispex, ctx, &Function_info, ctx->function_constr);
if(FAILED(hres))
return hres;
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;
}
HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc, DWORD flags,
DispatchEx *prototype, DispatchEx **ret)
{
FunctionInstance *function;
HRESULT hres;
hres = create_function(ctx, flags, FALSE, prototype, &function);
if(FAILED(hres))
return hres;
function->value_proc = value_proc;
*ret = &function->dispex;
return S_OK;
}
HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, source_elements_t *source,
scope_chain_t *scope_chain, DispatchEx **ret)
{
FunctionInstance *function;
DispatchEx *prototype;
parameter_t *iter;
DWORD length = 0;
HRESULT hres;
hres = create_object(ctx->script, NULL, &prototype);
if(FAILED(hres))
return hres;
hres = create_function(ctx->script, PROPF_CONSTR, FALSE, prototype, &function);
jsdisp_release(prototype);
if(FAILED(hres))
return hres;
function->source = source;
function->parameters = parameters;
if(scope_chain) {
scope_addref(scope_chain);
function->scope_chain = scope_chain;
}
parser_addref(ctx);
function->parser = ctx;
for(iter = parameters; iter; iter = iter->next)
length++;
function->length = length;
*ret = &function->dispex;
return S_OK;
}
HRESULT init_function_constr(script_ctx_t *ctx)
{
FunctionInstance *prot, *constr;
HRESULT hres;
hres = create_function(ctx, PROPF_CONSTR, TRUE, NULL, &prot);
if(FAILED(hres))
return hres;
prot->value_proc = FunctionProt_value;
hres = create_function(ctx, PROPF_CONSTR, TRUE, &prot->dispex, &constr);
jsdisp_release(&prot->dispex);
if(FAILED(hres))
return hres;
constr->value_proc = FunctionConstr_value;
ctx->function_constr = &constr->dispex;
return hres;
}
+394
View File
@@ -0,0 +1,394 @@
/*
* Copyright 2008 Jacek Caban for CodeWeavers
*
* 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 "jscript.h"
#include "engine.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
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 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};
static const WCHAR StringW[] = {'S','t','r','i','n','g',0};
static const WCHAR RegExpW[] = {'R','e','g','E','x','p',0};
static const WCHAR ActiveXObjectW[] = {'A','c','t','i','v','e','X','O','b','j','e','c','t',0};
static const WCHAR VBArrayW[] = {'V','B','A','r','r','a','y',0};
static const WCHAR EnumeratorW[] = {'E','n','u','m','e','r','a','t','o','r',0};
static const WCHAR escapeW[] = {'e','s','c','a','p','e',0};
static const WCHAR evalW[] = {'e','v','a','l',0};
static const WCHAR isNaNW[] = {'i','s','N','a','N',0};
static const WCHAR isFiniteW[] = {'i','s','F','i','n','i','t','e',0};
static const WCHAR parseIntW[] = {'p','a','r','s','e','I','n','t',0};
static const WCHAR parseFloatW[] = {'p','a','r','s','e','F','l','o','a','t',0};
static const WCHAR unescapeW[] = {'u','n','e','s','c','a','p','e',0};
static const WCHAR getObjectW[] = {'G','e','t','O','b','j','e','c','t',0};
static const WCHAR ScriptEngineW[] = {'S','c','r','i','p','t','E','n','g','i','n','e',0};
static const WCHAR ScriptEngineMajorVersionW[] =
{'S','c','r','i','p','t','E','n','g','i','n','e','M','a','j','o','r','V','e','r','s','i','o','n',0};
static const WCHAR ScriptEngineMinorVersionW[] =
{'S','c','r','i','p','t','E','n','g','i','n','e','M','i','n','o','r','V','e','r','s','i','o','n',0};
static const WCHAR ScriptEngineBuildVersionW[] =
{'S','c','r','i','p','t','E','n','g','i','n','e','B','u','i','l','d','V','e','r','s','i','o','n',0};
static const WCHAR CollectGarbageW[] = {'C','o','l','l','e','c','t','G','a','r','b','a','g','e',0};
static const WCHAR MathW[] = {'M','a','t','h',0};
static HRESULT constructor_call(DispatchEx *constr, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
if(flags != DISPATCH_PROPERTYGET)
return jsdisp_call_value(constr, lcid, flags, dp, retv, ei, sp);
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(constr);
IDispatchEx_AddRef(_IDispatchEx_(constr));
return S_OK;
}
static HRESULT JSGlobal_NaN(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_Infinity(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_Array(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->array_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_Boolean(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->bool_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_Date(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_Function(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->function_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_Number(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->number_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_Object(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->object_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_String(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->string_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_RegExp(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("\n");
return constructor_call(dispex->ctx->regexp_constr, lcid, flags, dp, retv, ei, sp);
}
static HRESULT JSGlobal_ActiveXObject(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_VBArray(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_Enumerator(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_escape(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
/* ECMA-262 3rd Edition 15.1.2.1 */
static HRESULT JSGlobal_eval(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
parser_ctx_t *parser_ctx;
VARIANT *arg;
HRESULT hres;
TRACE("\n");
if(!arg_cnt(dp)) {
if(retv)
V_VT(retv) = VT_EMPTY;
return S_OK;
}
arg = get_arg(dp, 0);
if(V_VT(arg) != VT_BSTR) {
if(retv) {
V_VT(retv) = VT_EMPTY;
return VariantCopy(retv, arg);
}
return S_OK;
}
if(!dispex->ctx->exec_ctx) {
FIXME("No active exec_ctx\n");
return E_UNEXPECTED;
}
TRACE("parsing %s\n", debugstr_w(V_BSTR(arg)));
hres = script_parse(dispex->ctx, V_BSTR(arg), &parser_ctx);
if(FAILED(hres)) {
FIXME("parse failed: %08x\n", hres);
return hres;
}
hres = exec_source(dispex->ctx->exec_ctx, parser_ctx, parser_ctx->source, ei, retv);
parser_release(parser_ctx);
return hres;
}
static HRESULT JSGlobal_isNaN(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_isFinite(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_parseInt(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
return E_NOTIMPL;
}
static HRESULT JSGlobal_parseFloat(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_unescape(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_GetObject(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_ScriptEngine(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_ScriptEngineMajorVersion(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_ScriptEngineMinorVersion(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_ScriptEngineBuildVersion(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT JSGlobal_CollectGarbage(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static const builtin_prop_t JSGlobal_props[] = {
{ActiveXObjectW, JSGlobal_ActiveXObject, PROPF_METHOD},
{ArrayW, JSGlobal_Array, PROPF_CONSTR},
{BooleanW, JSGlobal_Boolean, PROPF_CONSTR},
{CollectGarbageW, JSGlobal_CollectGarbage, PROPF_METHOD},
{DateW, JSGlobal_Date, PROPF_CONSTR},
{EnumeratorW, JSGlobal_Enumerator, PROPF_METHOD},
{FunctionW, JSGlobal_Function, PROPF_CONSTR},
{getObjectW, JSGlobal_GetObject, PROPF_METHOD},
{InfinityW, JSGlobal_Infinity, 0},
/* {MathW, JSGlobal_Math, 0}, */
{NaNW, JSGlobal_NaN, 0},
{NumberW, JSGlobal_Number, PROPF_CONSTR},
{ObjectW, JSGlobal_Object, 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},
{VBArrayW, JSGlobal_VBArray, PROPF_METHOD},
{escapeW, JSGlobal_escape, PROPF_METHOD},
{evalW, JSGlobal_eval, PROPF_METHOD|1},
{isFiniteW, JSGlobal_isFinite, PROPF_METHOD},
{isNaNW, JSGlobal_isNaN, PROPF_METHOD},
{parseFloatW, JSGlobal_parseFloat, PROPF_METHOD},
{parseIntW, JSGlobal_parseInt, PROPF_METHOD|2},
{unescapeW, JSGlobal_unescape, PROPF_METHOD}
};
static const builtin_info_t JSGlobal_info = {
JSCLASS_GLOBAL,
{NULL, NULL, 0},
sizeof(JSGlobal_props)/sizeof(*JSGlobal_props),
JSGlobal_props,
NULL,
NULL
};
static HRESULT init_constructors(script_ctx_t *ctx)
{
HRESULT hres;
hres = init_function_constr(ctx);
if(FAILED(hres))
return hres;
hres = create_array_constr(ctx, &ctx->array_constr);
if(FAILED(hres))
return hres;
hres = create_bool_constr(ctx, &ctx->bool_constr);
if(FAILED(hres))
return hres;
hres = create_number_constr(ctx, &ctx->number_constr);
if(FAILED(hres))
return hres;
hres = create_object_constr(ctx, &ctx->object_constr);
if(FAILED(hres))
return hres;
hres = create_object_constr(ctx, &ctx->regexp_constr);
if(FAILED(hres))
return hres;
hres = create_string_constr(ctx, &ctx->string_constr);
if(FAILED(hres))
return hres;
return S_OK;
}
HRESULT init_global(script_ctx_t *ctx)
{
DispatchEx *math;
VARIANT var;
HRESULT hres;
if(ctx->global)
return S_OK;
hres = init_constructors(ctx);
if(FAILED(hres))
return hres;
hres = create_dispex(ctx, &JSGlobal_info, NULL, &ctx->global);
if(FAILED(hres))
return hres;
hres = create_math(ctx, &math);
if(FAILED(hres))
return hres;
V_VT(&var) = VT_DISPATCH;
V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(math);
hres = jsdisp_propput_name(ctx->global, MathW, ctx->lcid, &var, NULL/*FIXME*/, NULL/*FIXME*/);
jsdisp_release(math);
return hres;
}
+90 -7
View File
@@ -54,6 +54,7 @@ void script_release(script_ctx_t *ctx)
if(--ctx->ref)
return;
jsheap_free(&ctx->tmp_heap);
heap_free(ctx);
}
@@ -80,7 +81,7 @@ static HRESULT exec_global_code(JScript *This, parser_ctx_t *parser_ctx)
VARIANT var;
HRESULT hres;
hres = create_exec_ctx(&exec_ctx);
hres = create_exec_ctx((IDispatch*)_IDispatchEx_(This->ctx->script_disp), This->ctx->script_disp, NULL, &exec_ctx);
if(FAILED(hres))
return hres;
@@ -216,7 +217,13 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
return hres;
}
hres = create_dispex(This->ctx, &This->ctx->script_disp);
if(!This->ctx->script_disp) {
hres = create_dispex(This->ctx, NULL, NULL, &This->ctx->script_disp);
if(FAILED(hres))
return hres;
}
hres = init_global(This->ctx);
if(FAILED(hres))
return hres;
@@ -299,6 +306,21 @@ static HRESULT WINAPI JScript_Close(IActiveScript *iface)
clear_script_queue(This);
if(This->ctx->named_items) {
named_item_t *iter, *iter2;
iter = This->ctx->named_items;
while(iter) {
iter2 = iter->next;
IDispatch_Release(iter->disp);
heap_free(iter);
iter = iter2;
}
This->ctx->named_items = NULL;
}
if(This->ctx) {
change_state(This, SCRIPTSTATE_CLOSED);
@@ -306,6 +328,11 @@ static HRESULT WINAPI JScript_Close(IActiveScript *iface)
IDispatchEx_Release(_IDispatchEx_(This->ctx->script_disp));
This->ctx->script_disp = NULL;
}
if(This->ctx->global) {
IDispatchEx_Release(_IDispatchEx_(This->ctx->global));
This->ctx->global = NULL;
}
}
if(This->site) {
@@ -320,8 +347,41 @@ static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface,
LPCOLESTR pstrName, DWORD dwFlags)
{
JScript *This = ACTSCRIPT_THIS(iface);
FIXME("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
return E_NOTIMPL;
named_item_t *item;
IDispatch *disp;
IUnknown *unk;
HRESULT hres;
TRACE("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
if(This->thread_id != GetCurrentThreadId() || !This->ctx || This->ctx->state == SCRIPTSTATE_CLOSED)
return E_UNEXPECTED;
hres = IActiveScriptSite_GetItemInfo(This->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL);
if(FAILED(hres)) {
WARN("GetItemInfo failed: %08x\n", hres);
return hres;
}
hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
IUnknown_Release(unk);
if(FAILED(hres)) {
WARN("object does not implement IDispatch\n");
return hres;
}
item = heap_alloc(sizeof(*item));
if(!item) {
IDispatch_Release(disp);
return E_OUTOFMEMORY;
}
item->disp = disp;
item->flags = dwFlags;
item->next = This->ctx->named_items;
This->ctx->named_items = item;
return S_OK;
}
static HRESULT WINAPI JScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib,
@@ -448,6 +508,7 @@ static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
ctx->ref = 1;
ctx->state = SCRIPTSTATE_UNINITIALIZED;
jsheap_init(&ctx->tmp_heap);
ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL);
if(ctx) {
@@ -517,7 +578,7 @@ static const IActiveScriptParseVtbl JScriptParseVtbl = {
JScriptParse_ParseScriptText
};
#define ASPARSEPROC_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
#define ASPARSEPROC_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParseProcedure2, iface)
static HRESULT WINAPI JScriptParseProcedure_QueryInterface(IActiveScriptParseProcedure2 *iface, REFIID riid, void **ppv)
{
@@ -543,8 +604,30 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars
DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
{
JScript *This = ASPARSEPROC_THIS(iface);
FIXME("(%p)->()\n", This);
return E_NOTIMPL;
parser_ctx_t *parser_ctx;
DispatchEx *dispex;
HRESULT hres;
TRACE("(%p)->(%s %s %s %s %p %s %x %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams),
debugstr_w(pstrProcedureName), debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
dwSourceContextCookie, ulStartingLineNumber, dwFlags, ppdisp);
if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
return E_UNEXPECTED;
hres = script_parse(This->ctx, pstrCode, &parser_ctx);
if(FAILED(hres)) {
WARN("Parse failed %08x\n", hres);
return hres;
}
hres = create_source_function(parser_ctx, NULL, parser_ctx->source, NULL, &dispex);
parser_release(parser_ctx);
if(FAILED(hres))
return hres;
*ppdisp = (IDispatch*)_IDispatchEx_(dispex);
return S_OK;
}
#undef ASPARSEPROC_THIS
+169 -14
View File
@@ -33,32 +33,145 @@
typedef struct _script_ctx_t script_ctx_t;
typedef struct _exec_ctx_t exec_ctx_t;
typedef struct _dispex_prop_t dispex_prop_t;
typedef struct {
EXCEPINFO ei;
VARIANT var;
} jsexcept_t;
typedef struct DispatchEx {
typedef struct {
void **blocks;
DWORD block_cnt;
DWORD last_block;
DWORD offset;
BOOL mark;
struct list custom_blocks;
} jsheap_t;
void jsheap_init(jsheap_t*);
void *jsheap_alloc(jsheap_t*,DWORD);
void *jsheap_grow(jsheap_t*,void*,DWORD,DWORD);
void jsheap_clear(jsheap_t*);
void jsheap_free(jsheap_t*);
jsheap_t *jsheap_mark(jsheap_t*);
typedef struct DispatchEx DispatchEx;
#define PROPF_ARGMASK 0x00ff
#define PROPF_METHOD 0x0100
#define PROPF_ENUM 0x0200
#define PROPF_CONSTR 0x0400
typedef enum {
JSCLASS_NONE,
JSCLASS_ARRAY,
JSCLASS_BOOLEAN,
JSCLASS_FUNCTION,
JSCLASS_GLOBAL,
JSCLASS_MATH,
JSCLASS_NUMBER,
JSCLASS_OBJECT,
JSCLASS_REGEXP,
JSCLASS_STRING
} jsclass_t;
typedef HRESULT (*builtin_invoke_t)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
typedef struct {
const WCHAR *name;
builtin_invoke_t invoke;
DWORD flags;
} builtin_prop_t;
typedef struct {
jsclass_t class;
builtin_prop_t value_prop;
DWORD props_cnt;
const builtin_prop_t *props;
void (*destructor)(DispatchEx*);
void (*on_put)(DispatchEx*,const WCHAR*);
} builtin_info_t;
struct DispatchEx {
const IDispatchExVtbl *lpIDispatchExVtbl;
LONG ref;
DWORD buf_size;
DWORD prop_cnt;
dispex_prop_t *props;
script_ctx_t *ctx;
} DispatchEx;
DispatchEx *prototype;
const builtin_info_t *builtin_info;
};
#define _IDispatchEx_(x) ((IDispatchEx*) &(x)->lpIDispatchExVtbl)
HRESULT create_dispex(script_ctx_t*,DispatchEx**);
static inline void jsdisp_release(DispatchEx *jsdisp)
{
IDispatchEx_Release(_IDispatchEx_(jsdisp));
}
HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,DispatchEx*,DispatchEx**);
HRESULT init_dispex(DispatchEx*,script_ctx_t*,const builtin_info_t*,DispatchEx*);
HRESULT init_dispex_from_constr(DispatchEx*,script_ctx_t*,const builtin_info_t*,DispatchEx*);
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 disp_propget(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT disp_propput(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_propput_name(DispatchEx*,const WCHAR*,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT jsdisp_propput_idx(DispatchEx*,DWORD,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,DWORD,DispatchEx*,DispatchEx**);
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_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*);
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*);
HRESULT to_int32(script_ctx_t*,VARIANT*,jsexcept_t*,INT*);
HRESULT to_uint32(script_ctx_t*,VARIANT*,jsexcept_t*,DWORD*);
HRESULT to_string(script_ctx_t*,VARIANT*,jsexcept_t*,BSTR*);
HRESULT to_object(exec_ctx_t*,VARIANT*,IDispatch**);
typedef struct named_item_t {
IDispatch *disp;
DWORD flags;
struct named_item_t *next;
} named_item_t;
struct _script_ctx_t {
LONG ref;
SCRIPTSTATE state;
exec_ctx_t *exec_ctx;
named_item_t *named_items;
LCID lcid;
jsheap_t tmp_heap;
DispatchEx *script_disp;
DispatchEx *global;
DispatchEx *function_constr;
DispatchEx *array_constr;
DispatchEx *bool_constr;
DispatchEx *number_constr;
DispatchEx *object_constr;
DispatchEx *regexp_constr;
DispatchEx *string_constr;
};
void script_release(script_ctx_t*);
@@ -68,20 +181,47 @@ static inline void script_addref(script_ctx_t *ctx)
ctx->ref++;
}
HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**);
HRESULT init_global(script_ctx_t*);
HRESULT init_function_constr(script_ctx_t*);
HRESULT create_array_constr(script_ctx_t*,DispatchEx**);
HRESULT create_bool_constr(script_ctx_t*,DispatchEx**);
HRESULT create_number_constr(script_ctx_t*,DispatchEx**);
HRESULT create_object_constr(script_ctx_t*,DispatchEx**);
HRESULT create_regexp_constr(script_ctx_t*,DispatchEx**);
HRESULT create_string_constr(script_ctx_t*,DispatchEx**);
typedef struct {
void **blocks;
DWORD block_cnt;
DWORD last_block;
DWORD offset;
struct list custom_blocks;
} jsheap_t;
const WCHAR *str;
DWORD len;
} match_result_t;
void jsheap_init(jsheap_t*);
void *jsheap_alloc(jsheap_t*,DWORD);
void jsheap_clear(jsheap_t*);
void jsheap_free(jsheap_t*);
HRESULT regexp_match(DispatchEx*,const WCHAR*,DWORD,BOOL,match_result_t**,DWORD*);
static inline VARIANT *get_arg(DISPPARAMS *dp, DWORD i)
{
return dp->rgvarg + dp->cArgs-i-1;
}
static inline DWORD arg_cnt(const DISPPARAMS *dp)
{
return dp->cArgs - dp->cNamedArgs;
}
static inline void num_set_val(VARIANT *v, DOUBLE d)
{
if(d == (DOUBLE)(INT)d) {
V_VT(v) = VT_I4;
V_I4(v) = d;
}else {
V_VT(v) = VT_R8;
V_R8(v) = d;
}
}
const char *debugstr_variant(const VARIANT*);
HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**);
extern LONG module_ref;
@@ -115,4 +255,19 @@ static inline BOOL heap_free(void *mem)
return HeapFree(GetProcessHeap(), 0, mem);
}
static inline LPWSTR heap_strdupW(LPCWSTR str)
{
LPWSTR ret = NULL;
if(str) {
DWORD size;
size = (strlenW(str)+1)*sizeof(WCHAR);
ret = heap_alloc(size);
memcpy(ret, str, size);
}
return ret;
}
#define DEFINE_THIS(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,lp ## ifc ## Vtbl)))
+10 -1
View File
@@ -1,5 +1,5 @@
<group>
<module name="jscript" type="win32dll" baseaddress="${BASEADDRESS_JSCRIPT}" installbase="system32" installname="jscript.dll">
<module name="jscript" type="win32dll" baseaddress="${BASEADDRESS_JSCRIPT}" installbase="system32" installname="jscript.dll" allowwarnings="true">
<autoregister infsection="OleControlDlls" type="DllRegisterServer" />
<importlibrary definition="jscript.spec.def" />
<include base="jscript">.</include>
@@ -21,6 +21,15 @@
<file>jsutils.c</file>
<file>lex.c</file>
<file>parser.tab.c</file>
<file>math.c</file>
<file>number.c</file>
<file>object.c</file>
<file>regexp.c</file>
<file>string.c</file>
<file>array.c</file>
<file>bool.c</file>
<file>function.c</file>
<file>global.c</file>
<file>rsrc.rc</file>
<file>jscript.spec</file>
</module>
+2
View File
@@ -38,6 +38,8 @@ static const CLSID CLSID_JScriptAuthor =
static const CLSID CLSID_JScriptEncode =
{0xf414c262,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}};
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
static HINSTANCE jscript_hinstance;
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
+291
View File
@@ -16,12 +16,37 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <math.h>
#include "jscript.h"
#include "engine.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
const char *debugstr_variant(const VARIANT *v)
{
switch(V_VT(v)) {
case VT_EMPTY:
return wine_dbg_sprintf("{VT_EMPTY}");
case VT_NULL:
return wine_dbg_sprintf("{VT_NULL}");
case VT_I4:
return wine_dbg_sprintf("{VT_I4: %d}", V_I4(v));
case VT_R8:
return wine_dbg_sprintf("{VT_R8: %lf}", V_R8(v));
case VT_BSTR:
return wine_dbg_sprintf("{VT_BSTR: %s}", debugstr_w(V_BSTR(v)));
case VT_DISPATCH:
return wine_dbg_sprintf("{VT_DISPATCH: %p}", V_DISPATCH(v));
case VT_BOOL:
return wine_dbg_sprintf("{VT_BOOL: %x}", V_BOOL(v));
default:
return wine_dbg_sprintf("{vt %d}", V_VT(v));
}
}
#define MIN_BLOCK_SIZE 128
static inline DWORD block_size(DWORD block)
@@ -88,14 +113,30 @@ void *jsheap_alloc(jsheap_t *heap, DWORD size)
return list+1;
}
void *jsheap_grow(jsheap_t *heap, void *mem, DWORD size, DWORD inc)
{
if(mem == (BYTE*)heap->blocks[heap->last_block] + heap->offset-size
&& heap->offset+inc < block_size(heap->last_block)) {
heap->offset += inc;
return mem;
}
return jsheap_alloc(heap, size+inc);
}
void jsheap_clear(jsheap_t *heap)
{
struct list *tmp;
if(!heap)
return;
while((tmp = list_next(&heap->custom_blocks, &heap->custom_blocks))) {
list_remove(tmp);
heap_free(tmp);
}
heap->last_block = heap->offset = 0;
}
void jsheap_free(jsheap_t *heap)
@@ -110,3 +151,253 @@ void jsheap_free(jsheap_t *heap)
jsheap_init(heap);
}
jsheap_t *jsheap_mark(jsheap_t *heap)
{
if(heap->mark)
return NULL;
heap->mark = TRUE;
return heap;
}
/* ECMA-262 3rd Edition 9.1 */
HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
{
switch(V_VT(v)) {
case VT_EMPTY:
case VT_NULL:
case VT_BOOL:
case VT_I4:
case VT_R8:
*ret = *v;
break;
case VT_BSTR:
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*/);
default:
FIXME("Unimplemented for vt %d\n", V_VT(v));
return E_NOTIMPL;
}
return S_OK;
}
/* ECMA-262 3rd Edition 9.2 */
HRESULT to_boolean(VARIANT *v, VARIANT_BOOL *b)
{
switch(V_VT(v)) {
case VT_EMPTY:
case VT_NULL:
*b = VARIANT_FALSE;
break;
case VT_I4:
*b = V_I4(v) ? VARIANT_TRUE : VARIANT_FALSE;
break;
case VT_R8:
*b = V_R8(v) ? VARIANT_TRUE : VARIANT_FALSE;
break;
case VT_BSTR:
*b = V_BSTR(v) && *V_BSTR(v) ? VARIANT_TRUE : VARIANT_FALSE;
break;
case VT_DISPATCH:
*b = V_DISPATCH(v) ? VARIANT_TRUE : VARIANT_FALSE;
break;
case VT_BOOL:
*b = V_BOOL(v);
break;
default:
FIXME("unimplemented for vt %d\n", V_VT(v));
return E_NOTIMPL;
}
return S_OK;
}
/* ECMA-262 3rd Edition 9.3 */
HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
{
switch(V_VT(v)) {
case VT_NULL:
V_VT(ret) = VT_I4;
V_I4(ret) = 0;
break;
case VT_I4:
case VT_R8:
*ret = *v;
break;
case VT_BOOL:
V_VT(ret) = VT_I4;
V_I4(ret) = V_BOOL(v) ? 1 : 0;
break;
default:
FIXME("unimplemented for vt %d\n", V_VT(v));
return E_NOTIMPL;
}
return S_OK;
}
/* ECMA-262 3rd Edition 9.4 */
HRESULT to_integer(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
{
VARIANT num;
HRESULT hres;
hres = to_number(ctx, v, ei, &num);
if(FAILED(hres))
return hres;
if(V_VT(&num) == VT_I4)
*ret = *v;
else
num_set_val(ret, V_R8(&num) >= 0.0 ? floor(V_R8(&num)) : -floor(-V_R8(&num)));
return S_OK;
}
/* ECMA-262 3rd Edition 9.5 */
HRESULT to_int32(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, INT *ret)
{
VARIANT num;
HRESULT hres;
hres = to_number(ctx, v, ei, &num);
if(FAILED(hres))
return hres;
*ret = V_VT(&num) == VT_I4 ? V_I4(&num) : (INT)V_R8(&num);
return S_OK;
}
/* ECMA-262 3rd Edition 9.6 */
HRESULT to_uint32(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, DWORD *ret)
{
VARIANT num;
HRESULT hres;
hres = to_number(ctx, v, ei, &num);
if(FAILED(hres))
return hres;
*ret = V_VT(&num) == VT_I4 ? V_I4(&num) : (DWORD)V_R8(&num);
return S_OK;
}
static BSTR int_to_bstr(INT i)
{
WCHAR buf[12], *p;
BOOL neg = FALSE;
if(!i) {
static const WCHAR zeroW[] = {'0',0};
return SysAllocString(zeroW);
}
if(i < 0) {
neg = TRUE;
i = -i;
}
p = buf + sizeof(buf)/sizeof(*buf)-1;
*p-- = 0;
while(i) {
*p-- = i%10 + '0';
i /= 10;
}
if(neg)
*p = '-';
else
p++;
return SysAllocString(p);
}
/* ECMA-262 3rd Edition 9.8 */
HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
{
const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
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};
switch(V_VT(v)) {
case VT_EMPTY:
*str = SysAllocString(undefinedW);
break;
case VT_NULL:
*str = SysAllocString(nullW);
break;
case VT_I4:
*str = int_to_bstr(V_I4(v));
break;
case VT_BSTR:
*str = SysAllocString(V_BSTR(v));
break;
case VT_DISPATCH: {
VARIANT prim;
HRESULT hres;
hres = to_primitive(ctx, v, ei, &prim);
if(FAILED(hres))
return hres;
hres = to_string(ctx, &prim, ei, str);
VariantClear(&prim);
return hres;
}
case VT_BOOL:
*str = SysAllocString(V_BOOL(v) ? trueW : falseW);
break;
default:
FIXME("unsupported vt %d\n", V_VT(v));
return E_NOTIMPL;
}
return *str ? S_OK : E_OUTOFMEMORY;
}
/* ECMA-262 3rd Edition 9.9 */
HRESULT to_object(exec_ctx_t *ctx, VARIANT *v, IDispatch **disp)
{
DispatchEx *dispex;
HRESULT hres;
switch(V_VT(v)) {
case VT_BSTR:
hres = create_string(ctx->parser->script, V_BSTR(v), SysStringLen(V_BSTR(v)), &dispex);
if(FAILED(hres))
return hres;
*disp = (IDispatch*)_IDispatchEx_(dispex);
break;
case VT_I4:
case VT_R8:
hres = create_number(ctx->parser->script, v, &dispex);
if(FAILED(hres))
return hres;
*disp = (IDispatch*)_IDispatchEx_(dispex);
break;
case VT_DISPATCH:
IDispatch_AddRef(V_DISPATCH(v));
*disp = V_DISPATCH(v);
break;
case VT_BOOL:
hres = create_bool(ctx->parser->script, V_BOOL(v), &dispex);
if(FAILED(hres))
return hres;
*disp = (IDispatch*)_IDispatchEx_(dispex);
break;
default:
FIXME("unsupported vt %d\n", V_VT(v));
return E_NOTIMPL;
}
return S_OK;
}
+47 -2
View File
@@ -23,7 +23,6 @@
#include "objsafe.h"
#include "engine.h"
#define YYSTYPE
#include "parser.tab.h"
#include "wine/debug.h"
@@ -667,7 +666,7 @@ int parser_lex(void *lval, parser_ctx_t *ctx)
if(++ctx->ptr < ctx->end) {
if(*ctx->ptr == '=') { /* /= */
ctx->ptr++;
*(int*)lval = EXPR_ASSIGNMUL;
*(int*)lval = EXPR_ASSIGNDIV;
return tAssignOper;
}
}
@@ -685,3 +684,49 @@ int parser_lex(void *lval, parser_ctx_t *ctx)
WARN("unexpected char '%c' %d\n", *ctx->ptr, *ctx->ptr);
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;
literal_t *ret;
DWORD re_len;
HRESULT hres;
TRACE("\n");
re = ctx->ptr;
while(ctx->ptr < ctx->end && (*ctx->ptr != '/' || *(ctx->ptr-1) == '\\'))
ctx->ptr++;
if(ctx->ptr == ctx->end) {
WARN("unexpected end of file\n");
return NULL;
}
re_len = ctx->ptr-re;
flags = ++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);
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);
return ret;
}
+275
View File
@@ -0,0 +1,275 @@
/*
* Copyright 2008 Jacek Caban for CodeWeavers
*
* 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 "jscript.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
static const WCHAR EW[] = {'E',0};
static const WCHAR LOG2EW[] = {'L','O','G','2','E',0};
static const WCHAR LOG10EW[] = {'L','O','G','1','0',0};
static const WCHAR LN2W[] = {'L','N','2',0};
static const WCHAR LN10W[] = {'L','N','1','0',0};
static const WCHAR PIW[] = {'P','I',0};
static const WCHAR SQRT2W[] = {'S','Q','R','T','2',0};
static const WCHAR SQRT1_2W[] = {'S','Q','R','T','1','_','2',0};
static const WCHAR absW[] = {'a','b','s',0};
static const WCHAR acosW[] = {'a','c','o','s',0};
static const WCHAR asinW[] = {'a','s','i','n',0};
static const WCHAR atanW[] = {'a','t','a','n',0};
static const WCHAR atan2W[] = {'a','t','a','n','2',0};
static const WCHAR ceilW[] = {'c','e','i','l',0};
static const WCHAR cosW[] = {'c','o','s',0};
static const WCHAR expW[] = {'e','x','p',0};
static const WCHAR floorW[] = {'f','l','o','o','r',0};
static const WCHAR logW[] = {'l','o','g',0};
static const WCHAR maxW[] = {'m','a','x',0};
static const WCHAR minW[] = {'m','i','n',0};
static const WCHAR powW[] = {'p','o','w',0};
static const WCHAR randomW[] = {'r','a','n','d','o','m',0};
static const WCHAR roundW[] = {'r','o','u','n','d',0};
static const WCHAR sinW[] = {'s','i','n',0};
static const WCHAR sqrtW[] = {'s','q','r','t',0};
static const WCHAR tanW[] = {'t','a','n',0};
static HRESULT Math_E(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_LOG2E(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_LOG10E(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_LN2(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_LN10(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_PI(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_SQRT2(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_SQRT1_2(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_abs(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_acos(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_asin(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_atan(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_atan2(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_ceil(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_cos(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_exp(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_floor(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_log(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_max(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_min(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_pow(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_random(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_round(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_sin(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_sqrt(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Math_tan(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static const builtin_prop_t Math_props[] = {
{EW, Math_E, 0},
{LOG2EW, Math_LOG2E, 0},
{LOG10EW, Math_LOG10E, 0},
{LN2W, Math_LN2, 0},
{LN10W, Math_LN10, 0},
{PIW, Math_PI, 0},
{SQRT1_2W, Math_SQRT1_2, 0},
{SQRT2W, Math_SQRT2, 0},
{absW, Math_abs, PROPF_METHOD},
{acosW, Math_acos, PROPF_METHOD},
{asinW, Math_asin, PROPF_METHOD},
{atanW, Math_atan, PROPF_METHOD},
{atan2W, Math_atan2, PROPF_METHOD},
{ceilW, Math_ceil, PROPF_METHOD},
{cosW, Math_cos, PROPF_METHOD},
{expW, Math_exp, PROPF_METHOD},
{floorW, Math_floor, PROPF_METHOD},
{logW, Math_log, PROPF_METHOD},
{maxW, Math_max, PROPF_METHOD},
{minW, Math_min, PROPF_METHOD},
{powW, Math_pow, PROPF_METHOD},
{randomW, Math_random, PROPF_METHOD},
{roundW, Math_round, PROPF_METHOD},
{sinW, Math_sin, PROPF_METHOD},
{sqrtW, Math_sqrt, PROPF_METHOD},
{tanW, Math_tan, PROPF_METHOD}
};
static const builtin_info_t Math_info = {
JSCLASS_MATH,
{NULL, NULL, 0},
sizeof(Math_props)/sizeof(*Math_props),
Math_props,
NULL,
NULL
};
HRESULT create_math(script_ctx_t *ctx, DispatchEx **ret)
{
return create_dispex(ctx, &Math_info, NULL, ret);
}
+184
View File
@@ -0,0 +1,184 @@
/*
* Copyright 2008 Jacek Caban for CodeWeavers
*
* 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 "jscript.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
typedef struct {
DispatchEx dispex;
VARIANT num;
} NumberInstance;
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 toFixedW[] = {'t','o','F','i','x','e','d',0};
static const WCHAR toExponentialW[] = {'t','o','E','x','p','o','n','e','n','t','i','a','l',0};
static const WCHAR toPrecisionW[] = {'t','o','P','r','e','c','i','s','i','o','n',0};
static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',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 Number_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Number_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Number_toFixed(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Number_toExponential(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Number_toPrecision(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Number_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Number_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Number_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Number_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Number_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static const builtin_prop_t Number_props[] = {
{hasOwnPropertyW, Number_hasOwnProperty, PROPF_METHOD},
{isPrototypeOfW, Number_isPrototypeOf, PROPF_METHOD},
{propertyIsEnumerableW, Number_propertyIsEnumerable, PROPF_METHOD},
{toExponentialW, Number_toExponential, PROPF_METHOD},
{toFixedW, Number_toFixed, PROPF_METHOD},
{toLocaleStringW, Number_toLocaleString, PROPF_METHOD},
{toPrecisionW, Number_toPrecision, PROPF_METHOD},
{toStringW, Number_toString, PROPF_METHOD},
{valueOfW, Number_valueOf, PROPF_METHOD}
};
static const builtin_info_t Number_info = {
JSCLASS_NUMBER,
{NULL, Number_value, 0},
sizeof(Number_props)/sizeof(*Number_props),
Number_props,
NULL,
NULL
};
static HRESULT NumberConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT alloc_number(script_ctx_t *ctx, BOOL use_constr, NumberInstance **ret)
{
NumberInstance *number = heap_alloc_zero(sizeof(NumberInstance));
HRESULT hres;
if(use_constr)
hres = init_dispex_from_constr(&number->dispex, ctx, &Number_info, ctx->number_constr);
else
hres = init_dispex(&number->dispex, ctx, &Number_info, NULL);
if(FAILED(hres))
return hres;
*ret = number;
return S_OK;
}
HRESULT create_number_constr(script_ctx_t *ctx, DispatchEx **ret)
{
NumberInstance *number;
HRESULT hres;
hres = alloc_number(ctx, FALSE, &number);
if(FAILED(hres))
return hres;
hres = create_builtin_function(ctx, NumberConstr_value, PROPF_CONSTR, &number->dispex, ret);
jsdisp_release(&number->dispex);
return hres;
}
HRESULT create_number(script_ctx_t *ctx, VARIANT *num, DispatchEx **ret)
{
NumberInstance *number;
HRESULT hres;
hres = alloc_number(ctx, TRUE, &number);
if(FAILED(hres))
return hres;
number->num = *num;
*ret = &number->dispex;
return S_OK;
}
+165
View File
@@ -0,0 +1,165 @@
/*
* Copyright 2008 Jacek Caban for CodeWeavers
*
* 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 "jscript.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
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 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 Object_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Object_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Object_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Object_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Object_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Object_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT Object_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static void Object_destructor(DispatchEx *dispex)
{
heap_free(dispex);
}
static const builtin_prop_t Object_props[] = {
{hasOwnPropertyW, Object_hasOwnProperty, PROPF_METHOD},
{isPrototypeOfW, Object_isPrototypeOf, PROPF_METHOD},
{propertyIsEnumerableW, Object_propertyIsEnumerable, PROPF_METHOD},
{toLocaleStringW, Object_toLocaleString, PROPF_METHOD},
{toStringW, Object_toString, PROPF_METHOD},
{valueOfW, Object_valueOf, PROPF_METHOD}
};
static const builtin_info_t Object_info = {
JSCLASS_OBJECT,
{NULL, Object_value, 0},
sizeof(Object_props)/sizeof(*Object_props),
Object_props,
Object_destructor,
NULL
};
static HRESULT ObjectConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
HRESULT hres;
TRACE("\n");
switch(flags) {
case DISPATCH_CONSTRUCT: {
DispatchEx *obj;
hres = create_object(dispex->ctx, NULL, &obj);
if(FAILED(hres))
return hres;
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj);
break;
}
default:
FIXME("unimplemented flags: %x\n", flags);
return E_NOTIMPL;
}
return S_OK;
}
HRESULT create_object_constr(script_ctx_t *ctx, DispatchEx **ret)
{
DispatchEx *object;
HRESULT hres;
hres = create_dispex(ctx, &Object_info, NULL, &object);
if(FAILED(hres))
return hres;
hres = create_builtin_function(ctx, ObjectConstr_value, PROPF_CONSTR, object, ret);
jsdisp_release(object);
return hres;
}
HRESULT create_object(script_ctx_t *ctx, DispatchEx *constr, DispatchEx **ret)
{
DispatchEx *object;
HRESULT hres;
object = heap_alloc_zero(sizeof(DispatchEx));
if(!object)
return E_OUTOFMEMORY;
hres = init_dispex_from_constr(object, ctx, &Object_info, constr ? constr : ctx->object_constr);
if(FAILED(hres)) {
heap_free(object);
return hres;
}
*ret = object;
return S_OK;
}
+44 -37
View File
@@ -169,7 +169,7 @@ static int parser_error(const char*);
static BOOL allow_auto_semicolon(parser_ctx_t*);
static void program_parsed(parser_ctx_t*,source_elements_t*);
typedef struct {
typedef struct _statement_list_t {
statement_t *head;
statement_t *tail;
} statement_list_t;
@@ -179,7 +179,7 @@ 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 {
typedef struct _property_list_t {
prop_val_t *head;
prop_val_t *tail;
} property_list_t;
@@ -187,7 +187,7 @@ typedef struct {
static property_list_t *new_property_list(parser_ctx_t*,literal_t*,expression_t*);
static property_list_t *property_list_add(parser_ctx_t*,property_list_t*,literal_t*,expression_t*);
typedef struct {
typedef struct _element_list_t {
array_element_t *head;
array_element_t *tail;
} element_list_t;
@@ -195,7 +195,7 @@ typedef struct {
static element_list_t *new_element_list(parser_ctx_t*,int,expression_t*);
static element_list_t *element_list_add(parser_ctx_t*,element_list_t*,int,expression_t*);
typedef struct {
typedef struct _argument_list_t {
argument_t *head;
argument_t *tail;
} argument_list_t;
@@ -203,7 +203,7 @@ typedef struct {
static argument_list_t *new_argument_list(parser_ctx_t*,expression_t*);
static argument_list_t *argument_list_add(parser_ctx_t*,argument_list_t*,expression_t*);
typedef struct {
typedef struct _case_list_t {
case_clausule_t *head;
case_clausule_t *tail;
} case_list_t;
@@ -214,7 +214,7 @@ static case_list_t *new_case_list(parser_ctx_t*,case_clausule_t*);
static case_list_t *case_list_add(parser_ctx_t*,case_list_t*,case_clausule_t*);
static case_clausule_t *new_case_block(parser_ctx_t*,case_list_t*,case_clausule_t*,case_list_t*);
typedef struct {
typedef struct _variable_list_t {
variable_declaration_t *head;
variable_declaration_t *tail;
} variable_list_t;
@@ -249,7 +249,7 @@ struct statement_list_t {
statement_list_t *new_statement_list(parser_ctx_t*,statement_t*);
statement_list_t *statement_list_add(statement_list_t*,statement_t*);
typedef struct {
typedef struct _parameter_list_t {
parameter_t *head;
parameter_t *tail;
} parameter_list_t;
@@ -263,7 +263,7 @@ static expression_t *new_unary_expression(parser_ctx_t*,expression_type_t,expres
static expression_t *new_conditional_expression(parser_ctx_t*,expression_t*,expression_t*,expression_t*);
static expression_t *new_array_expression(parser_ctx_t*,expression_t*,expression_t*);
static expression_t *new_member_expression(parser_ctx_t*,expression_t*,const WCHAR*);
static expression_t *new_member_new_expression(parser_ctx_t*,expression_t*,argument_list_t*);
static expression_t *new_new_expression(parser_ctx_t*,expression_t*,argument_list_t*);
static expression_t *new_call_expression(parser_ctx_t*,expression_t*,argument_list_t*);
static expression_t *new_this_expression(parser_ctx_t*);
static expression_t *new_identifier_expression(parser_ctx_t*,const WCHAR*);
@@ -302,20 +302,20 @@ typedef union YYSTYPE {
int ival;
LPCWSTR wstr;
literal_t *literal;
argument_list_t *argument_list;
struct _argument_list_t *argument_list;
case_clausule_t *case_clausule;
case_list_t *case_list;
struct _case_list_t *case_list;
catch_block_t *catch_block;
element_list_t *element_list;
struct _element_list_t *element_list;
expression_t *expr;
const WCHAR *identifier;
function_declaration_t *function_declaration;
parameter_list_t *parameter_list;
property_list_t *property_list;
struct _parameter_list_t *parameter_list;
struct _property_list_t *property_list;
source_elements_t *source_elements;
statement_t *statement;
statement_list_t *statement_list;
variable_list_t *variable_list;
struct _statement_list_t *statement_list;
struct _variable_list_t *variable_list;
variable_declaration_t *variable_declaration;
} YYSTYPE;
/* Line 196 of yacc.c. */
@@ -652,7 +652,7 @@ static const unsigned short int yyrline[] =
706, 710, 711, 716, 717, 718, 719, 720, 721, 725,
726, 727, 732, 734, 739, 740, 744, 745, 749, 750,
755, 757, 762, 763, 764, 768, 769, 773, 774, 775,
776, 777, 778, 782, 783, 786, 787
776, 777, 778, 783, 784, 787, 788
};
#endif
@@ -2279,7 +2279,7 @@ yyreduce:
case 106:
#line 569 "parser.y"
{ new_binary_expression(ctx, EXPR_BXOR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
{ (yyval.expr) = new_binary_expression(ctx, EXPR_BXOR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
break;
case 107:
@@ -2289,7 +2289,7 @@ yyreduce:
case 108:
#line 576 "parser.y"
{ new_binary_expression(ctx, EXPR_BXOR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
{ (yyval.expr) = new_binary_expression(ctx, EXPR_BXOR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
break;
case 109:
@@ -2299,7 +2299,7 @@ yyreduce:
case 110:
#line 582 "parser.y"
{ new_binary_expression(ctx, EXPR_BAND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
{ (yyval.expr) = new_binary_expression(ctx, EXPR_BAND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
break;
case 111:
@@ -2309,7 +2309,7 @@ yyreduce:
case 112:
#line 589 "parser.y"
{ new_binary_expression(ctx, EXPR_BAND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
{ (yyval.expr) = new_binary_expression(ctx, EXPR_BAND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
break;
case 113:
@@ -2494,7 +2494,7 @@ yyreduce:
case 149:
#line 679 "parser.y"
{ (yyval.expr) = new_unary_expression(ctx, EXPR_NEW, (yyvsp[0].expr)); ;}
{ (yyval.expr) = new_new_expression(ctx, (yyvsp[0].expr), NULL); ;}
break;
case 150:
@@ -2519,7 +2519,7 @@ yyreduce:
case 154:
#line 690 "parser.y"
{ (yyval.expr) = new_member_new_expression(ctx, (yyvsp[-1].expr), (yyvsp[0].argument_list)); ;}
{ (yyval.expr) = new_new_expression(ctx, (yyvsp[-1].expr), (yyvsp[0].argument_list)); ;}
break;
case 155:
@@ -2709,21 +2709,22 @@ yyreduce:
case 192:
#line 778 "parser.y"
{ FIXME("RegExp literal\n"); YYABORT; ;}
{ (yyval.literal) = parse_regexp(ctx);
if(!(yyval.literal)) YYABORT; ;}
break;
case 193:
#line 782 "parser.y"
#line 783 "parser.y"
{ (yyval.literal) = new_boolean_literal(ctx, TRUE); ;}
break;
case 194:
#line 783 "parser.y"
#line 784 "parser.y"
{ (yyval.literal) = new_boolean_literal(ctx, FALSE); ;}
break;
case 196:
#line 787 "parser.y"
#line 788 "parser.y"
{ if(!allow_auto_semicolon(ctx)) {YYABORT;} ;}
break;
@@ -2732,7 +2733,7 @@ yyreduce:
}
/* Line 1126 of yacc.c. */
#line 2736 "parser.tab.c"
#line 2737 "parser.tab.c"
yyvsp -= yylen;
yyssp -= yylen;
@@ -3000,7 +3001,7 @@ yyreturn:
}
#line 789 "parser.y"
#line 790 "parser.y"
static BOOL allow_auto_semicolon(parser_ctx_t *ctx)
@@ -3191,14 +3192,14 @@ static case_clausule_t *new_case_block(parser_ctx_t *ctx, case_list_t *case_list
if(!ret)
return NULL;
for(iter = ret->next; iter->next; iter = iter->next) {
for(iter2 = iter; iter2 && !iter2->expr; iter2 = iter2->next);
for(iter = ret; iter; iter = iter->next) {
for(iter2 = iter; iter2 && !iter2->stat; iter2 = iter2->next);
if(!iter2)
break;
while(iter != iter2) {
iter->stat = iter2->stat;
iter2 = iter2->next;
iter = iter->next;
}
if(stat) {
@@ -3300,8 +3301,9 @@ static statement_t *new_while_statement(parser_ctx_t *ctx, BOOL dowhile, express
{
while_statement_t *ret = parser_alloc(ctx, sizeof(while_statement_t));
ret->stat.eval = dowhile ? dowhile_statement_eval : while_statement_eval;
ret->stat.eval = while_statement_eval;
ret->stat.next = NULL;
ret->do_while = dowhile;
ret->expr = expr;
ret->statement = stat;
@@ -3495,7 +3497,6 @@ static const expression_eval_t expression_eval_table[] = {
post_decrement_expression_eval,
pre_increment_expression_eval,
pre_decrement_expression_eval,
new_expression_eval,
equal_expression_eval,
equal2_expression_eval,
not_equal_expression_eval,
@@ -3580,11 +3581,11 @@ static expression_t *new_member_expression(parser_ctx_t *ctx, expression_t *expr
return &ret->expr;
}
static expression_t *new_member_new_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list)
static expression_t *new_new_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list)
{
call_expression_t *ret = parser_alloc(ctx, sizeof(call_expression_t));
ret->expr.eval = member_new_expression_eval;
ret->expr.eval = new_expression_eval;
ret->expression = expression;
ret->argument_list = argument_list ? argument_list->head : NULL;
@@ -3724,9 +3725,14 @@ 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);
jsheap_free(&ctx->heap);
heap_free(ctx);
}
@@ -3734,6 +3740,7 @@ void parser_release(parser_ctx_t *ctx)
HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, parser_ctx_t **ret)
{
parser_ctx_t *parser_ctx;
jsheap_t *mark;
HRESULT hres;
parser_ctx = heap_alloc_zero(sizeof(parser_ctx_t));
@@ -3749,11 +3756,11 @@ HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, parser_ctx_t **ret)
script_addref(ctx);
parser_ctx->script = ctx;
jsheap_init(&parser_ctx->tmp_heap);
mark = jsheap_mark(&ctx->tmp_heap);
jsheap_init(&parser_ctx->heap);
parser_parse(parser_ctx);
jsheap_free(&parser_ctx->tmp_heap);
jsheap_clear(mark);
if(FAILED(parser_ctx->hres)) {
hres = parser_ctx->hres;
parser_release(parser_ctx);
+7 -7
View File
@@ -122,20 +122,20 @@ typedef union YYSTYPE {
int ival;
LPCWSTR wstr;
literal_t *literal;
argument_list_t *argument_list;
struct _argument_list_t *argument_list;
case_clausule_t *case_clausule;
case_list_t *case_list;
struct _case_list_t *case_list;
catch_block_t *catch_block;
element_list_t *element_list;
struct _element_list_t *element_list;
expression_t *expr;
const WCHAR *identifier;
function_declaration_t *function_declaration;
parameter_list_t *parameter_list;
property_list_t *property_list;
struct _parameter_list_t *parameter_list;
struct _property_list_t *property_list;
source_elements_t *source_elements;
statement_t *statement;
statement_list_t *statement_list;
variable_list_t *variable_list;
struct _statement_list_t *statement_list;
struct _variable_list_t *variable_list;
variable_declaration_t *variable_declaration;
} YYSTYPE;
/* Line 1447 of yacc.c. */
+38 -31
View File
@@ -32,7 +32,7 @@ static int parser_error(const char*);
static BOOL allow_auto_semicolon(parser_ctx_t*);
static void program_parsed(parser_ctx_t*,source_elements_t*);
typedef struct {
typedef struct _statement_list_t {
statement_t *head;
statement_t *tail;
} statement_list_t;
@@ -42,7 +42,7 @@ 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 {
typedef struct _property_list_t {
prop_val_t *head;
prop_val_t *tail;
} property_list_t;
@@ -50,7 +50,7 @@ typedef struct {
static property_list_t *new_property_list(parser_ctx_t*,literal_t*,expression_t*);
static property_list_t *property_list_add(parser_ctx_t*,property_list_t*,literal_t*,expression_t*);
typedef struct {
typedef struct _element_list_t {
array_element_t *head;
array_element_t *tail;
} element_list_t;
@@ -58,7 +58,7 @@ typedef struct {
static element_list_t *new_element_list(parser_ctx_t*,int,expression_t*);
static element_list_t *element_list_add(parser_ctx_t*,element_list_t*,int,expression_t*);
typedef struct {
typedef struct _argument_list_t {
argument_t *head;
argument_t *tail;
} argument_list_t;
@@ -66,7 +66,7 @@ typedef struct {
static argument_list_t *new_argument_list(parser_ctx_t*,expression_t*);
static argument_list_t *argument_list_add(parser_ctx_t*,argument_list_t*,expression_t*);
typedef struct {
typedef struct _case_list_t {
case_clausule_t *head;
case_clausule_t *tail;
} case_list_t;
@@ -77,7 +77,7 @@ static case_list_t *new_case_list(parser_ctx_t*,case_clausule_t*);
static case_list_t *case_list_add(parser_ctx_t*,case_list_t*,case_clausule_t*);
static case_clausule_t *new_case_block(parser_ctx_t*,case_list_t*,case_clausule_t*,case_list_t*);
typedef struct {
typedef struct _variable_list_t {
variable_declaration_t *head;
variable_declaration_t *tail;
} variable_list_t;
@@ -112,7 +112,7 @@ struct statement_list_t {
statement_list_t *new_statement_list(parser_ctx_t*,statement_t*);
statement_list_t *statement_list_add(statement_list_t*,statement_t*);
typedef struct {
typedef struct _parameter_list_t {
parameter_t *head;
parameter_t *tail;
} parameter_list_t;
@@ -126,7 +126,7 @@ static expression_t *new_unary_expression(parser_ctx_t*,expression_type_t,expres
static expression_t *new_conditional_expression(parser_ctx_t*,expression_t*,expression_t*,expression_t*);
static expression_t *new_array_expression(parser_ctx_t*,expression_t*,expression_t*);
static expression_t *new_member_expression(parser_ctx_t*,expression_t*,const WCHAR*);
static expression_t *new_member_new_expression(parser_ctx_t*,expression_t*,argument_list_t*);
static expression_t *new_new_expression(parser_ctx_t*,expression_t*,argument_list_t*);
static expression_t *new_call_expression(parser_ctx_t*,expression_t*,argument_list_t*);
static expression_t *new_this_expression(parser_ctx_t*);
static expression_t *new_identifier_expression(parser_ctx_t*,const WCHAR*);
@@ -148,20 +148,20 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi
int ival;
LPCWSTR wstr;
literal_t *literal;
argument_list_t *argument_list;
struct _argument_list_t *argument_list;
case_clausule_t *case_clausule;
case_list_t *case_list;
struct _case_list_t *case_list;
catch_block_t *catch_block;
element_list_t *element_list;
struct _element_list_t *element_list;
expression_t *expr;
const WCHAR *identifier;
function_declaration_t *function_declaration;
parameter_list_t *parameter_list;
property_list_t *property_list;
struct _parameter_list_t *parameter_list;
struct _property_list_t *property_list;
source_elements_t *source_elements;
statement_t *statement;
statement_list_t *statement_list;
variable_list_t *variable_list;
struct _statement_list_t *statement_list;
struct _variable_list_t *variable_list;
variable_declaration_t *variable_declaration;
}
@@ -566,27 +566,27 @@ BitwiseORExpressionNoIn
BitwiseXORExpression
: BitwiseANDExpression { $$ = $1; }
| BitwiseXORExpression '^' BitwiseANDExpression
{ new_binary_expression(ctx, EXPR_BXOR, $1, $3); }
{ $$ = new_binary_expression(ctx, EXPR_BXOR, $1, $3); }
/* ECMA-262 3rd Edition 11.10 */
BitwiseXORExpressionNoIn
: BitwiseANDExpressionNoIn
{ $$ = $1; }
| BitwiseXORExpressionNoIn '^' BitwiseANDExpressionNoIn
{ new_binary_expression(ctx, EXPR_BXOR, $1, $3); }
{ $$ = new_binary_expression(ctx, EXPR_BXOR, $1, $3); }
/* ECMA-262 3rd Edition 11.10 */
BitwiseANDExpression
: EqualityExpression { $$ = $1; }
| BitwiseANDExpression '&' EqualityExpression
{ new_binary_expression(ctx, EXPR_BAND, $1, $3); }
{ $$ = new_binary_expression(ctx, EXPR_BAND, $1, $3); }
/* ECMA-262 3rd Edition 11.10 */
BitwiseANDExpressionNoIn
: EqualityExpressionNoIn
{ $$ = $1; }
| BitwiseANDExpressionNoIn '&' EqualityExpressionNoIn
{ new_binary_expression(ctx, EXPR_BAND, $1, $3); }
{ $$ = new_binary_expression(ctx, EXPR_BAND, $1, $3); }
/* ECMA-262 3rd Edition 11.9 */
EqualityExpression
@@ -676,7 +676,7 @@ LeftHandSideExpression
/* ECMA-262 3rd Edition 11.2 */
NewExpression
: MemberExpression { $$ = $1; }
| kNEW NewExpression { $$ = new_unary_expression(ctx, EXPR_NEW, $2); }
| kNEW NewExpression { $$ = new_new_expression(ctx, $2, NULL); }
/* ECMA-262 3rd Edition 11.2 */
MemberExpression
@@ -687,7 +687,7 @@ MemberExpression
| MemberExpression '.' tIdentifier
{ $$ = new_member_expression(ctx, $1, $3); }
| kNEW MemberExpression Arguments
{ $$ = new_member_new_expression(ctx, $2, $3); }
{ $$ = new_new_expression(ctx, $2, $3); }
/* ECMA-262 3rd Edition 11.2 */
CallExpression
@@ -775,7 +775,8 @@ Literal
| BooleanLiteral { $$ = $1; }
| tNumericLiteral { $$ = $1; }
| tStringLiteral { $$ = new_string_literal(ctx, $1); }
| '/' { FIXME("RegExp literal\n"); YYABORT; }
| '/' { $$ = parse_regexp(ctx);
if(!$$) YYABORT; }
/* ECMA-262 3rd Edition 7.8.2 */
BooleanLiteral
@@ -976,14 +977,14 @@ static case_clausule_t *new_case_block(parser_ctx_t *ctx, case_list_t *case_list
if(!ret)
return NULL;
for(iter = ret->next; iter->next; iter = iter->next) {
for(iter2 = iter; iter2 && !iter2->expr; iter2 = iter2->next);
for(iter = ret; iter; iter = iter->next) {
for(iter2 = iter; iter2 && !iter2->stat; iter2 = iter2->next);
if(!iter2)
break;
while(iter != iter2) {
iter->stat = iter2->stat;
iter2 = iter2->next;
iter = iter->next;
}
if(stat) {
@@ -1085,8 +1086,9 @@ static statement_t *new_while_statement(parser_ctx_t *ctx, BOOL dowhile, express
{
while_statement_t *ret = parser_alloc(ctx, sizeof(while_statement_t));
ret->stat.eval = dowhile ? dowhile_statement_eval : while_statement_eval;
ret->stat.eval = while_statement_eval;
ret->stat.next = NULL;
ret->do_while = dowhile;
ret->expr = expr;
ret->statement = stat;
@@ -1280,7 +1282,6 @@ static const expression_eval_t expression_eval_table[] = {
post_decrement_expression_eval,
pre_increment_expression_eval,
pre_decrement_expression_eval,
new_expression_eval,
equal_expression_eval,
equal2_expression_eval,
not_equal_expression_eval,
@@ -1365,11 +1366,11 @@ static expression_t *new_member_expression(parser_ctx_t *ctx, expression_t *expr
return &ret->expr;
}
static expression_t *new_member_new_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list)
static expression_t *new_new_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list)
{
call_expression_t *ret = parser_alloc(ctx, sizeof(call_expression_t));
ret->expr.eval = member_new_expression_eval;
ret->expr.eval = new_expression_eval;
ret->expression = expression;
ret->argument_list = argument_list ? argument_list->head : NULL;
@@ -1509,9 +1510,14 @@ 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);
jsheap_free(&ctx->heap);
heap_free(ctx);
}
@@ -1519,6 +1525,7 @@ void parser_release(parser_ctx_t *ctx)
HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, parser_ctx_t **ret)
{
parser_ctx_t *parser_ctx;
jsheap_t *mark;
HRESULT hres;
parser_ctx = heap_alloc_zero(sizeof(parser_ctx_t));
@@ -1534,11 +1541,11 @@ HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, parser_ctx_t **ret)
script_addref(ctx);
parser_ctx->script = ctx;
jsheap_init(&parser_ctx->tmp_heap);
mark = jsheap_mark(&ctx->tmp_heap);
jsheap_init(&parser_ctx->heap);
parser_parse(parser_ctx);
jsheap_free(&parser_ctx->tmp_heap);
jsheap_clear(mark);
if(FAILED(parser_ctx->hres)) {
hres = parser_ctx->hres;
parser_release(parser_ctx);
File diff suppressed because it is too large Load Diff
+579
View File
@@ -0,0 +1,579 @@
/*
* Copyright 2008 Jacek Caban for CodeWeavers
*
* 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 "jscript.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
typedef struct {
DispatchEx dispex;
WCHAR *str;
DWORD length;
} StringInstance;
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 valueOfW[] = {'v','a','l','u','e','O','f',0};
static const WCHAR anchorW[] = {'a','n','c','h','o','r',0};
static const WCHAR bigW[] = {'b','i','g',0};
static const WCHAR blinkW[] = {'b','l','i','n','k',0};
static const WCHAR boldW[] = {'b','o','l','d',0};
static const WCHAR charAtW[] = {'c','h','a','r','A','t',0};
static const WCHAR charCodeAtW[] = {'c','h','a','r','C','o','d','e','A','t',0};
static const WCHAR concatW[] = {'c','o','n','c','a','t',0};
static const WCHAR fixedW[] = {'f','i','x','e','d',0};
static const WCHAR fontcolorW[] = {'f','o','n','t','c','o','l','o','r',0};
static const WCHAR fontsizeW[] = {'f','o','n','t','s','i','z','e',0};
static const WCHAR indexOfW[] = {'i','n','d','e','x','O','f',0};
static const WCHAR italicsW[] = {'i','t','a','l','i','c','s',0};
static const WCHAR lastIndexOfW[] = {'l','a','s','t','I','n','d','e','x','O','f',0};
static const WCHAR linkW[] = {'l','i','n','k',0};
static const WCHAR matchW[] = {'m','a','t','c','h',0};
static const WCHAR replaceW[] = {'r','e','p','l','a','c','e',0};
static const WCHAR searchW[] = {'s','e','a','r','c','h',0};
static const WCHAR sliceW[] = {'s','l','i','c','e',0};
static const WCHAR smallW[] = {'s','m','a','l','l',0};
static const WCHAR splitW[] = {'s','p','l','i','t',0};
static const WCHAR strikeW[] = {'s','t','r','i','k','e',0};
static const WCHAR subW[] = {'s','u','b',0};
static const WCHAR substringW[] = {'s','u','b','s','t','r','i','n','g',0};
static const WCHAR substrW[] = {'s','u','b','s','t','r',0};
static const WCHAR supW[] = {'s','u','p',0};
static const WCHAR toLowerCaseW[] = {'t','o','L','o','w','e','r','C','a','s','e',0};
static const WCHAR toUpperCaseW[] = {'t','o','U','p','p','e','r','C','a','s','e',0};
static const WCHAR toLocaleLowerCaseW[] = {'t','o','L','o','c','a','l','e','L','o','w','e','r','C','a','s','e',0};
static const WCHAR toLocaleUpperCaseW[] = {'t','o','L','o','c','a','l','e','U','p','p','e','r','C','a','s','e',0};
static const WCHAR localeCompareW[] = {'l','o','c','a','l','e','C','o','m','p','a','r','e',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 String_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
TRACE("%p\n", dispex);
switch(flags) {
case DISPATCH_PROPERTYGET: {
StringInstance *jsthis = (StringInstance*)dispex;
V_VT(retv) = VT_I4;
V_I4(retv) = jsthis->length;
break;
}
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
return S_OK;
}
static HRESULT String_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
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 HRESULT String_big(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_blink(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_bold(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
/* ECMA-262 3rd Edition 15.5.4.5 */
static HRESULT String_charAt(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
StringInstance *strobj;
BSTR str;
INT pos = 0;
HRESULT hres;
TRACE("\n");
if(dispex->builtin_info->class != JSCLASS_STRING) {
FIXME("not string this not supported\n");
return E_NOTIMPL;
}
strobj = (StringInstance*)dispex;
if(arg_cnt(dp)) {
VARIANT num;
hres = to_integer(dispex->ctx, get_arg(dp, 0), ei, &num);
if(FAILED(hres))
return hres;
if(V_VT(&num) == VT_I4) {
pos = V_I4(&num);
}else {
WARN("pos = %lf\n", V_R8(&num));
pos = -1;
}
}
if(!retv)
return S_OK;
if(0 <= pos && pos < strobj->length)
str = SysAllocStringLen(strobj->str+pos, 1);
else
str = SysAllocStringLen(NULL, 0);
if(!str)
return E_OUTOFMEMORY;
V_VT(retv) = VT_BSTR;
V_BSTR(retv) = str;
return S_OK;
}
static HRESULT String_charCodeAt(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_concat(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_fixed(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
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 HRESULT String_fontsize(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_indexOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_italics(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_lastIndexOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_link(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
/* 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;
match_result_t *match_result;
DispatchEx *array;
VARIANT var, *arg_var;
DWORD match_cnt, i;
HRESULT hres = S_OK;
TRACE("\n");
if(dp->cArgs - dp->cNamedArgs != 1) {
FIXME("unsupported args\n");
return E_NOTIMPL;
}
arg_var = get_arg(dp, 0);
switch(V_VT(arg_var)) {
case VT_DISPATCH: {
DispatchEx *regexp;
regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var));
if(regexp) {
if(regexp->builtin_info->class == JSCLASS_REGEXP) {
hres = regexp_match(regexp, This->str, This->length, FALSE, &match_result, &match_cnt);
jsdisp_release(regexp);
if(FAILED(hres))
return hres;
break;
}
jsdisp_release(regexp);
}
}
default:
FIXME("implemented only for regexp args\n");
return E_NOTIMPL;
}
if(!match_cnt) {
TRACE("no match\n");
if(retv)
V_VT(retv) = VT_NULL;
return S_OK;
}
hres = create_array(dispex->ctx, match_cnt, &array);
if(FAILED(hres))
return hres;
V_VT(&var) = VT_BSTR;
for(i=0; i < match_cnt; i++) {
V_BSTR(&var) = SysAllocStringLen(match_result[i].str, match_result[i].len);
if(!V_BSTR(&var)) {
hres = E_OUTOFMEMORY;
break;
}
hres = jsdisp_propput_idx(array, i, lcid, &var, ei, NULL/*FIXME*/);
SysFreeString(V_BSTR(&var));
if(FAILED(hres))
break;
}
if(FAILED(hres)) {
jsdisp_release(array);
return hres;
}
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array);
return S_OK;
}
static HRESULT String_replace(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_search(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_slice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_small(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_split(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_strike(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_sub(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_substring(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_substr(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_sup(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_toLowerCase(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_toUpperCase(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_toLocaleLowerCase(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_toLocaleUpperCase(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_localeCompare(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT String_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static void String_destructor(DispatchEx *dispex)
{
StringInstance *This = (StringInstance*)dispex;
heap_free(This->str);
heap_free(This);
}
static const builtin_prop_t String_props[] = {
{anchorW, String_anchor, PROPF_METHOD},
{bigW, String_big, PROPF_METHOD},
{blinkW, String_blink, PROPF_METHOD},
{boldW, String_bold, PROPF_METHOD},
{charAtW, String_charAt, PROPF_METHOD},
{charCodeAtW, String_charCodeAt, PROPF_METHOD},
{concatW, String_concat, PROPF_METHOD},
{fixedW, String_fixed, PROPF_METHOD},
{fontcolorW, String_fontcolor, PROPF_METHOD},
{fontsizeW, String_fontsize, PROPF_METHOD},
{hasOwnPropertyW, String_hasOwnProperty, PROPF_METHOD},
{indexOfW, String_indexOf, PROPF_METHOD},
{isPrototypeOfW, String_isPrototypeOf, PROPF_METHOD},
{italicsW, String_italics, PROPF_METHOD},
{lastIndexOfW, String_lastIndexOf, PROPF_METHOD},
{lengthW, String_length, 0},
{linkW, String_link, PROPF_METHOD},
{localeCompareW, String_localeCompare, PROPF_METHOD},
{matchW, String_match, PROPF_METHOD},
{propertyIsEnumerableW, String_propertyIsEnumerable, PROPF_METHOD},
{replaceW, String_replace, PROPF_METHOD},
{searchW, String_search, PROPF_METHOD},
{sliceW, String_slice, PROPF_METHOD},
{smallW, String_small, PROPF_METHOD},
{splitW, String_split, PROPF_METHOD},
{strikeW, String_strike, PROPF_METHOD},
{substringW, String_substring, PROPF_METHOD},
{substrW, String_substr, PROPF_METHOD},
{subW, String_sub, PROPF_METHOD},
{supW, String_sup, PROPF_METHOD},
{toLocaleLowerCaseW, String_toLocaleLowerCase, PROPF_METHOD},
{toLocaleUpperCaseW, String_toLocaleUpperCase, PROPF_METHOD},
{toLowerCaseW, String_toLowerCase, PROPF_METHOD},
{toStringW, String_toString, PROPF_METHOD},
{toUpperCaseW, String_toUpperCase, PROPF_METHOD},
{valueOfW, String_valueOf, PROPF_METHOD}
};
static const builtin_info_t String_info = {
JSCLASS_STRING,
{NULL, String_value, 0},
sizeof(String_props)/sizeof(*String_props),
String_props,
String_destructor,
NULL
};
static HRESULT StringConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT string_alloc(script_ctx_t *ctx, BOOL use_constr, StringInstance **ret)
{
StringInstance *string;
HRESULT hres;
string = heap_alloc_zero(sizeof(StringInstance));
if(!string)
return E_OUTOFMEMORY;
if(use_constr)
hres = init_dispex_from_constr(&string->dispex, ctx, &String_info, ctx->string_constr);
else
hres = init_dispex(&string->dispex, ctx, &String_info, NULL);
if(FAILED(hres)) {
heap_free(string);
return hres;
}
*ret = string;
return S_OK;
}
HRESULT create_string_constr(script_ctx_t *ctx, DispatchEx **ret)
{
StringInstance *string;
HRESULT hres;
hres = string_alloc(ctx, FALSE, &string);
if(FAILED(hres))
return hres;
hres = create_builtin_function(ctx, StringConstr_value, PROPF_CONSTR, &string->dispex, ret);
jsdisp_release(&string->dispex);
return hres;
}
HRESULT create_string(script_ctx_t *ctx, const WCHAR *str, DWORD len, DispatchEx **ret)
{
StringInstance *string;
HRESULT hres;
hres = string_alloc(ctx, TRUE, &string);
if(FAILED(hres))
return hres;
if(len == -1)
len = strlenW(str);
string->length = len;
string->str = heap_alloc((len+1)*sizeof(WCHAR));
if(!string->str) {
jsdisp_release(&string->dispex);
return E_OUTOFMEMORY;
}
memcpy(string->str, str, len*sizeof(WCHAR));
string->str[len] = 0;
*ret = &string->dispex;
return S_OK;
}