2008-09-21 13:24:00 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2018-03-17 12:11:29 +00:00
|
|
|
#include "config.h"
|
|
|
|
#include "wine/port.h"
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
2008-09-21 13:24:00 +00:00
|
|
|
#include "jscript.h"
|
|
|
|
|
2018-03-17 12:11:29 +00:00
|
|
|
#include "wine/debug.h"
|
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
|
|
|
|
|
2008-09-21 13:24:00 +00:00
|
|
|
typedef struct {
|
2013-04-03 21:19:50 +00:00
|
|
|
jsdisp_t dispex;
|
2008-09-21 13:24:00 +00:00
|
|
|
|
|
|
|
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};
|
2019-01-26 12:11:40 +00:00
|
|
|
static const WCHAR forEachW[] = {'f','o','r','E','a','c','h',0};
|
2008-09-21 13:24:00 +00:00
|
|
|
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 unshiftW[] = {'u','n','s','h','i','f','t',0};
|
2018-03-17 12:11:29 +00:00
|
|
|
static const WCHAR indexOfW[] = {'i','n','d','e','x','O','f',0};
|
2008-09-21 13:24:00 +00:00
|
|
|
|
2009-02-13 18:04:38 +00:00
|
|
|
static const WCHAR default_separatorW[] = {',',0};
|
2008-09-21 13:24:00 +00:00
|
|
|
|
2015-03-25 15:58:08 +00:00
|
|
|
static inline ArrayInstance *array_from_jsdisp(jsdisp_t *jsdisp)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(jsdisp, ArrayInstance, dispex);
|
|
|
|
}
|
|
|
|
|
2009-10-19 17:03:21 +00:00
|
|
|
static inline ArrayInstance *array_from_vdisp(vdisp_t *vdisp)
|
|
|
|
{
|
2015-03-25 15:58:08 +00:00
|
|
|
return array_from_jsdisp(vdisp->u.jsdisp);
|
2009-10-19 17:03:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline ArrayInstance *array_this(vdisp_t *jsthis)
|
|
|
|
{
|
|
|
|
return is_vclass(jsthis, JSCLASS_ARRAY) ? array_from_vdisp(jsthis) : NULL;
|
|
|
|
}
|
|
|
|
|
2016-03-03 13:24:43 +00:00
|
|
|
unsigned array_get_length(jsdisp_t *array)
|
|
|
|
{
|
|
|
|
assert(is_class(array, JSCLASS_ARRAY));
|
|
|
|
return array_from_jsdisp(array)->length;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT get_length(script_ctx_t *ctx, vdisp_t *vdisp, jsdisp_t **jsthis, DWORD *ret)
|
2009-10-19 17:03:21 +00:00
|
|
|
{
|
|
|
|
ArrayInstance *array;
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_t val;
|
2009-10-19 17:03:21 +00:00
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
array = array_this(vdisp);
|
|
|
|
if(array) {
|
|
|
|
*jsthis = &array->dispex;
|
|
|
|
*ret = array->length;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!is_jsdisp(vdisp))
|
2013-04-03 21:19:50 +00:00
|
|
|
return throw_type_error(ctx, JS_E_JSCRIPT_EXPECTED, NULL);
|
2009-10-19 17:03:21 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_propget_name(vdisp->u.jsdisp, lengthW, &val);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = to_uint32(ctx, val, ret);
|
|
|
|
jsval_release(val);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
*jsthis = vdisp->u.jsdisp;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT set_length(jsdisp_t *obj, DWORD length)
|
2009-10-19 17:03:21 +00:00
|
|
|
{
|
|
|
|
if(is_class(obj, JSCLASS_ARRAY)) {
|
2016-11-23 10:06:56 +00:00
|
|
|
array_from_jsdisp(obj)->length = length;
|
2009-10-19 17:03:21 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
return jsdisp_propput_name(obj, lengthW, jsval_number(length));
|
2009-10-19 17:03:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static WCHAR *idx_to_str(DWORD idx, WCHAR *ptr)
|
|
|
|
{
|
|
|
|
if(!idx) {
|
|
|
|
*ptr = '0';
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(idx) {
|
|
|
|
*ptr-- = '0' + (idx%10);
|
|
|
|
idx /= 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ptr+1;
|
|
|
|
}
|
|
|
|
|
2015-03-25 15:58:08 +00:00
|
|
|
static HRESULT Array_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2015-03-25 15:58:08 +00:00
|
|
|
TRACE("%p\n", jsthis);
|
2008-09-21 13:24:00 +00:00
|
|
|
|
2015-03-25 15:58:08 +00:00
|
|
|
*r = jsval_number(array_from_jsdisp(jsthis)->length);
|
|
|
|
return S_OK;
|
|
|
|
}
|
2008-09-21 13:24:00 +00:00
|
|
|
|
2015-03-25 15:58:08 +00:00
|
|
|
static HRESULT Array_set_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value)
|
|
|
|
{
|
|
|
|
ArrayInstance *This = array_from_jsdisp(jsthis);
|
|
|
|
DOUBLE len = -1;
|
|
|
|
DWORD i;
|
|
|
|
HRESULT hres;
|
2009-08-08 07:34:09 +00:00
|
|
|
|
2015-03-25 15:58:08 +00:00
|
|
|
TRACE("%p %d\n", This, This->length);
|
2009-08-08 07:34:09 +00:00
|
|
|
|
2015-03-25 15:58:08 +00:00
|
|
|
hres = to_number(ctx, value, &len);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
2009-08-08 07:34:09 +00:00
|
|
|
|
2015-03-25 15:58:08 +00:00
|
|
|
len = floor(len);
|
|
|
|
if(len!=(DWORD)len)
|
|
|
|
return throw_range_error(ctx, JS_E_INVALID_LENGTH, NULL);
|
2009-08-08 07:34:09 +00:00
|
|
|
|
2015-03-25 15:58:08 +00:00
|
|
|
for(i=len; i < This->length; i++) {
|
|
|
|
hres = jsdisp_delete_idx(&This->dispex, i);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2015-03-25 15:58:08 +00:00
|
|
|
This->length = len;
|
2008-09-21 13:24:00 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT concat_array(jsdisp_t *array, ArrayInstance *obj, DWORD *len)
|
2009-02-13 18:04:38 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_t val;
|
2009-02-13 18:04:38 +00:00
|
|
|
DWORD i;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
for(i=0; i < obj->length; i++) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_get_idx(&obj->dispex, i, &val);
|
2009-02-13 18:04:38 +00:00
|
|
|
if(hres == DISP_E_UNKNOWNNAME)
|
|
|
|
continue;
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_propput_idx(array, *len+i, val);
|
|
|
|
jsval_release(val);
|
2009-02-13 18:04:38 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
|
|
|
*len += obj->length;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT concat_obj(jsdisp_t *array, IDispatch *obj, DWORD *len)
|
2009-02-13 18:04:38 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
jsdisp_t *jsobj;
|
2009-02-13 18:04:38 +00:00
|
|
|
HRESULT hres;
|
|
|
|
|
2016-08-19 09:36:35 +00:00
|
|
|
jsobj = iface_to_jsdisp(obj);
|
2009-02-13 18:04:38 +00:00
|
|
|
if(jsobj) {
|
|
|
|
if(is_class(jsobj, JSCLASS_ARRAY)) {
|
2016-11-23 10:06:56 +00:00
|
|
|
hres = concat_array(array, array_from_jsdisp(jsobj), len);
|
2009-02-13 18:04:38 +00:00
|
|
|
jsdisp_release(jsobj);
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
jsdisp_release(jsobj);
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
return jsdisp_propput_idx(array, (*len)++, jsval_disp(obj));
|
2009-02-13 18:04:38 +00:00
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT Array_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
jsdisp_t *ret;
|
2009-02-13 18:04:38 +00:00
|
|
|
DWORD len = 0;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
2009-10-19 17:03:21 +00:00
|
|
|
hres = create_array(ctx, 0, &ret);
|
2009-02-13 18:04:38 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = concat_obj(ret, jsthis->u.disp, &len);
|
2009-02-13 18:04:38 +00:00
|
|
|
if(SUCCEEDED(hres)) {
|
|
|
|
DWORD i;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
for(i=0; i < argc; i++) {
|
|
|
|
if(is_object_instance(argv[i]))
|
|
|
|
hres = concat_obj(ret, get_object(argv[i]), &len);
|
2009-02-13 18:04:38 +00:00
|
|
|
else
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_propput_idx(ret, len++, argv[i]);
|
2009-02-13 18:04:38 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = jsval_obj(ret);
|
|
|
|
else
|
2009-02-13 18:04:38 +00:00
|
|
|
jsdisp_release(ret);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2016-11-23 10:06:56 +00:00
|
|
|
static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, const WCHAR *sep,
|
|
|
|
unsigned seplen, jsval_t *r)
|
2009-02-13 18:04:38 +00:00
|
|
|
{
|
2016-11-23 10:06:56 +00:00
|
|
|
jsstr_t **str_tab, *ret = NULL;
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_t val;
|
2009-02-13 18:04:38 +00:00
|
|
|
DWORD i;
|
|
|
|
HRESULT hres = E_FAIL;
|
|
|
|
|
|
|
|
if(!length) {
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = jsval_string(jsstr_empty());
|
2009-02-13 18:04:38 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
str_tab = heap_alloc_zero(length * sizeof(*str_tab));
|
2009-02-13 18:04:38 +00:00
|
|
|
if(!str_tab)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
for(i=0; i < length; i++) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_get_idx(array, i, &val);
|
2010-03-02 19:46:01 +00:00
|
|
|
if(hres == DISP_E_UNKNOWNNAME) {
|
|
|
|
hres = S_OK;
|
|
|
|
continue;
|
|
|
|
} else if(FAILED(hres))
|
2009-02-13 18:04:38 +00:00
|
|
|
break;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(!is_undefined(val) && !is_null(val)) {
|
|
|
|
hres = to_string(ctx, val, str_tab+i);
|
|
|
|
jsval_release(val);
|
|
|
|
if(FAILED(hres))
|
|
|
|
break;
|
|
|
|
}
|
2009-02-13 18:04:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(SUCCEEDED(hres)) {
|
2016-11-23 10:06:56 +00:00
|
|
|
DWORD len = 0;
|
2009-02-13 18:04:38 +00:00
|
|
|
|
|
|
|
if(str_tab[0])
|
2013-04-03 21:19:50 +00:00
|
|
|
len = jsstr_length(str_tab[0]);
|
|
|
|
for(i=1; i < length; i++) {
|
|
|
|
len += seplen;
|
|
|
|
if(str_tab[i])
|
|
|
|
len += jsstr_length(str_tab[i]);
|
|
|
|
if(len > JSSTR_MAX_LENGTH) {
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2013-09-20 12:14:54 +00:00
|
|
|
if(SUCCEEDED(hres)) {
|
|
|
|
WCHAR *ptr = NULL;
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2016-11-23 10:06:56 +00:00
|
|
|
ret = jsstr_alloc_buf(len, &ptr);
|
|
|
|
if(ret) {
|
2013-09-20 12:14:54 +00:00
|
|
|
if(str_tab[0])
|
|
|
|
ptr += jsstr_flush(str_tab[0], ptr);
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2013-09-20 12:14:54 +00:00
|
|
|
for(i=1; i < length; i++) {
|
|
|
|
if(seplen) {
|
|
|
|
memcpy(ptr, sep, seplen*sizeof(WCHAR));
|
|
|
|
ptr += seplen;
|
|
|
|
}
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2013-09-20 12:14:54 +00:00
|
|
|
if(str_tab[i])
|
|
|
|
ptr += jsstr_flush(str_tab[i], ptr);
|
|
|
|
}
|
|
|
|
}else {
|
|
|
|
hres = E_OUTOFMEMORY;
|
2009-02-13 18:04:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
for(i=0; i < length; i++) {
|
|
|
|
if(str_tab[i])
|
|
|
|
jsstr_release(str_tab[i]);
|
|
|
|
}
|
2009-02-13 18:04:38 +00:00
|
|
|
heap_free(str_tab);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
TRACE("= %s\n", debugstr_jsstr(ret));
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = jsval_string(ret);
|
|
|
|
else
|
|
|
|
jsstr_release(ret);
|
2009-02-13 18:04:38 +00:00
|
|
|
return S_OK;
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2009-02-13 18:04:38 +00:00
|
|
|
/* ECMA-262 3rd Edition 15.4.4.5 */
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
jsdisp_t *jsthis;
|
2009-02-13 18:04:38 +00:00
|
|
|
DWORD length;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = get_length(ctx, vthis, &jsthis, &length);
|
2010-03-02 19:46:01 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(argc) {
|
2013-09-20 12:14:54 +00:00
|
|
|
const WCHAR *sep;
|
|
|
|
jsstr_t *sep_str;
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2013-09-20 12:14:54 +00:00
|
|
|
hres = to_flat_string(ctx, argv[0], &sep_str, &sep);
|
2009-02-13 18:04:38 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2016-11-23 10:06:56 +00:00
|
|
|
hres = array_join(ctx, jsthis, length, sep, jsstr_length(sep_str), r);
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2013-09-20 12:14:54 +00:00
|
|
|
jsstr_release(sep_str);
|
2009-02-13 18:04:38 +00:00
|
|
|
}else {
|
2016-11-23 10:06:56 +00:00
|
|
|
hres = array_join(ctx, jsthis, length, default_separatorW, strlenW(default_separatorW), r);
|
2009-02-13 18:04:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return hres;
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT Array_pop(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
jsdisp_t *jsthis;
|
|
|
|
jsval_t val;
|
2009-02-13 18:04:38 +00:00
|
|
|
DWORD length;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = get_length(ctx, vthis, &jsthis, &length);
|
2010-03-02 19:46:01 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
2009-02-13 18:04:38 +00:00
|
|
|
|
|
|
|
if(!length) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = set_length(jsthis, 0);
|
2010-03-02 19:46:01 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = jsval_undefined();
|
2009-02-13 18:04:38 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2010-03-02 19:46:01 +00:00
|
|
|
length--;
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_get_idx(jsthis, length, &val);
|
|
|
|
if(SUCCEEDED(hres))
|
2010-03-02 19:46:01 +00:00
|
|
|
hres = jsdisp_delete_idx(jsthis, length);
|
2018-03-17 12:11:29 +00:00
|
|
|
else if(hres == DISP_E_UNKNOWNNAME) {
|
2013-04-03 21:19:50 +00:00
|
|
|
val = jsval_undefined();
|
2018-03-17 12:11:29 +00:00
|
|
|
hres = S_OK;
|
|
|
|
}else
|
2009-02-13 18:04:38 +00:00
|
|
|
return hres;
|
|
|
|
|
2010-03-02 19:46:01 +00:00
|
|
|
if(SUCCEEDED(hres))
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = set_length(jsthis, length);
|
2009-02-13 18:04:38 +00:00
|
|
|
|
|
|
|
if(FAILED(hres)) {
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_release(val);
|
2009-02-13 18:04:38 +00:00
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = val;
|
2009-02-13 18:04:38 +00:00
|
|
|
else
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_release(val);
|
|
|
|
return hres;
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2009-02-13 18:04:38 +00:00
|
|
|
/* ECMA-262 3rd Edition 15.4.4.7 */
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT Array_push(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
jsdisp_t *jsthis;
|
2009-02-13 18:04:38 +00:00
|
|
|
DWORD length = 0;
|
2013-04-03 21:19:50 +00:00
|
|
|
unsigned i;
|
2009-02-13 18:04:38 +00:00
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = get_length(ctx, vthis, &jsthis, &length);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
for(i=0; i < argc; i++) {
|
|
|
|
hres = jsdisp_propput_idx(jsthis, length+i, argv[i]);
|
2009-02-13 18:04:38 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = set_length(jsthis, length+argc);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = jsval_number(length+argc);
|
2009-02-13 18:04:38 +00:00
|
|
|
return S_OK;
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT Array_reverse(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
jsdisp_t *jsthis;
|
2010-03-02 19:46:01 +00:00
|
|
|
DWORD length, k, l;
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_t v1, v2;
|
2010-03-02 19:46:01 +00:00
|
|
|
HRESULT hres1, hres2;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres1 = get_length(ctx, vthis, &jsthis, &length);
|
2010-03-02 19:46:01 +00:00
|
|
|
if(FAILED(hres1))
|
|
|
|
return hres1;
|
|
|
|
|
|
|
|
for(k=0; k<length/2; k++) {
|
|
|
|
l = length-k-1;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres1 = jsdisp_get_idx(jsthis, k, &v1);
|
2010-03-02 19:46:01 +00:00
|
|
|
if(FAILED(hres1) && hres1!=DISP_E_UNKNOWNNAME)
|
|
|
|
return hres1;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres2 = jsdisp_get_idx(jsthis, l, &v2);
|
2010-03-02 19:46:01 +00:00
|
|
|
if(FAILED(hres2) && hres2!=DISP_E_UNKNOWNNAME) {
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_release(v1);
|
2010-03-02 19:46:01 +00:00
|
|
|
return hres2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(hres1 == DISP_E_UNKNOWNNAME)
|
|
|
|
hres1 = jsdisp_delete_idx(jsthis, l);
|
|
|
|
else
|
2013-04-03 21:19:50 +00:00
|
|
|
hres1 = jsdisp_propput_idx(jsthis, l, v1);
|
2010-03-02 19:46:01 +00:00
|
|
|
|
|
|
|
if(FAILED(hres1)) {
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_release(v1);
|
|
|
|
jsval_release(v2);
|
2010-03-02 19:46:01 +00:00
|
|
|
return hres1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(hres2 == DISP_E_UNKNOWNNAME)
|
|
|
|
hres2 = jsdisp_delete_idx(jsthis, k);
|
|
|
|
else
|
2013-04-03 21:19:50 +00:00
|
|
|
hres2 = jsdisp_propput_idx(jsthis, k, v2);
|
2010-03-02 19:46:01 +00:00
|
|
|
|
|
|
|
if(FAILED(hres2)) {
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_release(v2);
|
2010-03-02 19:46:01 +00:00
|
|
|
return hres2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = jsval_obj(jsdisp_addref(jsthis));
|
2010-03-02 19:46:01 +00:00
|
|
|
return S_OK;
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2009-10-19 17:03:21 +00:00
|
|
|
/* ECMA-262 3rd Edition 15.4.4.9 */
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT Array_shift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
jsdisp_t *jsthis;
|
2009-10-19 17:03:21 +00:00
|
|
|
DWORD length = 0, i;
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_t v, ret;
|
2009-10-19 17:03:21 +00:00
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = get_length(ctx, vthis, &jsthis, &length);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
if(!length) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = set_length(jsthis, 0);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = jsval_undefined();
|
2009-10-19 17:03:21 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_get_idx(jsthis, 0, &ret);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(hres == DISP_E_UNKNOWNNAME) {
|
2013-04-03 21:19:50 +00:00
|
|
|
ret = jsval_undefined();
|
2009-10-19 17:03:21 +00:00
|
|
|
hres = S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=1; SUCCEEDED(hres) && i<length; i++) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_get_idx(jsthis, i, &v);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(hres == DISP_E_UNKNOWNNAME)
|
|
|
|
hres = jsdisp_delete_idx(jsthis, i-1);
|
|
|
|
else if(SUCCEEDED(hres))
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_propput_idx(jsthis, i-1, v);
|
2009-10-19 17:03:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(SUCCEEDED(hres)) {
|
|
|
|
hres = jsdisp_delete_idx(jsthis, length-1);
|
|
|
|
if(SUCCEEDED(hres))
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = set_length(jsthis, length-1);
|
2009-10-19 17:03:21 +00:00
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
if(r)
|
|
|
|
*r = ret;
|
2009-10-19 17:03:21 +00:00
|
|
|
else
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_release(ret);
|
2009-10-19 17:03:21 +00:00
|
|
|
return hres;
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2009-10-19 17:03:21 +00:00
|
|
|
/* ECMA-262 3rd Edition 15.4.4.10 */
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT Array_slice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
jsdisp_t *arr, *jsthis;
|
2009-08-08 07:34:09 +00:00
|
|
|
DOUBLE range;
|
|
|
|
DWORD length, start, end, idx;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = get_length(ctx, vthis, &jsthis, &length);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
2009-08-08 07:34:09 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(argc) {
|
|
|
|
hres = to_number(ctx, argv[0], &range);
|
2009-08-08 07:34:09 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
range = floor(range);
|
2009-08-08 07:34:09 +00:00
|
|
|
if(-range>length || isnan(range)) start = 0;
|
|
|
|
else if(range < 0) start = range+length;
|
|
|
|
else if(range <= length) start = range;
|
|
|
|
else start = length;
|
|
|
|
}
|
|
|
|
else start = 0;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(argc > 1) {
|
|
|
|
hres = to_number(ctx, argv[1], &range);
|
2009-08-08 07:34:09 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
range = floor(range);
|
2009-08-08 07:34:09 +00:00
|
|
|
if(-range>length) end = 0;
|
|
|
|
else if(range < 0) end = range+length;
|
|
|
|
else if(range <= length) end = range;
|
|
|
|
else end = length;
|
|
|
|
}
|
|
|
|
else end = length;
|
|
|
|
|
2009-10-19 17:03:21 +00:00
|
|
|
hres = create_array(ctx, (end>start)?end-start:0, &arr);
|
2009-08-08 07:34:09 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
for(idx=start; idx<end; idx++) {
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_t v;
|
|
|
|
|
|
|
|
hres = jsdisp_get_idx(jsthis, idx, &v);
|
2009-08-08 07:34:09 +00:00
|
|
|
if(hres == DISP_E_UNKNOWNNAME)
|
|
|
|
continue;
|
|
|
|
|
2010-03-02 19:46:01 +00:00
|
|
|
if(SUCCEEDED(hres)) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_propput_idx(arr, idx-start, v);
|
|
|
|
jsval_release(v);
|
2010-03-02 19:46:01 +00:00
|
|
|
}
|
2009-08-08 07:34:09 +00:00
|
|
|
|
|
|
|
if(FAILED(hres)) {
|
|
|
|
jsdisp_release(arr);
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = jsval_obj(arr);
|
2009-08-08 07:34:09 +00:00
|
|
|
else
|
|
|
|
jsdisp_release(arr);
|
|
|
|
|
|
|
|
return S_OK;
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT sort_cmp(script_ctx_t *ctx, jsdisp_t *cmp_func, jsval_t v1, jsval_t v2, INT *cmp)
|
2009-02-13 18:04:38 +00:00
|
|
|
{
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
if(cmp_func) {
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_t args[2];
|
|
|
|
jsval_t res;
|
|
|
|
double n;
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
args[0] = v1;
|
|
|
|
args[1] = v2;
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_call_value(cmp_func, NULL, DISPATCH_METHOD, 2, args, &res);
|
2009-02-13 18:04:38 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = to_number(ctx, res, &n);
|
|
|
|
jsval_release(res);
|
2009-02-13 18:04:38 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(n == 0)
|
|
|
|
*cmp = 0;
|
|
|
|
*cmp = n > 0.0 ? 1 : -1;
|
|
|
|
}else if(is_undefined(v1)) {
|
|
|
|
*cmp = is_undefined(v2) ? 0 : 1;
|
|
|
|
}else if(is_undefined(v2)) {
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*cmp = -1;
|
2013-04-03 21:19:50 +00:00
|
|
|
}else if(is_number(v1) && is_number(v2)) {
|
|
|
|
double d = get_number(v1)-get_number(v2);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if(d > 0.0)
|
|
|
|
*cmp = 1;
|
2009-02-13 18:04:38 +00:00
|
|
|
else
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*cmp = d < -0.0 ? -1 : 0;
|
2009-02-13 18:04:38 +00:00
|
|
|
}else {
|
2013-04-03 21:19:50 +00:00
|
|
|
jsstr_t *x, *y;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = to_string(ctx, v1, &x);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = to_string(ctx, v2, &y);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if(SUCCEEDED(hres)) {
|
2013-04-03 21:19:50 +00:00
|
|
|
*cmp = jsstr_cmp(x, y);
|
|
|
|
jsstr_release(y);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
2013-04-03 21:19:50 +00:00
|
|
|
jsstr_release(x);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
2009-02-13 18:04:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ECMA-262 3rd Edition 15.4.4.11 */
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
jsdisp_t *jsthis, *cmp_func = NULL;
|
|
|
|
jsval_t *vtab, **sorttab = NULL;
|
2009-02-13 18:04:38 +00:00
|
|
|
DWORD length;
|
|
|
|
DWORD i;
|
|
|
|
HRESULT hres = S_OK;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = get_length(ctx, vthis, &jsthis, &length);
|
2010-03-02 19:46:01 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(argc > 1) {
|
|
|
|
WARN("invalid arg_cnt %d\n", argc);
|
2009-02-13 18:04:38 +00:00
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(argc == 1) {
|
|
|
|
if(!is_object_instance(argv[0])) {
|
2009-02-13 18:04:38 +00:00
|
|
|
WARN("arg is not dispatch\n");
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
2016-08-19 09:36:35 +00:00
|
|
|
cmp_func = iface_to_jsdisp(get_object(argv[0]));
|
2009-02-13 18:04:38 +00:00
|
|
|
if(!cmp_func || !is_class(cmp_func, JSCLASS_FUNCTION)) {
|
|
|
|
WARN("cmp_func is not a function\n");
|
|
|
|
if(cmp_func)
|
|
|
|
jsdisp_release(cmp_func);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!length) {
|
|
|
|
if(cmp_func)
|
|
|
|
jsdisp_release(cmp_func);
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = jsval_obj(jsdisp_addref(jsthis));
|
2009-02-13 18:04:38 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
vtab = heap_alloc_zero(length * sizeof(*vtab));
|
2009-02-13 18:04:38 +00:00
|
|
|
if(vtab) {
|
|
|
|
for(i=0; i<length; i++) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_get_idx(jsthis, i, vtab+i);
|
2010-03-02 19:46:01 +00:00
|
|
|
if(hres == DISP_E_UNKNOWNNAME) {
|
2013-04-03 21:19:50 +00:00
|
|
|
vtab[i] = jsval_undefined();
|
2010-03-02 19:46:01 +00:00
|
|
|
hres = S_OK;
|
|
|
|
} else if(FAILED(hres)) {
|
2009-02-13 18:04:38 +00:00
|
|
|
WARN("Could not get elem %d: %08x\n", i, hres);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else {
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(SUCCEEDED(hres)) {
|
2013-04-03 21:19:50 +00:00
|
|
|
sorttab = heap_alloc(length*2*sizeof(*sorttab));
|
2009-02-13 18:04:38 +00:00
|
|
|
if(!sorttab)
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* merge-sort */
|
|
|
|
if(SUCCEEDED(hres)) {
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_t *tmpv, **tmpbuf;
|
2009-02-13 18:04:38 +00:00
|
|
|
INT cmp;
|
|
|
|
|
|
|
|
tmpbuf = sorttab + length;
|
|
|
|
for(i=0; i < length; i++)
|
|
|
|
sorttab[i] = vtab+i;
|
|
|
|
|
|
|
|
for(i=0; i < length/2; i++) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = sort_cmp(ctx, cmp_func, *sorttab[2*i+1], *sorttab[2*i], &cmp);
|
2009-02-13 18:04:38 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if(cmp < 0) {
|
|
|
|
tmpv = sorttab[2*i];
|
|
|
|
sorttab[2*i] = sorttab[2*i+1];
|
|
|
|
sorttab[2*i+1] = tmpv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(SUCCEEDED(hres)) {
|
|
|
|
DWORD k, a, b, bend;
|
|
|
|
|
|
|
|
for(k=2; k < length; k *= 2) {
|
|
|
|
for(i=0; i+k < length; i += 2*k) {
|
|
|
|
a = b = 0;
|
|
|
|
if(i+2*k <= length)
|
|
|
|
bend = k;
|
|
|
|
else
|
|
|
|
bend = length - (i+k);
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
memcpy(tmpbuf, sorttab+i, k*sizeof(jsval_t*));
|
2009-02-13 18:04:38 +00:00
|
|
|
|
|
|
|
while(a < k && b < bend) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = sort_cmp(ctx, cmp_func, *tmpbuf[a], *sorttab[i+k+b], &cmp);
|
2009-02-13 18:04:38 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if(cmp < 0) {
|
|
|
|
sorttab[i+a+b] = tmpbuf[a];
|
|
|
|
a++;
|
|
|
|
}else {
|
|
|
|
sorttab[i+a+b] = sorttab[i+k+b];
|
|
|
|
b++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(FAILED(hres))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if(a < k)
|
2013-04-03 21:19:50 +00:00
|
|
|
memcpy(sorttab+i+a+b, tmpbuf+a, (k-a)*sizeof(jsval_t*));
|
2009-02-13 18:04:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(FAILED(hres))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0; SUCCEEDED(hres) && i < length; i++)
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_propput_idx(jsthis, i, *sorttab[i]);
|
2009-02-13 18:04:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(vtab) {
|
|
|
|
for(i=0; i < length; i++)
|
2013-04-03 21:19:50 +00:00
|
|
|
jsval_release(vtab[i]);
|
2009-02-13 18:04:38 +00:00
|
|
|
heap_free(vtab);
|
|
|
|
}
|
|
|
|
heap_free(sorttab);
|
|
|
|
if(cmp_func)
|
|
|
|
jsdisp_release(cmp_func);
|
|
|
|
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = jsval_obj(jsdisp_addref(jsthis));
|
2009-02-13 18:04:38 +00:00
|
|
|
return S_OK;
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2009-10-19 17:03:21 +00:00
|
|
|
/* ECMA-262 3rd Edition 15.4.4.12 */
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT Array_splice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
DWORD length, start=0, delete_cnt=0, i, add_args = 0;
|
|
|
|
jsdisp_t *ret_array = NULL, *jsthis;
|
|
|
|
jsval_t val;
|
|
|
|
double d;
|
|
|
|
int n;
|
2009-10-19 17:03:21 +00:00
|
|
|
HRESULT hres = S_OK;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = get_length(ctx, vthis, &jsthis, &length);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(argc) {
|
|
|
|
hres = to_integer(ctx, argv[0], &d);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(is_int32(d)) {
|
|
|
|
if((n = d) >= 0)
|
|
|
|
start = min(n, length);
|
2009-10-19 17:03:21 +00:00
|
|
|
else
|
2013-04-03 21:19:50 +00:00
|
|
|
start = -n > length ? 0 : length + n;
|
2009-10-19 17:03:21 +00:00
|
|
|
}else {
|
2013-04-03 21:19:50 +00:00
|
|
|
start = d < 0.0 ? 0 : length;
|
2009-10-19 17:03:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(argc >= 2) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = to_integer(ctx, argv[1], &d);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(is_int32(d)) {
|
|
|
|
if((n = d) > 0)
|
|
|
|
delete_cnt = min(n, length-start);
|
|
|
|
}else if(d > 0.0) {
|
2009-10-19 17:03:21 +00:00
|
|
|
delete_cnt = length-start;
|
|
|
|
}
|
|
|
|
|
|
|
|
add_args = argc-2;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r) {
|
2009-10-19 17:03:21 +00:00
|
|
|
hres = create_array(ctx, 0, &ret_array);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
for(i=0; SUCCEEDED(hres) && i < delete_cnt; i++) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_get_idx(jsthis, start+i, &val);
|
|
|
|
if(hres == DISP_E_UNKNOWNNAME) {
|
2009-10-19 17:03:21 +00:00
|
|
|
hres = S_OK;
|
2013-04-03 21:19:50 +00:00
|
|
|
}else if(SUCCEEDED(hres)) {
|
|
|
|
hres = jsdisp_propput_idx(ret_array, i, val);
|
|
|
|
jsval_release(val);
|
|
|
|
}
|
2009-10-19 17:03:21 +00:00
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(SUCCEEDED(hres))
|
|
|
|
hres = jsdisp_propput_name(ret_array, lengthW, jsval_number(delete_cnt));
|
2009-10-19 17:03:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(add_args < delete_cnt) {
|
|
|
|
for(i = start; SUCCEEDED(hres) && i < length-delete_cnt; i++) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_get_idx(jsthis, i+delete_cnt, &val);
|
|
|
|
if(hres == DISP_E_UNKNOWNNAME) {
|
2009-10-19 17:03:21 +00:00
|
|
|
hres = jsdisp_delete_idx(jsthis, i+add_args);
|
2013-04-03 21:19:50 +00:00
|
|
|
}else if(SUCCEEDED(hres)) {
|
|
|
|
hres = jsdisp_propput_idx(jsthis, i+add_args, val);
|
|
|
|
jsval_release(val);
|
|
|
|
}
|
2009-10-19 17:03:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for(i=length; SUCCEEDED(hres) && i != length-delete_cnt+add_args; i--)
|
|
|
|
hres = jsdisp_delete_idx(jsthis, i-1);
|
|
|
|
}else if(add_args > delete_cnt) {
|
|
|
|
for(i=length-delete_cnt; SUCCEEDED(hres) && i != start; i--) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_get_idx(jsthis, i+delete_cnt-1, &val);
|
|
|
|
if(hres == DISP_E_UNKNOWNNAME) {
|
2009-10-19 17:03:21 +00:00
|
|
|
hres = jsdisp_delete_idx(jsthis, i+add_args-1);
|
2013-04-03 21:19:50 +00:00
|
|
|
}else if(SUCCEEDED(hres)) {
|
|
|
|
hres = jsdisp_propput_idx(jsthis, i+add_args-1, val);
|
|
|
|
jsval_release(val);
|
|
|
|
}
|
2009-10-19 17:03:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0; SUCCEEDED(hres) && i < add_args; i++)
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_propput_idx(jsthis, start+i, argv[i+2]);
|
2009-10-19 17:03:21 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(SUCCEEDED(hres))
|
|
|
|
hres = jsdisp_propput_name(jsthis, lengthW, jsval_number(length-delete_cnt+add_args));
|
2009-10-19 17:03:21 +00:00
|
|
|
|
|
|
|
if(FAILED(hres)) {
|
|
|
|
if(ret_array)
|
|
|
|
jsdisp_release(ret_array);
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = jsval_obj(ret_array);
|
2009-10-19 17:03:21 +00:00
|
|
|
return S_OK;
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2009-02-13 18:04:38 +00:00
|
|
|
/* ECMA-262 3rd Edition 15.4.4.2 */
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT Array_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2009-10-19 17:03:21 +00:00
|
|
|
ArrayInstance *array;
|
|
|
|
|
2009-02-13 18:04:38 +00:00
|
|
|
TRACE("\n");
|
|
|
|
|
2009-10-19 17:03:21 +00:00
|
|
|
array = array_this(jsthis);
|
|
|
|
if(!array)
|
2013-04-03 21:19:50 +00:00
|
|
|
return throw_type_error(ctx, JS_E_ARRAY_EXPECTED, NULL);
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2016-11-23 10:06:56 +00:00
|
|
|
return array_join(ctx, &array->dispex, array->length, default_separatorW,
|
|
|
|
strlenW(default_separatorW), r);
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT Array_toLocaleString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
|
|
|
FIXME("\n");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
2019-01-26 12:11:40 +00:00
|
|
|
static HRESULT Array_forEach(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
|
|
|
{
|
|
|
|
jsval_t value, args[3], res;
|
|
|
|
jsdisp_t *jsthis;
|
|
|
|
unsigned length, i;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
|
|
|
/* FIXME: Check IsCallable */
|
|
|
|
if(argc != 1 || !is_object_instance(argv[0])) {
|
|
|
|
FIXME("Unsupported arguments\n");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
hres = get_length(ctx, vthis, &jsthis, &length);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
for(i = 0; i < length; i++) {
|
|
|
|
hres = jsdisp_get_idx(jsthis, i, &value);
|
|
|
|
if(hres == DISP_E_UNKNOWNNAME)
|
|
|
|
continue;
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
args[0] = value;
|
|
|
|
args[1] = jsval_number(i);
|
|
|
|
args[2] = jsval_obj(jsthis);
|
|
|
|
hres = disp_call_value(ctx, get_object(argv[0]), NULL, DISPATCH_METHOD, ARRAY_SIZE(args), args, &res);
|
|
|
|
jsval_release(value);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
jsval_release(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(r) *r = jsval_undefined();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2018-03-17 12:11:29 +00:00
|
|
|
static HRESULT Array_indexOf(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
|
|
|
{
|
|
|
|
jsdisp_t *jsthis;
|
|
|
|
unsigned length, i, from = 0;
|
|
|
|
jsval_t search, value;
|
|
|
|
BOOL eq;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
|
|
|
hres = get_length(ctx, vthis, &jsthis, &length);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
if(!length) {
|
|
|
|
if(r) *r = jsval_number(-1);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
search = argc ? argv[0] : jsval_undefined();
|
|
|
|
|
|
|
|
if(argc > 1) {
|
|
|
|
double from_arg;
|
|
|
|
|
|
|
|
hres = to_integer(ctx, argv[1], &from_arg);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
if(from_arg >= 0)
|
|
|
|
from = min(from_arg, length);
|
|
|
|
else
|
|
|
|
from = max(from_arg + length, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i = from; i < length; i++) {
|
|
|
|
hres = jsdisp_get_idx(jsthis, i, &value);
|
|
|
|
if(hres == DISP_E_UNKNOWNNAME)
|
|
|
|
continue;
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
hres = jsval_strict_equal(value, search, &eq);
|
|
|
|
jsval_release(value);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
if(eq) {
|
|
|
|
if(r) *r = jsval_number(i);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(r) *r = jsval_number(-1);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-19 17:03:21 +00:00
|
|
|
/* ECMA-262 3rd Edition 15.4.4.13 */
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
jsdisp_t *jsthis;
|
2009-10-19 17:03:21 +00:00
|
|
|
WCHAR buf[14], *buf_end, *str;
|
2013-04-03 21:19:50 +00:00
|
|
|
DWORD i, length;
|
|
|
|
jsval_t val;
|
2009-10-19 17:03:21 +00:00
|
|
|
DISPID id;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = get_length(ctx, vthis, &jsthis, &length);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2010-03-02 19:46:01 +00:00
|
|
|
if(argc) {
|
2019-01-26 12:11:40 +00:00
|
|
|
buf_end = buf + ARRAY_SIZE(buf)-1;
|
2010-03-02 19:46:01 +00:00
|
|
|
*buf_end-- = 0;
|
|
|
|
i = length;
|
2009-10-19 17:03:21 +00:00
|
|
|
|
2010-03-02 19:46:01 +00:00
|
|
|
while(i--) {
|
|
|
|
str = idx_to_str(i, buf_end);
|
2009-10-19 17:03:21 +00:00
|
|
|
|
2010-03-02 19:46:01 +00:00
|
|
|
hres = jsdisp_get_id(jsthis, str, 0, &id);
|
|
|
|
if(SUCCEEDED(hres)) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_propget(jsthis, id, &val);
|
2010-03-02 19:46:01 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
2009-10-19 17:03:21 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_propput_idx(jsthis, i+argc, val);
|
|
|
|
jsval_release(val);
|
2010-03-02 19:46:01 +00:00
|
|
|
}else if(hres == DISP_E_UNKNOWNNAME) {
|
|
|
|
hres = IDispatchEx_DeleteMemberByDispID(vthis->u.dispex, id);
|
|
|
|
}
|
2009-10-19 17:03:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0; i<argc; i++) {
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = jsdisp_propput_idx(jsthis, i, argv[i]);
|
2009-10-19 17:03:21 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
2010-03-02 19:46:01 +00:00
|
|
|
if(argc) {
|
|
|
|
length += argc;
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = set_length(jsthis, length);
|
2010-03-02 19:46:01 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
}
|
2009-10-19 17:03:21 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
if(r)
|
|
|
|
*r = ctx->version < 2 ? jsval_undefined() : jsval_number(length);
|
2009-10-19 17:03:21 +00:00
|
|
|
return S_OK;
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2015-03-25 15:58:08 +00:00
|
|
|
static HRESULT Array_get_value(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2015-03-25 15:58:08 +00:00
|
|
|
ArrayInstance *array = array_from_jsdisp(jsthis);
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2015-03-25 15:58:08 +00:00
|
|
|
TRACE("\n");
|
2009-02-13 18:04:38 +00:00
|
|
|
|
2016-11-23 10:06:56 +00:00
|
|
|
return array_join(ctx, &array->dispex, array->length, default_separatorW,
|
|
|
|
strlenW(default_separatorW), r);
|
2008-09-21 13:24:00 +00:00
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static void Array_destructor(jsdisp_t *dispex)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
|
|
|
heap_free(dispex);
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static void Array_on_put(jsdisp_t *dispex, const WCHAR *name)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2016-11-23 10:06:56 +00:00
|
|
|
ArrayInstance *array = array_from_jsdisp(dispex);
|
2008-09-21 13:24:00 +00:00
|
|
|
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[] = {
|
2009-08-22 15:25:26 +00:00
|
|
|
{concatW, Array_concat, PROPF_METHOD|1},
|
2019-01-26 12:11:40 +00:00
|
|
|
{forEachW, Array_forEach, PROPF_METHOD|PROPF_ES5|1},
|
|
|
|
{indexOfW, Array_indexOf, PROPF_METHOD|PROPF_ES5|1},
|
2009-08-22 15:25:26 +00:00
|
|
|
{joinW, Array_join, PROPF_METHOD|1},
|
2015-03-25 15:58:08 +00:00
|
|
|
{lengthW, NULL,0, Array_get_length, Array_set_length},
|
2008-09-21 13:24:00 +00:00
|
|
|
{popW, Array_pop, PROPF_METHOD},
|
2009-08-22 15:25:26 +00:00
|
|
|
{pushW, Array_push, PROPF_METHOD|1},
|
2008-09-21 13:24:00 +00:00
|
|
|
{reverseW, Array_reverse, PROPF_METHOD},
|
|
|
|
{shiftW, Array_shift, PROPF_METHOD},
|
2009-08-22 15:25:26 +00:00
|
|
|
{sliceW, Array_slice, PROPF_METHOD|2},
|
|
|
|
{sortW, Array_sort, PROPF_METHOD|1},
|
|
|
|
{spliceW, Array_splice, PROPF_METHOD|2},
|
2008-09-21 13:24:00 +00:00
|
|
|
{toLocaleStringW, Array_toLocaleString, PROPF_METHOD},
|
|
|
|
{toStringW, Array_toString, PROPF_METHOD},
|
2009-08-22 15:25:26 +00:00
|
|
|
{unshiftW, Array_unshift, PROPF_METHOD|1},
|
2008-09-21 13:24:00 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const builtin_info_t Array_info = {
|
|
|
|
JSCLASS_ARRAY,
|
2015-03-25 15:58:08 +00:00
|
|
|
{NULL, NULL,0, Array_get_value},
|
2019-01-26 12:11:40 +00:00
|
|
|
ARRAY_SIZE(Array_props),
|
2008-09-21 13:24:00 +00:00
|
|
|
Array_props,
|
|
|
|
Array_destructor,
|
|
|
|
Array_on_put
|
|
|
|
};
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static const builtin_prop_t ArrayInst_props[] = {
|
2015-03-25 15:58:08 +00:00
|
|
|
{lengthW, NULL,0, Array_get_length, Array_set_length}
|
2013-04-03 21:19:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const builtin_info_t ArrayInst_info = {
|
|
|
|
JSCLASS_ARRAY,
|
2015-03-25 15:58:08 +00:00
|
|
|
{NULL, NULL,0, Array_get_value},
|
2019-01-26 12:11:40 +00:00
|
|
|
ARRAY_SIZE(ArrayInst_props),
|
2013-04-03 21:19:50 +00:00
|
|
|
ArrayInst_props,
|
|
|
|
Array_destructor,
|
|
|
|
Array_on_put
|
|
|
|
};
|
|
|
|
|
2018-03-17 12:11:29 +00:00
|
|
|
/* ECMA-262 5.1 Edition 15.4.3.2 */
|
|
|
|
static HRESULT ArrayConstr_isArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
|
|
|
|
{
|
|
|
|
jsdisp_t *obj;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
|
|
|
if(!argc || !is_object_instance(argv[0])) {
|
|
|
|
if(r) *r = jsval_bool(FALSE);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = iface_to_jsdisp(get_object(argv[0]));
|
|
|
|
if(r) *r = jsval_bool(obj && is_class(obj, JSCLASS_ARRAY));
|
|
|
|
if(obj) jsdisp_release(obj);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT ArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
|
|
|
jsval_t *r)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2013-04-03 21:19:50 +00:00
|
|
|
jsdisp_t *obj;
|
2008-09-21 13:24:00 +00:00
|
|
|
DWORD i;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("\n");
|
|
|
|
|
|
|
|
switch(flags) {
|
2009-08-08 07:34:09 +00:00
|
|
|
case DISPATCH_METHOD:
|
2008-09-21 13:24:00 +00:00
|
|
|
case DISPATCH_CONSTRUCT: {
|
2013-04-03 21:19:50 +00:00
|
|
|
if(argc == 1 && is_number(argv[0])) {
|
|
|
|
double n = get_number(argv[0]);
|
|
|
|
|
|
|
|
if(n < 0 || !is_int32(n))
|
|
|
|
return throw_range_error(ctx, JS_E_INVALID_LENGTH, NULL);
|
2008-09-21 13:24:00 +00:00
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = create_array(ctx, n, &obj);
|
2008-09-21 13:24:00 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
*r = jsval_obj(obj);
|
2008-09-21 13:24:00 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = create_array(ctx, argc, &obj);
|
2008-09-21 13:24:00 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
for(i=0; i < argc; i++) {
|
|
|
|
hres = jsdisp_propput_idx(obj, i, argv[i]);
|
2008-09-21 13:24:00 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(FAILED(hres)) {
|
|
|
|
jsdisp_release(obj);
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
*r = jsval_obj(obj);
|
2008-09-21 13:24:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
FIXME("unimplemented flags: %x\n", flags);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
static HRESULT alloc_array(script_ctx_t *ctx, jsdisp_t *object_prototype, ArrayInstance **ret)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
2009-02-13 18:04:38 +00:00
|
|
|
ArrayInstance *array;
|
2008-09-21 13:24:00 +00:00
|
|
|
HRESULT hres;
|
|
|
|
|
2009-02-13 18:04:38 +00:00
|
|
|
array = heap_alloc_zero(sizeof(ArrayInstance));
|
|
|
|
if(!array)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2009-08-22 15:25:26 +00:00
|
|
|
if(object_prototype)
|
|
|
|
hres = init_dispex(&array->dispex, ctx, &Array_info, object_prototype);
|
2008-09-21 13:24:00 +00:00
|
|
|
else
|
2013-04-03 21:19:50 +00:00
|
|
|
hres = init_dispex_from_constr(&array->dispex, ctx, &ArrayInst_info, ctx->array_constr);
|
2008-09-21 13:24:00 +00:00
|
|
|
|
|
|
|
if(FAILED(hres)) {
|
|
|
|
heap_free(array);
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ret = array;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2018-03-17 12:11:29 +00:00
|
|
|
static const WCHAR isArrayW[] = {'i','s','A','r','r','a','y',0};
|
|
|
|
|
|
|
|
static const builtin_prop_t ArrayConstr_props[] = {
|
|
|
|
{isArrayW, ArrayConstr_isArray, PROPF_ES5|PROPF_METHOD|1}
|
|
|
|
};
|
|
|
|
|
|
|
|
static const builtin_info_t ArrayConstr_info = {
|
|
|
|
JSCLASS_FUNCTION,
|
|
|
|
DEFAULT_FUNCTION_VALUE,
|
2019-01-26 12:11:40 +00:00
|
|
|
ARRAY_SIZE(ArrayConstr_props),
|
2018-03-17 12:11:29 +00:00
|
|
|
ArrayConstr_props,
|
|
|
|
NULL,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
HRESULT create_array_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
|
|
|
ArrayInstance *array;
|
|
|
|
HRESULT hres;
|
|
|
|
|
2009-10-19 17:03:21 +00:00
|
|
|
static const WCHAR ArrayW[] = {'A','r','r','a','y',0};
|
|
|
|
|
2009-08-22 15:25:26 +00:00
|
|
|
hres = alloc_array(ctx, object_prototype, &array);
|
2008-09-21 13:24:00 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
2018-03-17 12:11:29 +00:00
|
|
|
hres = create_builtin_constructor(ctx, ArrayConstr_value, ArrayW, &ArrayConstr_info, PROPF_CONSTR|1, &array->dispex, ret);
|
2008-09-21 13:24:00 +00:00
|
|
|
|
2009-10-19 17:03:21 +00:00
|
|
|
jsdisp_release(&array->dispex);
|
2008-09-21 13:24:00 +00:00
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
2013-04-03 21:19:50 +00:00
|
|
|
HRESULT create_array(script_ctx_t *ctx, DWORD length, jsdisp_t **ret)
|
2008-09-21 13:24:00 +00:00
|
|
|
{
|
|
|
|
ArrayInstance *array;
|
|
|
|
HRESULT hres;
|
|
|
|
|
2009-08-22 15:25:26 +00:00
|
|
|
hres = alloc_array(ctx, NULL, &array);
|
2008-09-21 13:24:00 +00:00
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
array->length = length;
|
|
|
|
|
|
|
|
*ret = &array->dispex;
|
|
|
|
return S_OK;
|
|
|
|
}
|