2008-09-03 00:25:21 +02:00
|
|
|
/*
|
2011-12-30 11:20:43 +01:00
|
|
|
* Copyright 2008,2011 Jacek Caban for CodeWeavers
|
2008-09-03 00:25:21 +02:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2011-11-24 14:23:39 +01:00
|
|
|
#define OP_LIST \
|
|
|
|
X(add, 1, 0,0) \
|
2011-12-08 12:02:53 +01:00
|
|
|
X(and, 1, 0,0) \
|
2011-12-07 11:01:13 +01:00
|
|
|
X(array, 1, 0,0) \
|
2011-12-05 11:11:29 +01:00
|
|
|
X(assign, 1, 0,0) \
|
2018-03-01 23:58:38 +01:00
|
|
|
X(assign_call,1, ARG_UINT, 0) \
|
2011-11-24 14:23:39 +01:00
|
|
|
X(bool, 1, ARG_INT, 0) \
|
|
|
|
X(bneg, 1, 0,0) \
|
2011-12-07 11:00:44 +01:00
|
|
|
X(call, 1, ARG_UINT, ARG_UINT) \
|
2011-12-07 11:00:20 +01:00
|
|
|
X(call_member,1, ARG_UINT, ARG_UINT) \
|
2011-12-08 12:02:40 +01:00
|
|
|
X(carray, 1, ARG_UINT, 0) \
|
2018-03-01 23:58:38 +01:00
|
|
|
X(carray_set, 1, ARG_UINT, 0) \
|
2011-12-27 11:16:40 +01:00
|
|
|
X(case, 0, ARG_ADDR, 0) \
|
2011-12-20 11:47:23 +01:00
|
|
|
X(cnd_nz, 0, ARG_ADDR, 0) \
|
|
|
|
X(cnd_z, 0, ARG_ADDR, 0) \
|
2011-11-30 10:14:22 +01:00
|
|
|
X(delete, 1, 0,0) \
|
2011-12-15 15:42:27 +01:00
|
|
|
X(delete_ident,1,ARG_BSTR, 0) \
|
2011-11-29 11:09:04 +01:00
|
|
|
X(div, 1, 0,0) \
|
2011-12-28 12:06:28 +01:00
|
|
|
X(double, 1, ARG_DBL, 0) \
|
2017-05-01 18:31:02 +02:00
|
|
|
X(end_finally,0, 0,0) \
|
2017-05-01 18:30:06 +02:00
|
|
|
X(enter_catch,1, ARG_BSTR, 0) \
|
2011-11-25 12:07:30 +01:00
|
|
|
X(eq, 1, 0,0) \
|
2011-11-24 14:23:39 +01:00
|
|
|
X(eq2, 1, 0,0) \
|
2011-12-28 12:06:41 +01:00
|
|
|
X(forin, 0, ARG_ADDR, 0) \
|
2012-04-24 17:39:09 +02:00
|
|
|
X(func, 1, ARG_UINT, 0) \
|
2011-12-01 13:23:16 +01:00
|
|
|
X(gt, 1, 0,0) \
|
2011-12-05 11:11:29 +01:00
|
|
|
X(gteq, 1, 0,0) \
|
2011-11-28 12:08:54 +01:00
|
|
|
X(ident, 1, ARG_BSTR, 0) \
|
2011-12-07 11:00:20 +01:00
|
|
|
X(identid, 1, ARG_BSTR, ARG_INT) \
|
2011-11-24 14:23:39 +01:00
|
|
|
X(in, 1, 0,0) \
|
2011-12-12 14:43:54 +01:00
|
|
|
X(instanceof, 1, 0,0) \
|
2011-11-24 14:23:39 +01:00
|
|
|
X(int, 1, ARG_INT, 0) \
|
2011-11-28 12:04:51 +01:00
|
|
|
X(jmp, 0, ARG_ADDR, 0) \
|
2011-12-20 11:47:37 +01:00
|
|
|
X(jmp_z, 0, ARG_ADDR, 0) \
|
2016-08-04 13:40:44 +02:00
|
|
|
X(local, 1, ARG_INT, 0) \
|
2016-08-04 13:40:37 +02:00
|
|
|
X(local_ref, 1, ARG_INT, ARG_UINT) \
|
2011-12-09 11:04:57 +01:00
|
|
|
X(lshift, 1, 0,0) \
|
2011-12-01 13:22:52 +01:00
|
|
|
X(lt, 1, 0,0) \
|
2011-12-01 13:23:03 +01:00
|
|
|
X(lteq, 1, 0,0) \
|
2011-12-06 10:42:09 +01:00
|
|
|
X(member, 1, ARG_BSTR, 0) \
|
2011-12-07 11:00:20 +01:00
|
|
|
X(memberid, 1, ARG_UINT, 0) \
|
2011-11-25 12:06:30 +01:00
|
|
|
X(minus, 1, 0,0) \
|
2011-11-29 11:09:20 +01:00
|
|
|
X(mod, 1, 0,0) \
|
2011-11-29 11:08:54 +01:00
|
|
|
X(mul, 1, 0,0) \
|
2011-11-24 14:23:39 +01:00
|
|
|
X(neg, 1, 0,0) \
|
2011-11-25 12:07:30 +01:00
|
|
|
X(neq, 1, 0,0) \
|
2011-11-24 14:23:39 +01:00
|
|
|
X(neq2, 1, 0,0) \
|
2012-05-12 16:21:31 +02:00
|
|
|
X(new, 1, ARG_UINT, 0) \
|
2011-12-16 11:43:31 +01:00
|
|
|
X(new_obj, 1, 0,0) \
|
2011-11-24 14:23:39 +01:00
|
|
|
X(null, 1, 0,0) \
|
2019-03-01 17:43:52 +01:00
|
|
|
X(obj_prop, 1, ARG_STR, ARG_UINT) \
|
2011-11-29 11:09:35 +01:00
|
|
|
X(or, 1, 0,0) \
|
2012-12-14 11:06:43 +01:00
|
|
|
X(pop, 1, ARG_UINT, 0) \
|
2017-05-01 18:31:02 +02:00
|
|
|
X(pop_except, 0, ARG_ADDR, 0) \
|
2011-12-27 11:16:26 +01:00
|
|
|
X(pop_scope, 1, 0,0) \
|
2011-12-07 11:01:53 +01:00
|
|
|
X(postinc, 1, ARG_INT, 0) \
|
2011-12-08 12:02:08 +01:00
|
|
|
X(preinc, 1, ARG_INT, 0) \
|
2018-06-12 14:04:11 +02:00
|
|
|
X(push_acc, 1, 0,0) \
|
2017-05-01 18:30:44 +02:00
|
|
|
X(push_except,1, ARG_ADDR, ARG_UINT) \
|
2011-12-27 11:16:26 +01:00
|
|
|
X(push_scope, 1, 0,0) \
|
2012-05-12 16:21:44 +02:00
|
|
|
X(regexp, 1, ARG_STR, ARG_UINT) \
|
2011-12-08 12:03:22 +01:00
|
|
|
X(rshift, 1, 0,0) \
|
2011-12-09 11:04:24 +01:00
|
|
|
X(rshift2, 1, 0,0) \
|
2011-11-24 14:23:39 +01:00
|
|
|
X(str, 1, ARG_STR, 0) \
|
2011-11-24 14:24:14 +01:00
|
|
|
X(this, 1, 0,0) \
|
2011-12-28 12:06:17 +01:00
|
|
|
X(throw, 0, 0,0) \
|
2011-12-28 12:06:03 +01:00
|
|
|
X(throw_ref, 0, ARG_UINT, 0) \
|
2011-12-19 14:58:42 +01:00
|
|
|
X(throw_type, 0, ARG_UINT, ARG_STR) \
|
2011-11-24 14:23:39 +01:00
|
|
|
X(tonum, 1, 0,0) \
|
2011-12-13 11:57:11 +01:00
|
|
|
X(typeof, 1, 0,0) \
|
|
|
|
X(typeofid, 1, 0,0) \
|
|
|
|
X(typeofident,1, 0,0) \
|
2011-12-05 11:13:02 +01:00
|
|
|
X(refval, 1, 0,0) \
|
2017-05-01 18:31:02 +02:00
|
|
|
X(ret, 0, ARG_UINT, 0) \
|
2012-12-13 12:08:34 +01:00
|
|
|
X(setret, 1, 0,0) \
|
2011-11-25 12:06:05 +01:00
|
|
|
X(sub, 1, 0,0) \
|
2011-12-08 12:02:40 +01:00
|
|
|
X(undefined, 1, 0,0) \
|
2011-11-29 11:09:49 +01:00
|
|
|
X(void, 1, 0,0) \
|
|
|
|
X(xor, 1, 0,0)
|
2011-11-18 14:09:44 +01:00
|
|
|
|
|
|
|
typedef enum {
|
2011-11-24 14:23:39 +01:00
|
|
|
#define X(x,a,b,c) OP_##x,
|
2011-11-18 14:09:44 +01:00
|
|
|
OP_LIST
|
|
|
|
#undef X
|
|
|
|
OP_LAST
|
|
|
|
} jsop_t;
|
|
|
|
|
2019-12-11 15:08:22 +01:00
|
|
|
typedef struct _bytecode_t bytecode_t;
|
|
|
|
|
2011-11-18 14:09:44 +01:00
|
|
|
typedef union {
|
2011-11-28 12:08:54 +01:00
|
|
|
BSTR bstr;
|
2011-11-23 12:13:46 +01:00
|
|
|
LONG lng;
|
2012-10-11 12:17:17 +02:00
|
|
|
jsstr_t *str;
|
2011-11-28 12:03:57 +01:00
|
|
|
unsigned uint;
|
2011-11-18 14:09:44 +01:00
|
|
|
} instr_arg_t;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
ARG_NONE = 0,
|
2011-11-28 12:03:57 +01:00
|
|
|
ARG_ADDR,
|
2011-11-28 12:08:54 +01:00
|
|
|
ARG_BSTR,
|
2011-12-28 12:06:41 +01:00
|
|
|
ARG_DBL,
|
2011-12-16 11:42:57 +01:00
|
|
|
ARG_FUNC,
|
2011-11-28 12:03:57 +01:00
|
|
|
ARG_INT,
|
2011-12-28 12:06:41 +01:00
|
|
|
ARG_STR,
|
|
|
|
ARG_UINT
|
2011-11-18 14:09:44 +01:00
|
|
|
} instr_arg_type_t;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
jsop_t op;
|
2020-01-24 19:54:41 +01:00
|
|
|
unsigned loc;
|
2012-05-12 16:22:37 +02:00
|
|
|
union {
|
|
|
|
instr_arg_t arg[2];
|
|
|
|
double dbl;
|
|
|
|
} u;
|
2011-11-18 14:09:44 +01:00
|
|
|
} instr_t;
|
|
|
|
|
2018-11-30 22:44:32 +01:00
|
|
|
typedef enum {
|
|
|
|
PROPERTY_DEFINITION_VALUE,
|
|
|
|
PROPERTY_DEFINITION_GETTER,
|
|
|
|
PROPERTY_DEFINITION_SETTER
|
|
|
|
} property_definition_type_t;
|
|
|
|
|
2016-08-03 16:27:35 +02:00
|
|
|
typedef struct {
|
|
|
|
BSTR name;
|
|
|
|
int ref;
|
|
|
|
} local_ref_t;
|
|
|
|
|
2012-04-24 17:39:09 +02:00
|
|
|
typedef struct _function_code_t {
|
2012-04-24 17:39:25 +02:00
|
|
|
BSTR name;
|
2016-08-04 13:39:46 +02:00
|
|
|
int local_ref;
|
2015-06-02 14:45:10 +02:00
|
|
|
BSTR event_target;
|
2012-04-24 17:39:09 +02:00
|
|
|
unsigned instr_off;
|
|
|
|
|
2012-04-24 17:39:40 +02:00
|
|
|
const WCHAR *source;
|
|
|
|
unsigned source_len;
|
|
|
|
|
2012-04-24 17:39:09 +02:00
|
|
|
unsigned func_cnt;
|
|
|
|
struct _function_code_t *funcs;
|
2012-04-25 10:47:56 +02:00
|
|
|
|
|
|
|
unsigned var_cnt;
|
2016-08-04 13:39:46 +02:00
|
|
|
struct {
|
|
|
|
BSTR name;
|
|
|
|
int func_id; /* -1 if not a function */
|
|
|
|
} *variables;
|
2012-04-25 11:25:57 +02:00
|
|
|
|
|
|
|
unsigned param_cnt;
|
|
|
|
BSTR *params;
|
2016-08-03 16:27:35 +02:00
|
|
|
|
|
|
|
unsigned locals_cnt;
|
|
|
|
local_ref_t *locals;
|
2019-12-11 15:08:22 +01:00
|
|
|
|
|
|
|
bytecode_t *bytecode;
|
2012-04-24 17:39:09 +02:00
|
|
|
} function_code_t;
|
|
|
|
|
2016-08-04 13:39:46 +02:00
|
|
|
local_ref_t *lookup_local(const function_code_t*,const WCHAR*) DECLSPEC_HIDDEN;
|
|
|
|
|
2019-12-11 15:08:22 +01:00
|
|
|
struct _bytecode_t {
|
2012-03-12 19:24:22 +01:00
|
|
|
LONG ref;
|
2019-11-07 18:17:13 +01:00
|
|
|
BOOL is_persistent;
|
2012-03-12 19:24:22 +01:00
|
|
|
|
2011-11-18 14:09:44 +01:00
|
|
|
instr_t *instrs;
|
2013-02-15 14:04:14 +01:00
|
|
|
heap_pool_t heap;
|
2011-11-28 12:08:54 +01:00
|
|
|
|
2012-04-24 17:39:09 +02:00
|
|
|
function_code_t global_code;
|
|
|
|
|
2012-03-26 11:41:38 +02:00
|
|
|
WCHAR *source;
|
2020-01-30 15:49:58 +01:00
|
|
|
UINT64 source_context;
|
|
|
|
unsigned start_line;
|
2012-03-26 11:41:38 +02:00
|
|
|
|
2011-11-28 12:08:54 +01:00
|
|
|
BSTR *bstr_pool;
|
|
|
|
unsigned bstr_pool_size;
|
|
|
|
unsigned bstr_cnt;
|
2011-11-18 14:09:44 +01:00
|
|
|
|
2012-10-11 12:17:17 +02:00
|
|
|
jsstr_t **str_pool;
|
|
|
|
unsigned str_pool_size;
|
|
|
|
unsigned str_cnt;
|
|
|
|
|
2019-11-07 18:17:06 +01:00
|
|
|
struct list entry;
|
2019-12-11 15:08:22 +01:00
|
|
|
};
|
2008-09-05 02:37:59 +02:00
|
|
|
|
2020-01-30 15:49:58 +01:00
|
|
|
HRESULT compile_script(script_ctx_t*,const WCHAR*,UINT64,unsigned,const WCHAR*,const WCHAR*,BOOL,BOOL,bytecode_t**) DECLSPEC_HIDDEN;
|
2012-03-12 19:24:22 +01:00
|
|
|
void release_bytecode(bytecode_t*) DECLSPEC_HIDDEN;
|
2008-09-15 20:38:18 +02:00
|
|
|
|
2016-03-28 17:50:18 +02:00
|
|
|
static inline bytecode_t *bytecode_addref(bytecode_t *code)
|
2012-03-12 19:24:22 +01:00
|
|
|
{
|
|
|
|
code->ref++;
|
2016-03-28 17:50:18 +02:00
|
|
|
return code;
|
2012-03-12 19:24:22 +01:00
|
|
|
}
|
2008-09-03 00:25:21 +02:00
|
|
|
|
2008-09-09 01:24:22 +02:00
|
|
|
typedef struct _scope_chain_t {
|
|
|
|
LONG ref;
|
2012-09-13 14:34:25 +02:00
|
|
|
jsdisp_t *jsobj;
|
|
|
|
IDispatch *obj;
|
2016-07-28 18:44:43 +02:00
|
|
|
struct _call_frame_t *frame;
|
2008-09-09 01:24:22 +02:00
|
|
|
struct _scope_chain_t *next;
|
|
|
|
} scope_chain_t;
|
|
|
|
|
2011-04-21 11:22:45 +02:00
|
|
|
void scope_release(scope_chain_t*) DECLSPEC_HIDDEN;
|
2008-09-09 01:24:22 +02:00
|
|
|
|
2016-03-25 12:04:13 +01:00
|
|
|
static inline scope_chain_t *scope_addref(scope_chain_t *scope)
|
2008-09-09 01:24:22 +02:00
|
|
|
{
|
|
|
|
scope->ref++;
|
2016-03-25 12:04:13 +01:00
|
|
|
return scope;
|
2008-09-09 01:24:22 +02:00
|
|
|
}
|
|
|
|
|
2020-01-30 15:50:15 +01:00
|
|
|
struct _jsexcept_t {
|
2020-01-30 15:50:33 +01:00
|
|
|
HRESULT error;
|
|
|
|
|
2020-01-30 15:50:22 +01:00
|
|
|
BOOL valid_value;
|
2020-01-30 15:50:15 +01:00
|
|
|
jsval_t value;
|
2020-01-30 15:50:22 +01:00
|
|
|
|
2020-02-03 14:47:15 +01:00
|
|
|
jsstr_t *source;
|
2020-02-03 14:47:25 +01:00
|
|
|
jsstr_t *message;
|
2020-02-04 20:28:38 +01:00
|
|
|
jsstr_t *line;
|
2020-02-03 14:47:15 +01:00
|
|
|
|
|
|
|
bytecode_t *code;
|
|
|
|
unsigned loc;
|
|
|
|
|
2020-01-30 15:50:39 +01:00
|
|
|
BOOL enter_notified;
|
2020-01-30 15:50:15 +01:00
|
|
|
jsexcept_t *prev;
|
|
|
|
};
|
|
|
|
|
|
|
|
void enter_script(script_ctx_t*,jsexcept_t*) DECLSPEC_HIDDEN;
|
|
|
|
HRESULT leave_script(script_ctx_t*,HRESULT) DECLSPEC_HIDDEN;
|
|
|
|
void reset_ei(jsexcept_t*) DECLSPEC_HIDDEN;
|
2020-02-04 20:28:38 +01:00
|
|
|
void set_error_location(jsexcept_t*,bytecode_t*,unsigned,unsigned,jsstr_t*) DECLSPEC_HIDDEN;
|
2020-01-30 15:50:15 +01:00
|
|
|
|
2011-12-28 12:06:28 +01:00
|
|
|
typedef struct _except_frame_t except_frame_t;
|
2014-09-30 16:51:14 +02:00
|
|
|
struct _parser_ctx_t;
|
2011-12-19 14:58:42 +01:00
|
|
|
|
2016-03-25 12:02:35 +01:00
|
|
|
typedef struct _call_frame_t {
|
2016-03-25 12:03:45 +01:00
|
|
|
unsigned ip;
|
2016-03-25 12:03:35 +01:00
|
|
|
except_frame_t *except_frame;
|
2016-03-25 12:03:55 +01:00
|
|
|
unsigned stack_base;
|
2016-03-25 12:04:13 +01:00
|
|
|
scope_chain_t *scope;
|
2016-03-25 12:04:19 +01:00
|
|
|
scope_chain_t *base_scope;
|
2016-03-25 12:03:35 +01:00
|
|
|
|
2016-03-25 17:49:56 +01:00
|
|
|
jsval_t ret;
|
|
|
|
|
2016-03-25 17:49:37 +01:00
|
|
|
IDispatch *this_obj;
|
2016-03-28 17:51:28 +02:00
|
|
|
jsdisp_t *function_instance;
|
2016-03-25 17:49:48 +01:00
|
|
|
jsdisp_t *variable_obj;
|
2016-03-28 17:50:59 +02:00
|
|
|
jsdisp_t *arguments_obj;
|
2016-03-28 17:49:33 +02:00
|
|
|
DWORD flags;
|
2016-03-25 17:49:37 +01:00
|
|
|
|
2016-08-03 16:28:26 +02:00
|
|
|
unsigned argc;
|
2016-07-28 18:44:43 +02:00
|
|
|
unsigned pop_locals;
|
|
|
|
unsigned arguments_off;
|
2016-08-04 13:40:11 +02:00
|
|
|
unsigned variables_off;
|
|
|
|
unsigned pop_variables;
|
2016-07-28 18:44:43 +02:00
|
|
|
|
2016-03-25 12:02:48 +01:00
|
|
|
bytecode_t *bytecode;
|
2016-03-25 12:03:11 +01:00
|
|
|
function_code_t *function;
|
2016-03-25 12:02:48 +01:00
|
|
|
|
2016-03-25 12:02:35 +01:00
|
|
|
struct _call_frame_t *prev_frame;
|
|
|
|
} call_frame_t;
|
|
|
|
|
2016-03-28 17:49:33 +02:00
|
|
|
#define EXEC_GLOBAL 0x0001
|
2016-03-28 17:49:53 +02:00
|
|
|
#define EXEC_CONSTRUCTOR 0x0002
|
2016-03-29 17:49:01 +02:00
|
|
|
#define EXEC_RETURN_TO_INTERP 0x0004
|
2016-07-28 18:44:43 +02:00
|
|
|
#define EXEC_EVAL 0x0008
|
2016-03-28 17:49:33 +02:00
|
|
|
|
2016-03-28 17:50:59 +02:00
|
|
|
HRESULT exec_source(script_ctx_t*,DWORD,bytecode_t*,function_code_t*,scope_chain_t*,IDispatch*,
|
2016-08-03 16:28:19 +02:00
|
|
|
jsdisp_t*,jsdisp_t*,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
|
2016-03-28 17:51:28 +02:00
|
|
|
|
2012-04-25 11:25:57 +02:00
|
|
|
HRESULT create_source_function(script_ctx_t*,bytecode_t*,function_code_t*,scope_chain_t*,jsdisp_t**) DECLSPEC_HIDDEN;
|
2016-08-03 16:28:26 +02:00
|
|
|
HRESULT setup_arguments_object(script_ctx_t*,call_frame_t*) DECLSPEC_HIDDEN;
|
2016-08-03 16:28:19 +02:00
|
|
|
void detach_arguments_object(jsdisp_t*) DECLSPEC_HIDDEN;
|