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 js_setvar(js_State *J, const char *name) { js_Environment *E = J->E; do { js_Property *ref = jsV_getproperty(J, E->variables, name); if (ref) { if (ref->setter) { js_pushobject(J, ref->setter); js_pushobject(J, E->variables); js_copy(J, -3); js_call(J, 1); js_pop(J, 1); return; } if (!(ref->atts & JS_READONLY)) ref->value = *stackidx(J, -1); else if (J->strict) js_typeerror(J, "'%s' is read-only", name); return; } E = E->outer; } while (E); if (J->strict) js_referenceerror(J, "assignment to undeclared variable '%s'", name); jsR_setproperty(J, J->G, name, stackidx(J, -1)); }
static int jsR_hasproperty(js_State *J, js_Object *obj, const char *name) { js_Property *ref; unsigned int k; if (obj->type == JS_CARRAY) { if (!strcmp(name, "length")) { js_pushnumber(J, obj->u.a.length); return 1; } } if (obj->type == JS_CSTRING) { if (!strcmp(name, "length")) { js_pushnumber(J, obj->u.s.length); return 1; } if (js_isarrayindex(J, name, &k)) { js_pushrune(J, js_runeat(J, obj->u.s.string, k)); return 1; } } if (obj->type == JS_CREGEXP) { if (!strcmp(name, "source")) { js_pushliteral(J, obj->u.r.source); return 1; } if (!strcmp(name, "global")) { js_pushboolean(J, obj->u.r.flags & JS_REGEXP_G); return 1; } if (!strcmp(name, "ignoreCase")) { js_pushboolean(J, obj->u.r.flags & JS_REGEXP_I); return 1; } if (!strcmp(name, "multiline")) { js_pushboolean(J, obj->u.r.flags & JS_REGEXP_M); return 1; } if (!strcmp(name, "lastIndex")) { js_pushnumber(J, obj->u.r.last); return 1; } } ref = jsV_getproperty(J, obj, name); if (ref) { if (ref->getter) { js_pushobject(J, ref->getter); js_pushobject(J, obj); js_call(J, 0); } else { js_pushvalue(J, ref->value); } return 1; } return 0; }
const char *jsV_nextiterator(js_State *J, js_Object *io) { int k; if (io->type != JS_CITERATOR) js_typeerror(J, "not an iterator"); while (io->u.iter.head) { js_Iterator *next = io->u.iter.head->next; const char *name = io->u.iter.head->name; js_free(J, io->u.iter.head); io->u.iter.head = next; if (jsV_getproperty(J, io->u.iter.target, name)) return name; if (io->u.iter.target->type == JS_CSTRING) if (js_isarrayindex(J, name, &k) && k < io->u.iter.target->u.s.length) return name; } return NULL; }
static int js_hasvar(js_State *J, const char *name) { js_Environment *E = J->E; do { js_Property *ref = jsV_getproperty(J, E->variables, name); if (ref) { if (ref->getter) { js_pushobject(J, ref->getter); js_pushobject(J, E->variables); js_call(J, 0); } else { js_pushvalue(J, ref->value); } return 1; } E = E->outer; } while (E); return 0; }