static void O_create(js_State *J) { js_Object *obj; js_Object *proto; js_Object *props; js_Property *ref; if (js_isobject(J, 1)) proto = js_toobject(J, 1); else if (js_isnull(J, 1)) proto = NULL; else js_typeerror(J, "not an object or null"); obj = jsV_newobject(J, JS_COBJECT, proto); js_pushobject(J, obj); if (js_isdefined(J, 2)) { if (!js_isobject(J, 2)) js_typeerror(J, "not an object"); props = js_toobject(J, 2); for (ref = props->head; ref; ref = ref->next) { if (!(ref->atts & JS_DONTENUM)) { if (ref->value.type != JS_TOBJECT) js_typeerror(J, "not an object"); ToPropertyDescriptor(J, obj, ref->name, ref->value.u.object); } } } }
int js_instanceof(js_State *J) { js_Object *O, *V; if (!js_iscallable(J, -1)) js_typeerror(J, "instanceof: invalid operand"); if (!js_isobject(J, -2)) return 0; js_getproperty(J, -1, "prototype"); if (!js_isobject(J, -1)) js_typeerror(J, "instanceof: 'prototype' property is not an object"); O = js_toobject(J, -1); js_pop(J, 1); V = js_toobject(J, -2); while (V) { V = V->prototype; if (O == V) return 1; } return 0; }
static void O_defineProperty(js_State *J) { if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); if (!js_isobject(J, 3)) js_typeerror(J, "not an object"); ToPropertyDescriptor(J, js_toobject(J, 1), js_tostring(J, 2), js_toobject(J, 3)); js_copy(J, 1); }
void js_construct(js_State *J, int n) { js_Object *obj; js_Object *prototype; js_Object *newobj; if (!js_iscallable(J, -n-1)) js_typeerror(J, "called object is not a function"); obj = js_toobject(J, -n-1); /* built-in constructors create their own objects, give them a 'null' this */ if (obj->type == JS_CCFUNCTION && obj->u.c.constructor) { int savebot = BOT; js_pushnull(J); if (n > 0) js_rot(J, n + 1); BOT = TOP - n - 1; jsR_pushtrace(J, obj->u.c.name, "[C]", 0); jsR_callcfunction(J, n, obj->u.c.length, obj->u.c.constructor); --J->tracetop; BOT = savebot; return; } /* extract the function object's prototype property */ js_getproperty(J, -n - 1, "prototype"); if (js_isobject(J, -1)) prototype = js_toobject(J, -1); else prototype = J->Object_prototype; js_pop(J, 1); /* create a new object with above prototype, and shift it into the 'this' slot */ newobj = jsV_newobject(J, JS_COBJECT, prototype); js_pushobject(J, newobj); if (n > 0) js_rot(J, n + 1); /* call the function */ js_call(J, n); /* if result is not an object, return the original object we created */ if (!js_isobject(J, -1)) { js_pop(J, 1); js_pushobject(J, newobj); } }
static void Op_isPrototypeOf(js_State *J) { js_Object *self = js_toobject(J, 0); if (js_isobject(J, 1)) { js_Object *V = js_toobject(J, 1); do { V = V->prototype; if (V == self) { js_pushboolean(J, 1); return; } } while (V); } js_pushboolean(J, 0); }
void js_call(js_State *J, int n) { js_Object *obj; int savebot; if (!js_iscallable(J, -n-2)) js_typeerror(J, "called object is not a function"); obj = js_toobject(J, -n-2); savebot = BOT; BOT = TOP - n - 1; if (obj->type == JS_CFUNCTION) { jsR_pushtrace(J, obj->u.f.function->name, obj->u.f.function->filename, obj->u.f.function->line); if (obj->u.f.function->lightweight) jsR_calllwfunction(J, n, obj->u.f.function, obj->u.f.scope); else jsR_callfunction(J, n, obj->u.f.function, obj->u.f.scope); --J->tracetop; } else if (obj->type == JS_CSCRIPT) { jsR_pushtrace(J, obj->u.f.function->name, obj->u.f.function->filename, obj->u.f.function->line); jsR_callscript(J, n, obj->u.f.function, obj->u.f.scope); --J->tracetop; } else if (obj->type == JS_CCFUNCTION) { jsR_pushtrace(J, obj->u.c.name, "[C]", 0); jsR_callcfunction(J, n, obj->u.c.length, obj->u.c.function); --J->tracetop; } BOT = savebot; }
static void Fp_toString(js_State *J) { js_Object *self = js_toobject(J, 0); char *s; unsigned int i, n; if (!js_iscallable(J, 0)) js_typeerror(J, "not a function"); if (self->type == JS_CFUNCTION || self->type == JS_CSCRIPT) { js_Function *F = self->u.f.function; n = strlen("function () { ... }"); n += strlen(F->name); for (i = 0; i < F->numparams; ++i) n += strlen(F->vartab[i]) + 1; s = js_malloc(J, n); strcpy(s, "function "); strcat(s, F->name); strcat(s, "("); for (i = 0; i < F->numparams; ++i) { if (i > 0) strcat(s, ","); strcat(s, F->vartab[i]); } strcat(s, ") { ... }"); if (js_try(J)) { js_free(J, s); js_throw(J); } js_pushstring(J, s); js_free(J, s); js_endtry(J); } else { js_pushliteral(J, "function () { ... }"); } }
static void Op_toString(js_State *J) { js_Object *self = js_toobject(J, 0); switch (self->type) { case JS_COBJECT: js_pushliteral(J, "[object Object]"); break; case JS_CARRAY: js_pushliteral(J, "[object Array]"); break; case JS_CFUNCTION: js_pushliteral(J, "[object Function]"); break; case JS_CSCRIPT: js_pushliteral(J, "[object Function]"); break; case JS_CCFUNCTION: js_pushliteral(J, "[object Function]"); break; case JS_CERROR: js_pushliteral(J, "[object Error]"); break; case JS_CBOOLEAN: js_pushliteral(J, "[object Boolean]"); break; case JS_CNUMBER: js_pushliteral(J, "[object Number]"); break; case JS_CSTRING: js_pushliteral(J, "[object String]"); break; case JS_CREGEXP: js_pushliteral(J, "[object RegExp]"); break; case JS_CDATE: js_pushliteral(J, "[object Date]"); break; case JS_CMATH: js_pushliteral(J, "[object Math]"); break; case JS_CJSON: js_pushliteral(J, "[object JSON]"); break; case JS_CITERATOR: js_pushliteral(J, "[Iterator]"); break; case JS_CUSERDATA: js_pushliteral(J, "[object "); js_pushliteral(J, self->u.user.tag); js_concat(J); js_pushliteral(J, "]"); js_concat(J); break; } }
static void O_getOwnPropertyDescriptor(js_State *J) { js_Object *obj; js_Property *ref; if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); obj = js_toobject(J, 1); ref = jsV_getproperty(J, obj, js_tostring(J, 2)); if (!ref) js_pushundefined(J); else { js_newobject(J); if (!ref->getter && !ref->setter) { js_pushvalue(J, ref->value); js_setproperty(J, -2, "value"); js_pushboolean(J, !(ref->atts & JS_READONLY)); js_setproperty(J, -2, "writable"); } else { if (ref->getter) js_pushobject(J, ref->getter); else js_pushundefined(J); js_setproperty(J, -2, "get"); if (ref->setter) js_pushobject(J, ref->setter); else js_pushundefined(J); js_setproperty(J, -2, "set"); } js_pushboolean(J, !(ref->atts & JS_DONTENUM)); js_setproperty(J, -2, "enumerable"); js_pushboolean(J, !(ref->atts & JS_DONTCONF)); js_setproperty(J, -2, "configurable"); } }
static void jsB_new_Object(js_State *J) { if (js_isundefined(J, 1) || js_isnull(J, 1)) js_newobject(J); else js_pushobject(J, js_toobject(J, 1)); }
static void Op_hasOwnProperty(js_State *J) { js_Object *self = js_toobject(J, 0); const char *name = js_tostring(J, 1); js_Property *ref = jsV_getownproperty(J, self, name); js_pushboolean(J, ref != NULL); }
static void O_preventExtensions(js_State *J) { if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); js_toobject(J, 1)->extensible = 0; js_copy(J, 1); }
static void Op_propertyIsEnumerable(js_State *J) { js_Object *self = js_toobject(J, 0); const char *name = js_tostring(J, 1); js_Property *ref = jsV_getownproperty(J, self, name); js_pushboolean(J, ref && !(ref->atts & JS_DONTENUM)); }
static void O_keys(js_State *J) { js_Object *obj; js_Property *ref; int k; int i; if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); obj = js_toobject(J, 1); js_newarray(J); i = 0; for (ref = obj->head; ref; ref = ref->next) { if (!(ref->atts & JS_DONTENUM)) { js_pushliteral(J, ref->name); js_setindex(J, -2, i++); } } if (obj->type == JS_CSTRING) { for (k = 0; k < obj->u.s.length; ++k) { js_pushnumber(J, k); js_setindex(J, -2, i++); } } }
void js_newobjectx(js_State *J) { js_Object *prototype = NULL; if (js_isobject(J, -1)) prototype = js_toobject(J, -1); js_pop(J, 1); js_pushobject(J, jsV_newobject(J, JS_COBJECT, prototype)); }
static void A_isArray(js_State *J) { if (js_isobject(J, 1)) { js_Object *T = js_toobject(J, 1); js_pushboolean(J, T->type == JS_CARRAY); } else { js_pushboolean(J, 0); } }
static void O_defineProperties(js_State *J) { js_Object *props; js_Property *ref; if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); if (!js_isobject(J, 2)) js_typeerror(J, "not an object"); props = js_toobject(J, 2); for (ref = props->head; ref; ref = ref->next) { if (!(ref->atts & JS_DONTENUM)) { js_pushvalue(J, ref->value); ToPropertyDescriptor(J, js_toobject(J, 1), ref->name, js_toobject(J, -1)); js_pop(J, 1); } } js_copy(J, 1); }
static void O_getPrototypeOf(js_State *J) { js_Object *obj; if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); obj = js_toobject(J, 1); if (obj->prototype) js_pushobject(J, obj->prototype); else js_pushnull(J); }
void js_newuserdata(js_State *J, const char *tag, void *data) { js_Object *prototype = NULL; js_Object *obj; if (js_isobject(J, -1)) prototype = js_toobject(J, -1); js_pop(J, 1); obj = jsV_newobject(J, JS_CUSERDATA, prototype); obj->u.user.tag = tag; obj->u.user.data = data; js_pushobject(J, obj); }
static void O_freeze(js_State *J) { js_Object *obj; js_Property *ref; if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); obj = js_toobject(J, 1); obj->extensible = 0; for (ref = obj->head; ref; ref = ref->next) ref->atts |= JS_READONLY | JS_DONTCONF; js_copy(J, 1); }
static void O_getOwnPropertyNames(js_State *J) { js_Object *obj; js_Property *ref; int k; int i; if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); obj = js_toobject(J, 1); js_newarray(J); i = 0; for (ref = obj->head; ref; ref = ref->next) { js_pushliteral(J, ref->name); js_setindex(J, -2, i++); } if (obj->type == JS_CARRAY) { js_pushliteral(J, "length"); js_setindex(J, -2, i++); } if (obj->type == JS_CSTRING) { js_pushliteral(J, "length"); js_setindex(J, -2, i++); for (k = 0; k < obj->u.s.length; ++k) { js_pushnumber(J, k); js_setindex(J, -2, i++); } } if (obj->type == JS_CREGEXP) { js_pushliteral(J, "source"); js_setindex(J, -2, i++); js_pushliteral(J, "global"); js_setindex(J, -2, i++); js_pushliteral(J, "ignoreCase"); js_setindex(J, -2, i++); js_pushliteral(J, "multiline"); js_setindex(J, -2, i++); js_pushliteral(J, "lastIndex"); js_setindex(J, -2, i++); } }
void js_newuserdatax(js_State *J, const char *tag, void *data, js_HasProperty has, js_Put put, js_Delete jdelete, js_Finalize finalize) { js_Object *prototype = NULL; js_Object *obj; if (js_isobject(J, -1)) prototype = js_toobject(J, -1); js_pop(J, 1); obj = jsV_newobject(J, JS_CUSERDATA, prototype); obj->u.user.tag = tag; obj->u.user.data = data; obj->u.user.has = has; obj->u.user.put = put; obj->u.user.jdelete = jdelete; obj->u.user.finalize = finalize; js_pushobject(J, obj); }
static void O_isFrozen(js_State *J) { js_Object *obj; js_Property *ref; if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); obj = js_toobject(J, 1); if (obj->extensible) { js_pushboolean(J, 0); return; } for (ref = obj->head; ref; ref = ref->next) { if (!(ref->atts & (JS_READONLY | JS_DONTCONF))) { js_pushboolean(J, 0); return; } } js_pushboolean(J, 1); }
void js_defaccessor(js_State *J, int idx, const char *name, int atts) { jsR_defproperty(J, js_toobject(J, idx), name, atts, NULL, jsR_tofunction(J, -2), jsR_tofunction(J, -1)); js_pop(J, 2); }
void js_pushiterator(js_State *J, int idx, int own) { js_pushobject(J, jsV_newiterator(J, js_toobject(J, idx), own)); }
const char *js_nextiterator(js_State *J, int idx) { return jsV_nextiterator(J, js_toobject(J, idx)); }
static void Sp_valueOf(js_State *J) { js_Object *self = js_toobject(J, 0); if (self->type != JS_CSTRING) js_typeerror(J, "not a string"); js_pushliteral(J, self->u.s.string); }
static void O_isExtensible(js_State *J) { if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); js_pushboolean(J, js_toobject(J, 1)->extensible); }
int js_hasproperty(js_State *J, int idx, const char *name) { return jsR_hasproperty(J, js_toobject(J, idx), name); }
void js_delproperty(js_State *J, int idx, const char *name) { jsR_delproperty(J, js_toobject(J, idx), name); }