Beispiel #1
0
static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, 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(ctx, NULL, NULL, &var_disp);
    if(FAILED(hres))
        return hres;

    hres = create_arguments(ctx, (IDispatch*)_IDispatchEx_(&function->dispex),
            dp, ei, caller, &arg_disp);
    if(SUCCEEDED(hres)) {
        VARIANT var;

        V_VT(&var) = VT_DISPATCH;
        V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(arg_disp);
        hres = jsdisp_propput_name(var_disp, argumentsW, &var, ei, caller);
        jsdisp_release(arg_disp);
    }

    if(SUCCEEDED(hres))
        hres = init_parameters(var_disp, function, dp, ei, caller);
    if(FAILED(hres)) {
        jsdisp_release(var_disp);
        return hres;
    }

    *ret = var_disp;
    return S_OK;
}
Beispiel #2
0
static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, unsigned argc, jsval_t *argv,
        jsval_t *r)
{
    jsdisp_t *var_disp, *arg_disp;
    exec_ctx_t *exec_ctx;
    scope_chain_t *scope;
    HRESULT hres;

    if(ctx->state == SCRIPTSTATE_UNINITIALIZED || ctx->state == SCRIPTSTATE_CLOSED) {
        WARN("Script engine state does not allow running code.\n");
        return E_UNEXPECTED;
    }

    if(!function->func_code) {
        FIXME("no source\n");
        return E_FAIL;
    }

    hres = create_var_disp(ctx, function, argc, argv, &var_disp);
    if(FAILED(hres))
        return hres;

    hres = create_arguments(ctx, function, var_disp, argc, argv, &arg_disp);
    if(FAILED(hres)) {
        jsdisp_release(var_disp);
        return hres;
    }

    hres = jsdisp_propput(var_disp, argumentsW, PROPF_DONTDELETE, jsval_obj(arg_disp));
    if(FAILED(hres)) {
        jsdisp_release(arg_disp);
        jsdisp_release(var_disp);
        return hres;
    }

    hres = scope_push(function->scope_chain, var_disp, to_disp(var_disp), &scope);
    if(SUCCEEDED(hres)) {
        hres = create_exec_ctx(ctx, this_obj, var_disp, scope, FALSE, &exec_ctx);
        scope_release(scope);

        if(SUCCEEDED(hres)) {
            jsdisp_t *prev_args;

            prev_args = function->arguments;
            function->arguments = arg_disp;
            hres = exec_source(exec_ctx, function->code, function->func_code, FALSE, r);
            function->arguments = prev_args;

            exec_release(exec_ctx);
        }
    }

    /* Reset arguments value to cut the reference cycle. Note that since all activation contexts have
     * their own arguments property, it's impossible to use prototype's one during name lookup */
    jsdisp_propput_name(var_disp, argumentsW, jsval_undefined());

    jsdisp_release(arg_disp);
    jsdisp_release(var_disp);
    return hres;
}
Beispiel #3
0
static HRESULT create_error(script_ctx_t *ctx, jsdisp_t *constr,
        UINT number, jsstr_t *msg, jsdisp_t **ret)
{
    jsdisp_t *err;
    HRESULT hres;

    hres = alloc_error(ctx, NULL, constr, &err);
    if(FAILED(hres))
        return hres;

    hres = jsdisp_propput_dontenum(err, numberW, jsval_number((INT)number));
    if(FAILED(hres)) {
        jsdisp_release(err);
        return hres;
    }

    hres = jsdisp_propput_name(err, messageW, jsval_string(msg));
    if(SUCCEEDED(hres))
        hres = jsdisp_propput_dontenum(err, descriptionW, jsval_string(msg));
    if(FAILED(hres)) {
        jsdisp_release(err);
        return hres;
    }

    *ret = err;
    return S_OK;
}
Beispiel #4
0
static HRESULT create_arguments(script_ctx_t *ctx, IDispatch *calee, DISPPARAMS *dp,
        jsexcept_t *ei, IServiceProvider *caller, DispatchEx **ret)
{
    DispatchEx *args;
    VARIANT var;
    DWORD i;
    HRESULT hres;

    static const WCHAR caleeW[] = {'c','a','l','l','e','e',0};

    args = heap_alloc_zero(sizeof(DispatchEx));
    if(!args)
        return E_OUTOFMEMORY;

    hres = init_dispex_from_constr(args, ctx, &Arguments_info, ctx->object_constr);
    if(FAILED(hres)) {
        heap_free(args);
        return hres;
    }

    for(i=0; i < arg_cnt(dp); i++) {
        hres = jsdisp_propput_idx(args, i, get_arg(dp,i), ei, caller);
        if(FAILED(hres))
            break;
    }

    if(SUCCEEDED(hres)) {
        V_VT(&var) = VT_I4;
        V_I4(&var) = arg_cnt(dp);
        hres = jsdisp_propput_name(args, lengthW, &var, ei, caller);

        if(SUCCEEDED(hres)) {
            V_VT(&var) = VT_DISPATCH;
            V_DISPATCH(&var) = calee;
            hres = jsdisp_propput_name(args, caleeW, &var, ei, caller);
        }
    }

    if(FAILED(hres)) {
        jsdisp_release(args);
        return hres;
    }

    *ret = args;
    return S_OK;
}
Beispiel #5
0
static HRESULT set_length(jsdisp_t *obj, DWORD length)
{
    if(is_class(obj, JSCLASS_ARRAY)) {
        ((ArrayInstance*)obj)->length = length;
        return S_OK;
    }

    return jsdisp_propput_name(obj, lengthW, jsval_number(length));
}
Beispiel #6
0
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);
}
Beispiel #7
0
static HRESULT Arguments_idx_put(jsdisp_t *jsdisp, unsigned idx, jsval_t val)
{
    ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp;

    TRACE("%p[%u] = %s\n", arguments, idx, debugstr_jsval(val));

    /* FIXME: Accessing by name won't work for duplicated argument names */
    return jsdisp_propput_name(arguments->var_obj, arguments->function->func_code->params[idx], val);
}
Beispiel #8
0
static HRESULT set_prototype(script_ctx_t *ctx, jsdisp_t *dispex, jsdisp_t *prototype)
{
    jsexcept_t jsexcept;
    VARIANT var;

    var_set_jsdisp(&var, prototype);
    memset(&jsexcept, 0, sizeof(jsexcept));

    return jsdisp_propput_name(dispex, prototypeW, &var, &jsexcept, NULL/*FIXME*/);
}
Beispiel #9
0
static HRESULT set_prototype(script_ctx_t *ctx, DispatchEx *dispex, DispatchEx *prototype)
{
    jsexcept_t jsexcept;
    VARIANT var;

    V_VT(&var) = VT_DISPATCH;
    V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(prototype);
    memset(&jsexcept, 0, sizeof(jsexcept));

    return jsdisp_propput_name(dispex, prototypeW, &var, &jsexcept, NULL/*FIXME*/);
}
Beispiel #10
0
static HRESULT set_length(jsdisp_t *obj, jsexcept_t *ei, DWORD length)
{
    VARIANT var;

    if(is_class(obj, JSCLASS_ARRAY)) {
        ((ArrayInstance*)obj)->length = length;
        return S_OK;
    }

    V_VT(&var) = VT_I4;
    V_I4(&var) = length;
    return jsdisp_propput_name(obj, lengthW, &var, ei);
}
Beispiel #11
0
static HRESULT create_arguments(script_ctx_t *ctx, IDispatch *calee, unsigned argc, jsval_t *argv, jsdisp_t **ret)
{
    jsdisp_t *args;
    DWORD i;
    HRESULT hres;

    static const WCHAR caleeW[] = {'c','a','l','l','e','e',0};

    args = heap_alloc_zero(sizeof(jsdisp_t));
    if(!args)
        return E_OUTOFMEMORY;

    hres = init_dispex_from_constr(args, ctx, &Arguments_info, ctx->object_constr);
    if(FAILED(hres)) {
        heap_free(args);
        return hres;
    }

    for(i=0; i < argc; i++) {
        hres = jsdisp_propput_idx(args, i, argv[i]);
        if(FAILED(hres))
            break;
    }

    if(SUCCEEDED(hres)) {
        hres = jsdisp_propput_name(args, lengthW, jsval_number(argc));

        if(SUCCEEDED(hres))
            hres = jsdisp_propput_name(args, caleeW, jsval_disp(calee));
    }

    if(FAILED(hres)) {
        jsdisp_release(args);
        return hres;
    }

    *ret = args;
    return S_OK;
}
Beispiel #12
0
HRESULT init_error_constr(script_ctx_t *ctx, DispatchEx *object_prototype)
{
    static const WCHAR ErrorW[] = {'E','r','r','o','r',0};
    static const WCHAR EvalErrorW[] = {'E','v','a','l','E','r','r','o','r',0};
    static const WCHAR RangeErrorW[] = {'R','a','n','g','e','E','r','r','o','r',0};
    static const WCHAR ReferenceErrorW[] = {'R','e','f','e','r','e','n','c','e','E','r','r','o','r',0};
    static const WCHAR RegExpErrorW[] = {'R','e','g','E','x','p','E','r','r','o','r',0};
    static const WCHAR SyntaxErrorW[] = {'S','y','n','t','a','x','E','r','r','o','r',0};
    static const WCHAR TypeErrorW[] = {'T','y','p','e','E','r','r','o','r',0};
    static const WCHAR URIErrorW[] = {'U','R','I','E','r','r','o','r',0};
    static const WCHAR *names[] = {ErrorW, EvalErrorW, RangeErrorW,
        ReferenceErrorW, RegExpErrorW, SyntaxErrorW, TypeErrorW, URIErrorW};
    DispatchEx **constr_addr[] = {&ctx->error_constr, &ctx->eval_error_constr,
        &ctx->range_error_constr, &ctx->reference_error_constr, &ctx->regexp_error_constr,
        &ctx->syntax_error_constr, &ctx->type_error_constr,
        &ctx->uri_error_constr};
    static builtin_invoke_t constr_val[] = {ErrorConstr_value, EvalErrorConstr_value,
        RangeErrorConstr_value, ReferenceErrorConstr_value, RegExpErrorConstr_value,
        SyntaxErrorConstr_value, TypeErrorConstr_value, URIErrorConstr_value};

    ErrorInstance *err;
    INT i;
    VARIANT v;
    HRESULT hres;

    for(i=0; i < sizeof(names)/sizeof(names[0]); i++) {
        hres = alloc_error(ctx, i==0 ? object_prototype : NULL, NULL, &err);
        if(FAILED(hres))
            return hres;

        V_VT(&v) = VT_BSTR;
        V_BSTR(&v) = SysAllocString(names[i]);
        if(!V_BSTR(&v)) {
            jsdisp_release(&err->dispex);
            return E_OUTOFMEMORY;
        }

        hres = jsdisp_propput_name(&err->dispex, nameW, &v, NULL/*FIXME*/, NULL/*FIXME*/);

        if(SUCCEEDED(hres))
            hres = create_builtin_function(ctx, constr_val[i], names[i], NULL,
                    PROPF_CONSTR|1, &err->dispex, constr_addr[i]);

        jsdisp_release(&err->dispex);
        VariantClear(&v);
        if(FAILED(hres))
            return hres;
    }

    return S_OK;
}
Beispiel #13
0
static HRESULT init_parameters(jsdisp_t *var_disp, FunctionInstance *function, unsigned argc, jsval_t *argv)
{
    DWORD i=0;
    HRESULT hres;

    for(i=0; i < function->func_code->param_cnt; i++) {
        hres = jsdisp_propput_name(var_disp, function->func_code->params[i],
                i < argc ? argv[i] : jsval_undefined());
        if(FAILED(hres))
            return hres;
    }

    return S_OK;
}
Beispiel #14
0
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);
}
Beispiel #15
0
static HRESULT init_parameters(jsdisp_t *var_disp, FunctionInstance *function, DISPPARAMS *dp,
        jsexcept_t *ei)
{
    VARIANT var_empty;
    DWORD cargs, i=0;
    HRESULT hres;

    V_VT(&var_empty) = VT_EMPTY;
    cargs = arg_cnt(dp);

    for(i=0; i < function->func_code->param_cnt; i++) {
        hres = jsdisp_propput_name(var_disp, function->func_code->params[i],
                i < cargs ? get_arg(dp,i) : &var_empty, ei);
        if(FAILED(hres))
            return hres;
    }

    return S_OK;
}
Beispiel #16
0
static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, jsdisp_t *arg_disp,
        unsigned argc, jsval_t *argv, jsdisp_t **ret)
{
    jsdisp_t *var_disp;
    HRESULT hres;

    hres = create_dispex(ctx, NULL, NULL, &var_disp);
    if(FAILED(hres))
        return hres;

    hres = jsdisp_propput_name(var_disp, argumentsW, jsval_obj(arg_disp));
    if(SUCCEEDED(hres))
        hres = init_parameters(var_disp, function, argc, argv);
    if(FAILED(hres)) {
        jsdisp_release(var_disp);
        return hres;
    }

    *ret = var_disp;
    return S_OK;
}
Beispiel #17
0
static HRESULT init_parameters(DispatchEx *var_disp, FunctionInstance *function, 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 = arg_cnt(dp);

    for(param = function->parameters; param; param = param->next) {
        hres = jsdisp_propput_name(var_disp, param->identifier,
                i < cargs ? get_arg(dp,i) : &var_empty, ei, caller);
        if(FAILED(hres))
            return hres;

        i++;
    }

    return S_OK;
}
Beispiel #18
0
static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, jsdisp_t *arg_disp,
        DISPPARAMS *dp, jsexcept_t *ei, IServiceProvider *caller, jsdisp_t **ret)
{
    jsdisp_t *var_disp;
    VARIANT var;
    HRESULT hres;

    hres = create_dispex(ctx, NULL, NULL, &var_disp);
    if(FAILED(hres))
        return hres;

    var_set_jsdisp(&var, arg_disp);
    hres = jsdisp_propput_name(var_disp, argumentsW, &var, ei, caller);
    if(SUCCEEDED(hres))
        hres = init_parameters(var_disp, function, dp, ei, caller);
    if(FAILED(hres)) {
        jsdisp_release(var_disp);
        return hres;
    }

    *ret = var_disp;
    return S_OK;
}
Beispiel #19
0
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;
}
Beispiel #20
0
static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input,
        const match_state_t *result, IDispatch **ret)
{
    jsdisp_t *array;
    jsstr_t *str;
    DWORD i;
    HRESULT hres = S_OK;

    static const WCHAR indexW[] = {'i','n','d','e','x',0};
    static const WCHAR inputW[] = {'i','n','p','u','t',0};
    static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0};
    static const WCHAR zeroW[] = {'0',0};

    hres = create_array(ctx, result->paren_count+1, &array);
    if(FAILED(hres))
        return hres;

    for(i=0; i < result->paren_count; i++) {
        if(result->parens[i].index != -1)
            str = jsstr_substr(input, result->parens[i].index, result->parens[i].length);
        else
            str = jsstr_empty();
        if(!str) {
            hres = E_OUTOFMEMORY;
            break;
        }

        hres = jsdisp_propput_idx(array, i+1, jsval_string(str));
        jsstr_release(str);
        if(FAILED(hres))
            break;
    }

    while(SUCCEEDED(hres)) {
        hres = jsdisp_propput_name(array, indexW, jsval_number(result->cp-input->str-result->match_len));
        if(FAILED(hres))
            break;

        hres = jsdisp_propput_name(array, lastIndexW, jsval_number(result->cp-input->str));
        if(FAILED(hres))
            break;

        hres = jsdisp_propput_name(array, inputW, jsval_string(jsstr_addref(input)));
        if(FAILED(hres))
            break;

        str = jsstr_alloc_len(result->cp-result->match_len, result->match_len);
        if(!str) {
            hres = E_OUTOFMEMORY;
            break;
        }
        hres = jsdisp_propput_name(array, zeroW, jsval_string(str));
        jsstr_release(str);
        break;
    }

    if(FAILED(hres)) {
        jsdisp_release(array);
        return hres;
    }

    *ret = to_disp(array);
    return S_OK;
}
Beispiel #21
0
HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval_t *r)
{
    static const WCHAR indexW[] = {'i','n','d','e','x',0};
    static const WCHAR inputW[] = {'i','n','p','u','t',0};
    static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0};

    RegExpInstance *regexp = (RegExpInstance*)re;
    match_result_t *match_result;
    unsigned match_cnt, i;
    jsdisp_t *array;
    HRESULT hres;

    if(!(regexp->jsregexp->flags & REG_GLOB)) {
        match_state_t *match;
        heap_pool_t *mark;

        mark = heap_pool_mark(&ctx->tmp_heap);
        match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, str->str);
        if(!match) {
            heap_pool_clear(mark);
            return E_OUTOFMEMORY;
        }

        hres = regexp_match_next(ctx, &regexp->dispex, 0, str, &match);
        if(FAILED(hres)) {
            heap_pool_clear(mark);
            return hres;
        }

        if(r) {
            if(hres == S_OK) {
                IDispatch *ret;

                hres = create_match_array(ctx, str, match, &ret);
                if(SUCCEEDED(hres))
                    *r = jsval_disp(ret);
            }else {
                *r = jsval_null();
            }
        }

        heap_pool_clear(mark);
        return S_OK;
    }

    hres = regexp_match(ctx, &regexp->dispex, str, FALSE, &match_result, &match_cnt);
    if(FAILED(hres))
        return hres;

    if(!match_cnt) {
        TRACE("no match\n");

        if(r)
            *r = jsval_null();
        return S_OK;
    }

    hres = create_array(ctx, match_cnt, &array);
    if(FAILED(hres))
        return hres;

    for(i=0; i < match_cnt; i++) {
        jsstr_t *tmp_str;

        tmp_str = jsstr_substr(str, match_result[i].index, match_result[i].length);
        if(!tmp_str) {
            hres = E_OUTOFMEMORY;
            break;
        }

        hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str));
        jsstr_release(tmp_str);
        if(FAILED(hres))
            break;
    }

    while(SUCCEEDED(hres)) {
        hres = jsdisp_propput_name(array, indexW, jsval_number(match_result[match_cnt-1].index));
        if(FAILED(hres))
            break;

        hres = jsdisp_propput_name(array, lastIndexW,
                jsval_number(match_result[match_cnt-1].index + match_result[match_cnt-1].length));
        if(FAILED(hres))
            break;

        hres = jsdisp_propput_name(array, inputW, jsval_string(str));
        break;
    }

    heap_free(match_result);

    if(SUCCEEDED(hres) && r)
        *r = jsval_obj(array);
    else
        jsdisp_release(array);
    return hres;
}
Beispiel #22
0
/* ECMA-262 5.1 Edition    15.12.1.2 */
static HRESULT parse_json_value(json_parse_ctx_t *ctx, jsval_t *r)
{
    HRESULT hres;

    switch(skip_spaces(ctx)) {

    /* JSONNullLiteral */
    case 'n':
        if(!is_keyword(ctx, nullW))
            break;
        *r = jsval_null();
        return S_OK;

    /* JSONBooleanLiteral */
    case 't':
        if(!is_keyword(ctx, trueW))
            break;
        *r = jsval_bool(TRUE);
        return S_OK;
    case 'f':
        if(!is_keyword(ctx, falseW))
            break;
        *r = jsval_bool(FALSE);
        return S_OK;

    /* JSONObject */
    case '{': {
        WCHAR *prop_name;
        jsdisp_t *obj;
        jsval_t val;

        hres = create_object(ctx->ctx, NULL, &obj);
        if(FAILED(hres))
            return hres;

        ctx->ptr++;
        if(skip_spaces(ctx) == '}') {
            ctx->ptr++;
            *r = jsval_obj(obj);
            return S_OK;
        }

        while(1) {
            if(*ctx->ptr != '"')
                break;
            hres = parse_json_string(ctx, &prop_name);
            if(FAILED(hres))
                break;

            if(skip_spaces(ctx) != ':') {
                FIXME("missing ':'\n");
                heap_free(prop_name);
                break;
            }

            ctx->ptr++;
            hres = parse_json_value(ctx, &val);
            if(SUCCEEDED(hres)) {
                hres = jsdisp_propput_name(obj, prop_name, val);
                jsval_release(val);
            }
            heap_free(prop_name);
            if(FAILED(hres))
                break;

            if(skip_spaces(ctx) == '}') {
                ctx->ptr++;
                *r = jsval_obj(obj);
                return S_OK;
            }

            if(*ctx->ptr++ != ',') {
                FIXME("expected ','\n");
                break;
            }
            skip_spaces(ctx);
        }

        jsdisp_release(obj);
        break;
    }

    /* JSONString */
    case '"': {
        WCHAR *string;
        jsstr_t *str;

        hres = parse_json_string(ctx, &string);
        if(FAILED(hres))
            return hres;

        /* FIXME: avoid reallocation */
        str = jsstr_alloc(string);
        heap_free(string);
        if(!str)
            return E_OUTOFMEMORY;

        *r = jsval_string(str);
        return S_OK;
    }

    /* JSONArray */
    case '[': {
        jsdisp_t *array;
        unsigned i = 0;
        jsval_t val;

        hres = create_array(ctx->ctx, 0, &array);
        if(FAILED(hres))
            return hres;

        ctx->ptr++;
        if(skip_spaces(ctx) == ']') {
            ctx->ptr++;
            *r = jsval_obj(array);
            return S_OK;
        }

        while(1) {
            hres = parse_json_value(ctx, &val);
            if(FAILED(hres))
                break;

            hres = jsdisp_propput_idx(array, i, val);
            jsval_release(val);
            if(FAILED(hres))
                break;

            if(skip_spaces(ctx) == ']') {
                ctx->ptr++;
                *r = jsval_obj(array);
                return S_OK;
            }

            if(*ctx->ptr != ',') {
                FIXME("expected ','\n");
                break;
            }

            ctx->ptr++;
            i++;
        }

        jsdisp_release(array);
        break;
    }

    /* JSONNumber */
    default: {
        int sign = 1;
        double n;

        if(*ctx->ptr == '-') {
            sign = -1;
            ctx->ptr++;
            skip_spaces(ctx);
        }

        if(!isdigitW(*ctx->ptr))
            break;

        if(*ctx->ptr == '0') {
            ctx->ptr++;
            n = 0;
            if(is_identifier_char(*ctx->ptr))
                break;
        }else {
            hres = parse_decimal(&ctx->ptr, ctx->end, &n);
            if(FAILED(hres))
                return hres;
        }

        *r = jsval_number(sign*n);
        return S_OK;
    }
    }

    FIXME("Syntax error at %s\n", debugstr_w(ctx->ptr));
    return E_FAIL;
}
Beispiel #23
0
/* ECMA-262 3rd Edition    15.4.4.12 */
static HRESULT Array_splice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
        VARIANT *retv, jsexcept_t *ei)
{
    DWORD length, start=0, delete_cnt=0, argc, i, add_args = 0;
    jsdisp_t *ret_array = NULL, *jsthis;
    VARIANT v;
    double d;
    int n;
    HRESULT hres = S_OK;

    TRACE("\n");

    hres = get_length(ctx, vthis, ei, &jsthis, &length);
    if(FAILED(hres))
        return hres;

    argc = arg_cnt(dp);
    if(argc >= 1) {
        hres = to_integer(ctx, get_arg(dp,0), ei, &d);
        if(FAILED(hres))
            return hres;

        if(is_int32(d)) {
            if((n = d) >= 0)
                start = min(n, length);
            else
                start = -n > length ? 0 : length + n;
        }else {
            start = d < 0.0 ? 0 : length;
        }
    }

    if(argc >= 2) {
        hres = to_integer(ctx, get_arg(dp,1), ei, &d);
        if(FAILED(hres))
            return hres;

        if(is_int32(d)) {
            if((n = d) > 0)
                delete_cnt = min(n, length-start);
        }else if(d > 0.0) {
            delete_cnt = length-start;
        }

        add_args = argc-2;
    }

    if(retv) {
        hres = create_array(ctx, 0, &ret_array);
        if(FAILED(hres))
            return hres;

        for(i=0; SUCCEEDED(hres) && i < delete_cnt; i++) {
            hres = jsdisp_get_idx(jsthis, start+i, &v, ei);
            if(hres == DISP_E_UNKNOWNNAME)
                hres = S_OK;
            else if(SUCCEEDED(hres))
                hres = jsdisp_propput_idx(ret_array, i, &v, ei);
        }

        if(SUCCEEDED(hres)) {
            V_VT(&v) = VT_I4;
            V_I4(&v) = delete_cnt;

            hres = jsdisp_propput_name(ret_array, lengthW, &v, ei);
        }
    }

    if(add_args < delete_cnt) {
        for(i = start; SUCCEEDED(hres) && i < length-delete_cnt; i++) {
            hres = jsdisp_get_idx(jsthis, i+delete_cnt, &v, ei);
            if(hres == DISP_E_UNKNOWNNAME)
                hres = jsdisp_delete_idx(jsthis, i+add_args);
            else if(SUCCEEDED(hres))
                hres = jsdisp_propput_idx(jsthis, i+add_args, &v, ei);
        }

        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--) {
            hres = jsdisp_get_idx(jsthis, i+delete_cnt-1, &v, ei);
            if(hres == DISP_E_UNKNOWNNAME)
                hres = jsdisp_delete_idx(jsthis, i+add_args-1);
            else if(SUCCEEDED(hres))
                hres = jsdisp_propput_idx(jsthis, i+add_args-1, &v, ei);
        }
    }

    for(i=0; SUCCEEDED(hres) && i < add_args; i++)
        hres = jsdisp_propput_idx(jsthis, start+i, get_arg(dp,i+2), ei);

    if(SUCCEEDED(hres)) {
        V_VT(&v) = VT_I4;
        V_I4(&v) = length-delete_cnt+add_args;
        hres = jsdisp_propput_name(jsthis, lengthW, &v, ei);
    }

    if(FAILED(hres)) {
        if(ret_array)
            jsdisp_release(ret_array);
        return hres;
    }

    if(retv)
        var_set_jsdisp(retv, ret_array);
    return S_OK;
}
Beispiel #24
0
/* ECMA-262 3rd Edition    15.4.4.12 */
static HRESULT Array_splice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
        jsval_t *r)
{
    DWORD length, start=0, delete_cnt=0, i, add_args = 0;
    jsdisp_t *ret_array = NULL, *jsthis;
    jsval_t val;
    double d;
    int n;
    HRESULT hres = S_OK;

    TRACE("\n");

    hres = get_length(ctx, vthis, &jsthis, &length);
    if(FAILED(hres))
        return hres;

    if(argc) {
        hres = to_integer(ctx, argv[0], &d);
        if(FAILED(hres))
            return hres;

        if(is_int32(d)) {
            if((n = d) >= 0)
                start = min(n, length);
            else
                start = -n > length ? 0 : length + n;
        }else {
            start = d < 0.0 ? 0 : length;
        }
    }

    if(argc >= 2) {
        hres = to_integer(ctx, argv[1], &d);
        if(FAILED(hres))
            return hres;

        if(is_int32(d)) {
            if((n = d) > 0)
                delete_cnt = min(n, length-start);
        }else if(d > 0.0) {
            delete_cnt = length-start;
        }

        add_args = argc-2;
    }

    if(r) {
        hres = create_array(ctx, 0, &ret_array);
        if(FAILED(hres))
            return hres;

        for(i=0; SUCCEEDED(hres) && i < delete_cnt; i++) {
            hres = jsdisp_get_idx(jsthis, start+i, &val);
            if(hres == DISP_E_UNKNOWNNAME) {
                hres = S_OK;
            }else if(SUCCEEDED(hres)) {
                hres = jsdisp_propput_idx(ret_array, i, val);
                jsval_release(val);
            }
        }

        if(SUCCEEDED(hres))
            hres = jsdisp_propput_name(ret_array, lengthW, jsval_number(delete_cnt));
    }

    if(add_args < delete_cnt) {
        for(i = start; SUCCEEDED(hres) && i < length-delete_cnt; i++) {
            hres = jsdisp_get_idx(jsthis, i+delete_cnt, &val);
            if(hres == DISP_E_UNKNOWNNAME) {
                hres = jsdisp_delete_idx(jsthis, i+add_args);
            }else if(SUCCEEDED(hres)) {
                hres = jsdisp_propput_idx(jsthis, i+add_args, val);
                jsval_release(val);
            }
        }

        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--) {
            hres = jsdisp_get_idx(jsthis, i+delete_cnt-1, &val);
            if(hres == DISP_E_UNKNOWNNAME) {
                hres = jsdisp_delete_idx(jsthis, i+add_args-1);
            }else if(SUCCEEDED(hres)) {
                hres = jsdisp_propput_idx(jsthis, i+add_args-1, val);
                jsval_release(val);
            }
        }
    }

    for(i=0; SUCCEEDED(hres) && i < add_args; i++)
        hres = jsdisp_propput_idx(jsthis, start+i, argv[i+2]);

    if(SUCCEEDED(hres))
        hres = jsdisp_propput_name(jsthis, lengthW, jsval_number(length-delete_cnt+add_args));

    if(FAILED(hres)) {
        if(ret_array)
            jsdisp_release(ret_array);
        return hres;
    }

    if(r)
        *r = jsval_obj(ret_array);
    return S_OK;
}
Beispiel #25
0
static inline HRESULT set_prototype(script_ctx_t *ctx, jsdisp_t *dispex, jsdisp_t *prototype)
{
    return jsdisp_propput_name(dispex, prototypeW, jsval_obj(prototype));
}