mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 04:13:34 +00:00
sync jscript with wine 1.1.5
svn path=/trunk/; revision=36376
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+2632
-209
File diff suppressed because it is too large
Load Diff
@@ -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*);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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, ®exp);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user