Compare commits
2 Commits
cellfix
...
warningfix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c9d039271 | ||
|
|
d4635f2a75 |
16
debug/js.c
16
debug/js.c
@@ -39,22 +39,20 @@ JSC_CCALL(os_calc_mem,
|
||||
JSC_SSCALL(os_eval,
|
||||
if (!str2) return JS_ThrowReferenceError(js, "Second argument should be the script.");
|
||||
if (!str) return JS_ThrowReferenceError(js, "First argument should be the name of the script.");
|
||||
JSValue bytecode = JS_Compile(js, str2, strlen(str2), str);
|
||||
if (JS_IsException(bytecode)) return bytecode;
|
||||
ret = JS_Integrate(js, bytecode, JS_NULL);
|
||||
ret = JS_Eval(js,str2,strlen(str2),str, 0);
|
||||
)
|
||||
|
||||
// Compile a string of JavaScript code into a function object.
|
||||
JSC_SSCALL(js_compile,
|
||||
if (!str2) return JS_ThrowReferenceError(js, "Second argument should be the script.");
|
||||
if (!str) return JS_ThrowReferenceError(js, "First argument should be the name of the script.");
|
||||
ret = JS_Compile(js, str2, strlen(str2), str);
|
||||
ret = JS_Eval(js, str2, strlen(str2), str, JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_FLAG_BACKTRACE_BARRIER);
|
||||
)
|
||||
|
||||
// Link compiled bytecode with environment and execute.
|
||||
JSC_CCALL(js_integrate,
|
||||
JSValue env = (argc > 1 && !JS_IsNull(argv[1])) ? argv[1] : JS_NULL;
|
||||
ret = JS_Integrate(js, argv[0], env);
|
||||
// Evaluate a function object in the current QuickJS context.
|
||||
JSC_CCALL(js_eval_compile,
|
||||
JS_DupValue(js,argv[0]);
|
||||
ret = JS_EvalFunction(js, argv[0]);
|
||||
)
|
||||
|
||||
// Compile a function object into a bytecode blob.
|
||||
@@ -94,7 +92,7 @@ static const JSCFunctionListEntry js_js_funcs[] = {
|
||||
MIST_FUNC_DEF(os, max_stacksize, 1),
|
||||
MIST_FUNC_DEF(os, eval, 2),
|
||||
MIST_FUNC_DEF(js, compile, 2),
|
||||
MIST_FUNC_DEF(js, integrate, 2),
|
||||
MIST_FUNC_DEF(js, eval_compile, 1),
|
||||
MIST_FUNC_DEF(js, compile_blob, 1),
|
||||
MIST_FUNC_DEF(js, compile_unblob, 1),
|
||||
MIST_FUNC_DEF(js, disassemble, 1),
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
(function engine() {
|
||||
// Hidden vars (os, actorsym, init, core_path) come from env
|
||||
var ACTORDATA = actorsym
|
||||
(function engine() {
|
||||
var _cell = globalThis.cell
|
||||
delete globalThis.cell
|
||||
var ACTORDATA = _cell.hidden.actorsym
|
||||
var SYSYM = '__SYSTEM__'
|
||||
|
||||
var _cell = {}
|
||||
var hidden = _cell.hidden
|
||||
|
||||
var os = hidden.os;
|
||||
|
||||
_cell.os = null
|
||||
|
||||
var dylib_ext
|
||||
|
||||
_cell.id ??= "newguy"
|
||||
|
||||
switch(os.platform()) {
|
||||
case 'Windows': dylib_ext = '.dll'; break;
|
||||
case 'macOS': dylib_ext = '.dylib'; break;
|
||||
@@ -21,7 +28,8 @@ function use_embed(name) {
|
||||
return load_internal("js_" + name + "_use")
|
||||
}
|
||||
|
||||
function logical(val1) {
|
||||
globalThis.logical = function(val1)
|
||||
{
|
||||
if (val1 == 0 || val1 == false || val1 == "false" || val1 == null)
|
||||
return false;
|
||||
if (val1 == 1 || val1 == true || val1 == "true")
|
||||
@@ -29,19 +37,19 @@ function logical(val1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function some(arr, pred) {
|
||||
globalThis.some = function(arr, pred) {
|
||||
return find(arr, pred) != null
|
||||
}
|
||||
|
||||
function every(arr, pred) {
|
||||
globalThis.every = function(arr, pred) {
|
||||
return find(arr, x => not(pred(x))) == null
|
||||
}
|
||||
|
||||
function starts_with(str, prefix) {
|
||||
globalThis.starts_with = function(str, prefix) {
|
||||
return search(str, prefix) == 0
|
||||
}
|
||||
|
||||
function ends_with(str, suffix) {
|
||||
globalThis.ends_with = function(str, suffix) {
|
||||
return search(str, suffix, -length(suffix)) != null
|
||||
}
|
||||
|
||||
@@ -91,7 +99,8 @@ function use_core(path) {
|
||||
|
||||
var blob = use_core('blob')
|
||||
|
||||
function actor() {
|
||||
globalThis.actor = function()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -99,7 +108,7 @@ var actor_mod = use_core('actor')
|
||||
var wota = use_core('wota')
|
||||
var nota = use_core('nota')
|
||||
|
||||
function is_actor(value) {
|
||||
globalThis.is_actor = function(value) {
|
||||
return is_object(value) && value[ACTORDATA]
|
||||
}
|
||||
|
||||
@@ -129,10 +138,10 @@ function console_rec(line, file, msg) {
|
||||
// time: [${time.text("mb d yyyy h:nn:ss")}]
|
||||
}
|
||||
|
||||
function log(name, args) {
|
||||
globalThis.log = function(name, args) {
|
||||
var caller = caller_data(1)
|
||||
var msg = args[0]
|
||||
|
||||
|
||||
switch(name) {
|
||||
case 'console':
|
||||
os.print(console_rec(caller.line, caller.file, msg))
|
||||
@@ -140,7 +149,7 @@ function log(name, args) {
|
||||
case 'error':
|
||||
msg = msg ?? Error()
|
||||
if (is_proto(msg, Error))
|
||||
msg = msg.name + ": " + msg.message + "\n" + msg.stack
|
||||
msg = msg.name + ": " + msg.message + "\n" + msg.stack
|
||||
os.print(console_rec(caller.line, caller.file, msg))
|
||||
break
|
||||
case 'system':
|
||||
@@ -192,8 +201,9 @@ function disrupt(err)
|
||||
|
||||
actor_mod.on_exception(disrupt)
|
||||
|
||||
_cell.args = init ?? {}
|
||||
_cell.id = "newguy"
|
||||
_cell.args = _cell.hidden.init
|
||||
_cell.args ??= {}
|
||||
_cell.id ??= "newguy"
|
||||
|
||||
function create_actor(desc = {id:guid()}) {
|
||||
var actor = {}
|
||||
@@ -214,30 +224,10 @@ var json = use_core('json')
|
||||
var time = use_core('time')
|
||||
|
||||
var pronto = use_core('pronto')
|
||||
var fallback = pronto.fallback
|
||||
var parallel = pronto.parallel
|
||||
var race = pronto.race
|
||||
var sequence = pronto.sequence
|
||||
|
||||
// Create runtime environment for modules
|
||||
var runtime_env = {
|
||||
logical: logical,
|
||||
some: some,
|
||||
every: every,
|
||||
starts_with: starts_with,
|
||||
ends_with: ends_with,
|
||||
actor: actor,
|
||||
is_actor: is_actor,
|
||||
log: log,
|
||||
send: send,
|
||||
fallback: fallback,
|
||||
parallel: parallel,
|
||||
race: race,
|
||||
sequence: sequence
|
||||
}
|
||||
|
||||
// Pass to os for shop to access
|
||||
os.runtime_env = runtime_env
|
||||
globalThis.fallback = pronto.fallback
|
||||
globalThis.parallel = pronto.parallel
|
||||
globalThis.race = pronto.race
|
||||
globalThis.sequence = pronto.sequence
|
||||
|
||||
$_.time_limit = function(requestor, seconds)
|
||||
{
|
||||
@@ -607,13 +597,13 @@ var need_stop = false
|
||||
|
||||
var replies = {}
|
||||
|
||||
function send(actor, message, reply) {
|
||||
globalThis.send = function send(actor, message, reply) {
|
||||
if (!is_object(actor))
|
||||
throw Error(`Must send to an actor object. Provided: ${actor}`);
|
||||
|
||||
|
||||
if (!is_object(message))
|
||||
throw Error('Message must be an object')
|
||||
var send_msg = {type:"user", data: message}
|
||||
var send = {type:"user", data: message}
|
||||
|
||||
if (actor[HEADER] && actor[HEADER].replycc) {
|
||||
var header = actor[HEADER]
|
||||
@@ -621,7 +611,7 @@ function send(actor, message, reply) {
|
||||
throw Error(`Supplied actor had a return, but it's not a valid actor! ${actor[HEADER]}`)
|
||||
|
||||
actor = header.replycc
|
||||
send_msg.return = header.reply
|
||||
send.return = header.reply
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
@@ -633,12 +623,12 @@ function send(actor, message, reply) {
|
||||
delete replies[id]
|
||||
}
|
||||
}, REPLYTIMEOUT)
|
||||
send_msg.reply = id
|
||||
send_msg.replycc = $_.self
|
||||
send.reply = id
|
||||
send.replycc = $_.self
|
||||
}
|
||||
|
||||
// Instead of sending immediately, queue it
|
||||
actor_prep(actor, send_msg);
|
||||
actor_prep(actor,send);
|
||||
}
|
||||
|
||||
stone(send)
|
||||
@@ -795,6 +785,8 @@ if (!locator) {
|
||||
if (!locator)
|
||||
throw Error(`Main program ${_cell.args.program} could not be found`)
|
||||
|
||||
stone(globalThis)
|
||||
|
||||
$_.clock(_ => {
|
||||
// Get capabilities for the main program
|
||||
var file_info = shop.file_info ? shop.file_info(locator.path) : null
|
||||
|
||||
@@ -379,16 +379,7 @@ Shop.get_script_capabilities = function(path) {
|
||||
}
|
||||
|
||||
function inject_env(inject) {
|
||||
// Start with runtime functions from engine
|
||||
var env = {}
|
||||
var rt = my$_.os ? my$_.os.runtime_env : null
|
||||
if (rt) {
|
||||
for (var k in rt) {
|
||||
env[k] = rt[k]
|
||||
}
|
||||
}
|
||||
|
||||
// Add capability injections
|
||||
for (var i = 0; i < length(inject); i++) {
|
||||
var inj = inject[i]
|
||||
var key = trim(inj, '$')
|
||||
@@ -400,17 +391,6 @@ function inject_env(inject) {
|
||||
|
||||
function inject_bindings_code(inject) {
|
||||
var lines = []
|
||||
|
||||
// Runtime function bindings
|
||||
var runtime_fns = ['logical', 'some', 'every', 'starts_with', 'ends_with',
|
||||
'actor', 'is_actor', 'log', 'send',
|
||||
'fallback', 'parallel', 'race', 'sequence']
|
||||
for (var i = 0; i < length(runtime_fns); i++) {
|
||||
var fn = runtime_fns[i]
|
||||
push(lines, `var ${fn} = env["${fn}"];`)
|
||||
}
|
||||
|
||||
// Capability bindings ($delay, $start, etc.)
|
||||
for (var i = 0; i < length(inject); i++) {
|
||||
var inj = inject[i]
|
||||
var key = trim(inj, '$')
|
||||
@@ -448,21 +428,22 @@ function resolve_mod_fn(path, pkg) {
|
||||
var inject = Shop.script_inject_for(file_info)
|
||||
var content = text(fd.slurp(path))
|
||||
var script = script_form(path, content, file_pkg, inject);
|
||||
|
||||
|
||||
var obj = pull_from_cache(stone(blob(script)))
|
||||
if (obj) {
|
||||
var fn = js.compile_unblob(obj)
|
||||
return js.integrate(fn, null)
|
||||
return js.eval_compile(fn)
|
||||
}
|
||||
|
||||
|
||||
// Compile name is just for debug/stack traces
|
||||
// var compile_name = pkg ? pkg + ':' + path : 'local:' + path
|
||||
var compile_name = path
|
||||
|
||||
|
||||
var fn = js.compile(compile_name, script)
|
||||
|
||||
|
||||
put_into_cache(stone(blob(script)), js.compile_blob(fn))
|
||||
|
||||
return js.integrate(fn, null)
|
||||
|
||||
return js.eval_compile(fn)
|
||||
}
|
||||
|
||||
// given a path and a package context
|
||||
|
||||
134
source/cell.c
134
source/cell.c
@@ -121,10 +121,13 @@ JSValue js_math_use(JSContext *js);
|
||||
|
||||
void script_startup(cell_rt *prt)
|
||||
{
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSRuntime *rt;
|
||||
|
||||
rt = JS_NewRuntime();
|
||||
|
||||
JSContext *js = JS_NewContextRaw(rt);
|
||||
JS_SetInterruptHandler(rt, (JSInterruptHandler *)actor_interrupt_cb, prt);
|
||||
|
||||
|
||||
JS_AddIntrinsicBaseObjects(js);
|
||||
JS_AddIntrinsicEval(js);
|
||||
JS_AddIntrinsicRegExp(js);
|
||||
@@ -136,7 +139,38 @@ void script_startup(cell_rt *prt)
|
||||
cell_rt *crt = JS_GetContextOpaque(js);
|
||||
JS_FreeValue(js, js_blob_use(js));
|
||||
|
||||
// Load and compile engine.cm
|
||||
JSValue globalThis = JS_GetGlobalObject(js);
|
||||
|
||||
JSValue cell = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js,globalThis,"cell", cell);
|
||||
|
||||
JSValue hidden_fn = JS_NewObject(js);
|
||||
|
||||
JS_SetPropertyStr(js, cell, "hidden", hidden_fn);
|
||||
JS_SetPropertyStr(js, hidden_fn, "os", js_os_use(js));
|
||||
|
||||
crt->actor_sym = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, hidden_fn, "actorsym", JS_DupValue(js,crt->actor_sym));
|
||||
|
||||
if (crt->init_wota) {
|
||||
JS_SetPropertyStr(js, hidden_fn, "init", wota2value(js, crt->init_wota));
|
||||
// init wota can now be freed
|
||||
free(crt->init_wota);
|
||||
crt->init_wota = NULL;
|
||||
}
|
||||
|
||||
// Store the core path for scripts to use
|
||||
JSValue js_cell = JS_GetPropertyStr(js, globalThis, "cell");
|
||||
JSValue hidden = JS_GetPropertyStr(js, js_cell, "hidden");
|
||||
if (core_path) {
|
||||
JS_SetPropertyStr(js, hidden, "core_path", JS_NewString(js, core_path));
|
||||
}
|
||||
JS_FreeValue(js, hidden);
|
||||
JS_FreeValue(js, js_cell);
|
||||
|
||||
JS_FreeValue(js, globalThis);
|
||||
|
||||
// Load engine.cm from the core directory
|
||||
size_t engine_size;
|
||||
char *data = load_core_file(ENGINE, &engine_size);
|
||||
if (!data) {
|
||||
@@ -144,39 +178,9 @@ void script_startup(cell_rt *prt)
|
||||
return;
|
||||
}
|
||||
|
||||
JSValue bytecode = JS_Compile(js, data, engine_size, ENGINE);
|
||||
free(data);
|
||||
if (JS_IsException(bytecode)) {
|
||||
uncaught_exception(js, bytecode);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create hidden environment
|
||||
JSValue hidden_env = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, hidden_env, "os", js_os_use(js));
|
||||
|
||||
crt->actor_sym = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, hidden_env, "actorsym", JS_DupValue(js, crt->actor_sym));
|
||||
|
||||
// Always set init (even if null)
|
||||
if (crt->init_wota) {
|
||||
JS_SetPropertyStr(js, hidden_env, "init", wota2value(js, crt->init_wota));
|
||||
free(crt->init_wota);
|
||||
crt->init_wota = NULL;
|
||||
} else {
|
||||
JS_SetPropertyStr(js, hidden_env, "init", JS_NULL);
|
||||
}
|
||||
|
||||
if (core_path) {
|
||||
JS_SetPropertyStr(js, hidden_env, "core_path", JS_NewString(js, core_path));
|
||||
}
|
||||
|
||||
// Stone the environment
|
||||
hidden_env = JS_Stone(js, hidden_env);
|
||||
|
||||
// Integrate and run
|
||||
crt->state = ACTOR_RUNNING;
|
||||
JSValue v = JS_Integrate(js, bytecode, hidden_env);
|
||||
JSValue v = JS_Eval(js, data, engine_size, ENGINE, 0);
|
||||
free(data);
|
||||
uncaught_exception(js, v);
|
||||
crt->state = ACTOR_IDLE;
|
||||
set_actor_state(crt);
|
||||
@@ -282,21 +286,55 @@ static int run_eval(const char *script_or_file, int print_bytecode)
|
||||
|
||||
int result = 0;
|
||||
|
||||
JSValue bytecode = JS_Compile(ctx, script, strlen(script), filename);
|
||||
if (JS_IsException(bytecode)) {
|
||||
uncaught_exception(ctx, bytecode);
|
||||
result = 1;
|
||||
} else {
|
||||
if (print_bytecode) {
|
||||
printf("=== Compiled Bytecode ===\n");
|
||||
JS_DumpFunctionBytecode(ctx, bytecode);
|
||||
}
|
||||
JSValue v = JS_Integrate(ctx, bytecode, JS_NULL);
|
||||
if (JS_IsException(v)) {
|
||||
uncaught_exception(ctx, v);
|
||||
if (print_bytecode) {
|
||||
/* Compile only, then dump and optionally execute */
|
||||
JSValue func = JS_Eval(ctx, script, strlen(script), filename, JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
if (JS_IsException(func)) {
|
||||
uncaught_exception(ctx, func);
|
||||
result = 1;
|
||||
} else {
|
||||
JS_FreeValue(ctx, v);
|
||||
printf("=== Compiled Bytecode ===\n");
|
||||
JS_DumpFunctionBytecode(ctx, func);
|
||||
|
||||
/* Link - resolve global references */
|
||||
JSValue linked = JS_LinkFunction(ctx, func);
|
||||
if (JS_IsException(linked)) {
|
||||
uncaught_exception(ctx, linked);
|
||||
result = 1;
|
||||
} else {
|
||||
printf("\n=== Linked Bytecode ===\n");
|
||||
JS_DumpFunctionBytecode(ctx, linked);
|
||||
|
||||
/* Now execute the linked bytecode */
|
||||
JSValue v = JS_EvalFunction(ctx, linked);
|
||||
if (JS_IsException(v)) {
|
||||
uncaught_exception(ctx, v);
|
||||
result = 1;
|
||||
} else {
|
||||
JS_FreeValue(ctx, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Compile, link, execute */
|
||||
JSValue func = JS_Eval(ctx, script, strlen(script), filename, JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
if (JS_IsException(func)) {
|
||||
uncaught_exception(ctx, func);
|
||||
result = 1;
|
||||
} else {
|
||||
JSValue linked = JS_LinkFunction(ctx, func);
|
||||
if (JS_IsException(linked)) {
|
||||
uncaught_exception(ctx, linked);
|
||||
result = 1;
|
||||
} else {
|
||||
JSValue v = JS_EvalFunction(ctx, linked);
|
||||
if (JS_IsException(v)) {
|
||||
uncaught_exception(ctx, v);
|
||||
result = 1;
|
||||
} else {
|
||||
JS_FreeValue(ctx, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -193,10 +193,8 @@ DEF( strict_neq, 1, 2, 1, none)
|
||||
DEF( and, 1, 2, 1, none)
|
||||
DEF( xor, 1, 2, 1, none)
|
||||
DEF( or, 1, 2, 1, none)
|
||||
/* format template - format_string_cpool_idx(u32), expr_count(u16)
|
||||
Note: n_push=2 ensures stack has room for temp [format_str, arr] pair,
|
||||
even though we only leave 1 value (the result) on the stack. */
|
||||
DEF(format_template, 7, 0, 1, npop_u16)
|
||||
/* template literal concatenation - pops N parts, pushes concatenated string */
|
||||
DEF(template_concat, 3, 0, 1, npop_u16)
|
||||
|
||||
/* Upvalue access (closures via outer_frame chain) */
|
||||
DEF( get_up, 4, 0, 1, u8_u16) /* depth:u8, slot:u16 -> value */
|
||||
|
||||
1931
source/quickjs.c
1931
source/quickjs.c
File diff suppressed because it is too large
Load Diff
111
source/quickjs.h
111
source/quickjs.h
@@ -176,8 +176,6 @@ void JS_DeleteGCRef(JSContext *ctx, JSGCRef *ref);
|
||||
Value Extraction
|
||||
============================================================ */
|
||||
|
||||
#define JS_VALUE_GET_INT(v) ((int)(v) >> 1)
|
||||
|
||||
/* Get primary tag (low 2-3 bits) */
|
||||
static inline int
|
||||
JS_VALUE_GET_TAG (JSValue v) {
|
||||
@@ -334,13 +332,18 @@ JS_IsShortFloat (JSValue v) {
|
||||
#define JS_DEFAULT_STACK_SIZE (1024 * 1024)
|
||||
#endif
|
||||
|
||||
/* Internal eval flags */
|
||||
/* JS_Eval() flags */
|
||||
#define JS_EVAL_TYPE_GLOBAL (0 << 0) /* global code (default) */
|
||||
#define JS_EVAL_TYPE_DIRECT (2 << 0) /* direct call (internal use) */
|
||||
#define JS_EVAL_TYPE_INDIRECT (3 << 0) /* indirect call (internal use) */
|
||||
#define JS_EVAL_TYPE_MASK (3 << 0)
|
||||
#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5) /* internal use */
|
||||
#define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6) /* internal use */
|
||||
|
||||
/* compile but do not run. The result is an object with a
|
||||
JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed
|
||||
with JS_EvalFunction(). */
|
||||
#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5)
|
||||
/* don't include the stack frames before this eval in the Error() backtraces */
|
||||
#define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6)
|
||||
|
||||
typedef JSValue JSCFunction (JSContext *ctx, JSValue this_val, int argc,
|
||||
JSValue *argv);
|
||||
@@ -722,17 +725,12 @@ int JS_SetPropertyInt64 (JSContext *ctx, JSValue this_obj, int64_t idx, JSValue
|
||||
JSValue JS_GetOwnPropertyNames (JSContext *ctx, JSValue obj);
|
||||
|
||||
JSValue JS_Call (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv);
|
||||
|
||||
/* Compile source code to bytecode without executing.
|
||||
'input' must be zero terminated i.e. input[input_len] = '\0'.
|
||||
Returns unlinked bytecode on success, JS_EXCEPTION on error. */
|
||||
JSValue JS_Compile (JSContext *ctx, const char *input, size_t input_len,
|
||||
const char *filename);
|
||||
|
||||
/* Link compiled bytecode with environment and execute.
|
||||
env should be stoned record or null.
|
||||
Variables resolve: env first, then global intrinsics. */
|
||||
JSValue JS_Integrate (JSContext *ctx, JSValue bytecode, JSValue env);
|
||||
/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */
|
||||
JSValue JS_Eval (JSContext *ctx, const char *input, size_t input_len,
|
||||
const char *filename, int eval_flags);
|
||||
/* same as JS_Eval() but with an explicit 'this_obj' parameter */
|
||||
JSValue JS_EvalThis (JSContext *ctx, JSValue this_obj, const char *input,
|
||||
size_t input_len, const char *filename, int eval_flags);
|
||||
JSValue JS_GetGlobalObject (JSContext *ctx);
|
||||
void JS_SetOpaque (JSValue obj, void *opaque);
|
||||
void *JS_GetOpaque (JSValue obj, JSClassID class_id);
|
||||
@@ -779,9 +777,27 @@ uint8_t *JS_WriteObject2 (JSContext *ctx, size_t *psize, JSValue obj,
|
||||
#define JS_READ_OBJ_REFERENCE (1 << 3) /* allow object references */
|
||||
JSValue JS_ReadObject (JSContext *ctx, const uint8_t *buf, size_t buf_len,
|
||||
int flags);
|
||||
/* instantiate and evaluate a bytecode function. Only used when
|
||||
reading a script or module with JS_ReadObject() */
|
||||
JSValue JS_EvalFunction (JSContext *ctx, JSValue fun_obj);
|
||||
|
||||
/* Eval function with environment record for variable resolution.
|
||||
The env must be a stoned record. Variables are resolved env first,
|
||||
then global intrinsics. */
|
||||
JSValue JS_EvalFunctionEnv (JSContext *ctx, JSValue fun_obj, JSValue env);
|
||||
|
||||
/* Dump bytecode of a compiled function (for debugging) */
|
||||
void JS_DumpFunctionBytecode (JSContext *ctx, JSValue func_val);
|
||||
|
||||
/* Link compiled bytecode to context - resolves global references.
|
||||
Returns linked bytecode on success, JS_EXCEPTION on link error. */
|
||||
JSValue JS_LinkFunction (JSContext *ctx, JSValue func_val);
|
||||
|
||||
/* Link compiled bytecode with environment record for variable resolution.
|
||||
Variables are resolved: env first, then global intrinsics.
|
||||
Returns linked bytecode on success, JS_EXCEPTION on link error. */
|
||||
JSValue JS_LinkFunctionEnv (JSContext *ctx, JSValue func_val, JSValue env);
|
||||
|
||||
/* C function definition */
|
||||
typedef enum JSCFunctionEnum {
|
||||
JS_CFUNC_generic,
|
||||
@@ -793,7 +809,14 @@ typedef enum JSCFunctionEnum {
|
||||
JS_CFUNC_1, /* JSValue f(ctx, this_val, arg0) */
|
||||
JS_CFUNC_2, /* JSValue f(ctx, this_val, arg0, arg1) */
|
||||
JS_CFUNC_3, /* JSValue f(ctx, this_val, arg0, arg1, arg2) */
|
||||
JS_CFUNC_4
|
||||
JS_CFUNC_4,
|
||||
/* Pure functions (no this_val) - for global utility functions */
|
||||
JS_CFUNC_PURE, /* JSValue f(ctx, argc, argv) - generic pure */
|
||||
JS_CFUNC_PURE_0, /* JSValue f(ctx) */
|
||||
JS_CFUNC_PURE_1, /* JSValue f(ctx, arg0) */
|
||||
JS_CFUNC_PURE_2, /* JSValue f(ctx, arg0, arg1) */
|
||||
JS_CFUNC_PURE_3, /* JSValue f(ctx, arg0, arg1, arg2) */
|
||||
JS_CFUNC_PURE_4 /* JSValue f(ctx, arg0, arg1, arg2, arg3) */
|
||||
} JSCFunctionEnum;
|
||||
|
||||
/* Fixed-arity C function types for fast paths */
|
||||
@@ -809,6 +832,16 @@ typedef JSValue JSCFunction4 (JSContext *ctx, JSValue this_val,
|
||||
JSValue arg0, JSValue arg1,
|
||||
JSValue arg2, JSValue arg3);
|
||||
|
||||
/* Pure function types (no this_val) */
|
||||
typedef JSValue JSCFunctionPure (JSContext *ctx, int argc, JSValue *argv);
|
||||
typedef JSValue JSCFunctionPure0 (JSContext *ctx);
|
||||
typedef JSValue JSCFunctionPure1 (JSContext *ctx, JSValue arg0);
|
||||
typedef JSValue JSCFunctionPure2 (JSContext *ctx, JSValue arg0, JSValue arg1);
|
||||
typedef JSValue JSCFunctionPure3 (JSContext *ctx, JSValue arg0, JSValue arg1,
|
||||
JSValue arg2);
|
||||
typedef JSValue JSCFunctionPure4 (JSContext *ctx, JSValue arg0, JSValue arg1,
|
||||
JSValue arg2, JSValue arg3);
|
||||
|
||||
typedef union JSCFunctionType {
|
||||
JSCFunction *generic;
|
||||
JSValue (*generic_magic) (JSContext *ctx, JSValue this_val, int argc,
|
||||
@@ -821,6 +854,13 @@ typedef union JSCFunctionType {
|
||||
JSCFunction2 *f2;
|
||||
JSCFunction3 *f3;
|
||||
JSCFunction4 *f4;
|
||||
/* Pure function pointers */
|
||||
JSCFunctionPure *pure;
|
||||
JSCFunctionPure0 *pure0;
|
||||
JSCFunctionPure1 *pure1;
|
||||
JSCFunctionPure2 *pure2;
|
||||
JSCFunctionPure3 *pure3;
|
||||
JSCFunctionPure4 *pure4;
|
||||
} JSCFunctionType;
|
||||
|
||||
JSValue JS_NewCFunction2 (JSContext *ctx, JSCFunction *func, const char *name,
|
||||
@@ -937,6 +977,43 @@ typedef struct JSCFunctionListEntry {
|
||||
.u \
|
||||
= {.func = { 3, JS_CFUNC_3, { .f3 = func1 } } } \
|
||||
}
|
||||
/* Pure function (no this_val) macros */
|
||||
#define JS_CFUNC_PURE_DEF(name, length, func1) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, 0, \
|
||||
.u \
|
||||
= {.func = { length, JS_CFUNC_PURE, { .pure = func1 } } } \
|
||||
}
|
||||
#define JS_CFUNC_PURE0_DEF(name, func1) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, 0, \
|
||||
.u \
|
||||
= {.func = { 0, JS_CFUNC_PURE_0, { .pure0 = func1 } } } \
|
||||
}
|
||||
#define JS_CFUNC_PURE1_DEF(name, func1) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, 0, \
|
||||
.u \
|
||||
= {.func = { 1, JS_CFUNC_PURE_1, { .pure1 = func1 } } } \
|
||||
}
|
||||
#define JS_CFUNC_PURE2_DEF(name, func1) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, 0, \
|
||||
.u \
|
||||
= {.func = { 2, JS_CFUNC_PURE_2, { .pure2 = func1 } } } \
|
||||
}
|
||||
#define JS_CFUNC_PURE3_DEF(name, func1) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, 0, \
|
||||
.u \
|
||||
= {.func = { 3, JS_CFUNC_PURE_3, { .pure3 = func1 } } } \
|
||||
}
|
||||
#define JS_CFUNC_PURE4_DEF(name, func1) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, 0, \
|
||||
.u \
|
||||
= {.func = { 4, JS_CFUNC_PURE_4, { .pure4 = func1 } } } \
|
||||
}
|
||||
#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, magic, .u = { \
|
||||
|
||||
Reference in New Issue
Block a user