| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560 |
- #include "jsi.h"
- 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 jsB_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_toString(js_State *J)
- {
- if (js_isundefined(J, 0))
- js_pushliteral(J, "[object Undefined]");
- else if (js_isnull(J, 0))
- js_pushliteral(J, "[object Null]");
- else {
- 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_CARGUMENTS: js_pushliteral(J, "[object Arguments]"); break;
- case JS_CITERATOR: js_pushliteral(J, "[object 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 Op_valueOf(js_State *J)
- {
- js_copy(J, 0);
- }
- static void Op_hasOwnProperty(js_State *J)
- {
- js_Object *self = js_toobject(J, 0);
- const char *name = js_tostring(J, 1);
- js_Property *ref;
- int k;
- if (self->type == JS_CSTRING) {
- if (js_isarrayindex(J, name, &k) && k >= 0 && k < self->u.s.length) {
- js_pushboolean(J, 1);
- return;
- }
- }
- if (self->type == JS_CARRAY && self->u.a.simple) {
- if (js_isarrayindex(J, name, &k) && k >= 0 && k < self->u.a.flat_length) {
- js_pushboolean(J, 1);
- return;
- }
- }
- ref = jsV_getownproperty(J, self, name);
- js_pushboolean(J, ref != NULL);
- }
- 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);
- }
- 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_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);
- }
- 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) {
- // TODO: builtin properties (string and array index and length, regexp flags, etc)
- js_pushundefined(J);
- } else {
- js_newobject(J);
- if (!ref->getter && !ref->setter) {
- js_pushvalue(J, ref->value);
- js_defproperty(J, -2, "value", 0);
- js_pushboolean(J, !(ref->atts & JS_READONLY));
- js_defproperty(J, -2, "writable", 0);
- } else {
- if (ref->getter)
- js_pushobject(J, ref->getter);
- else
- js_pushundefined(J);
- js_defproperty(J, -2, "get", 0);
- if (ref->setter)
- js_pushobject(J, ref->setter);
- else
- js_pushundefined(J);
- js_defproperty(J, -2, "set", 0);
- }
- js_pushboolean(J, !(ref->atts & JS_DONTENUM));
- js_defproperty(J, -2, "enumerable", 0);
- js_pushboolean(J, !(ref->atts & JS_DONTCONF));
- js_defproperty(J, -2, "configurable", 0);
- }
- }
- static int O_getOwnPropertyNames_walk(js_State *J, js_Property *ref, int i)
- {
- if (ref->left->level)
- i = O_getOwnPropertyNames_walk(J, ref->left, i);
- js_pushstring(J, ref->name);
- js_setindex(J, -2, i++);
- if (ref->right->level)
- i = O_getOwnPropertyNames_walk(J, ref->right, i);
- return i;
- }
- static void O_getOwnPropertyNames(js_State *J)
- {
- js_Object *obj;
- char name[32];
- int k;
- int i;
- if (!js_isobject(J, 1))
- js_typeerror(J, "not an object");
- obj = js_toobject(J, 1);
- js_newarray(J);
- if (obj->properties->level)
- i = O_getOwnPropertyNames_walk(J, obj->properties, 0);
- else
- i = 0;
- if (obj->type == JS_CARRAY) {
- js_pushliteral(J, "length");
- js_setindex(J, -2, i++);
- if (obj->u.a.simple) {
- for (k = 0; k < obj->u.a.flat_length; ++k) {
- js_itoa(name, k);
- js_pushstring(J, name);
- 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_itoa(name, k);
- js_pushstring(J, name);
- 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++);
- }
- }
- static void ToPropertyDescriptor(js_State *J, js_Object *obj, const char *name, js_Object *desc)
- {
- int haswritable = 0;
- int hasvalue = 0;
- int enumerable = 0;
- int configurable = 0;
- int writable = 0;
- int atts = 0;
- js_pushobject(J, obj);
- js_pushobject(J, desc);
- if (js_hasproperty(J, -1, "writable")) {
- haswritable = 1;
- writable = js_toboolean(J, -1);
- js_pop(J, 1);
- }
- if (js_hasproperty(J, -1, "enumerable")) {
- enumerable = js_toboolean(J, -1);
- js_pop(J, 1);
- }
- if (js_hasproperty(J, -1, "configurable")) {
- configurable = js_toboolean(J, -1);
- js_pop(J, 1);
- }
- if (js_hasproperty(J, -1, "value")) {
- hasvalue = 1;
- js_defproperty(J, -3, name, 0);
- }
- if (!writable) atts |= JS_READONLY;
- if (!enumerable) atts |= JS_DONTENUM;
- if (!configurable) atts |= JS_DONTCONF;
- if (js_hasproperty(J, -1, "get")) {
- if (haswritable || hasvalue)
- js_typeerror(J, "value/writable and get/set attributes are exclusive");
- } else {
- js_pushundefined(J);
- }
- if (js_hasproperty(J, -2, "set")) {
- if (haswritable || hasvalue)
- js_typeerror(J, "value/writable and get/set attributes are exclusive");
- } else {
- js_pushundefined(J);
- }
- js_defaccessor(J, -4, name, atts);
- js_pop(J, 2);
- }
- 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);
- }
- static void O_defineProperties_walk(js_State *J, js_Property *ref)
- {
- if (ref->left->level)
- O_defineProperties_walk(J, ref->left);
- 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);
- }
- if (ref->right->level)
- O_defineProperties_walk(J, ref->right);
- }
- static void O_defineProperties(js_State *J)
- {
- js_Object *props;
- 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);
- if (props->properties->level)
- O_defineProperties_walk(J, props->properties);
- js_copy(J, 1);
- }
- static void O_create_walk(js_State *J, js_Object *obj, js_Property *ref)
- {
- if (ref->left->level)
- O_create_walk(J, obj, ref->left);
- if (!(ref->atts & JS_DONTENUM)) {
- if (ref->value.t.type != JS_TOBJECT)
- js_typeerror(J, "not an object");
- ToPropertyDescriptor(J, obj, ref->name, ref->value.u.object);
- }
- if (ref->right->level)
- O_create_walk(J, obj, ref->right);
- }
- static void O_create(js_State *J)
- {
- js_Object *obj;
- js_Object *proto;
- js_Object *props;
- 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);
- if (props->properties->level)
- O_create_walk(J, obj, props->properties);
- }
- }
- static int O_keys_walk(js_State *J, js_Property *ref, int i)
- {
- if (ref->left->level)
- i = O_keys_walk(J, ref->left, i);
- if (!(ref->atts & JS_DONTENUM)) {
- js_pushstring(J, ref->name);
- js_setindex(J, -2, i++);
- }
- if (ref->right->level)
- i = O_keys_walk(J, ref->right, i);
- return i;
- }
- static void O_keys(js_State *J)
- {
- js_Object *obj;
- char name[32];
- int i, k;
- if (!js_isobject(J, 1))
- js_typeerror(J, "not an object");
- obj = js_toobject(J, 1);
- js_newarray(J);
- if (obj->properties->level)
- i = O_keys_walk(J, obj->properties, 0);
- else
- i = 0;
- if (obj->type == JS_CSTRING) {
- for (k = 0; k < obj->u.s.length; ++k) {
- js_itoa(name, k);
- js_pushstring(J, name);
- js_setindex(J, -2, i++);
- }
- }
- if (obj->type == JS_CARRAY && obj->u.a.simple) {
- for (k = 0; k < obj->u.a.flat_length; ++k) {
- js_itoa(name, k);
- js_pushstring(J, name);
- js_setindex(J, -2, i++);
- }
- }
- }
- static void O_preventExtensions(js_State *J)
- {
- js_Object *obj;
- if (!js_isobject(J, 1))
- js_typeerror(J, "not an object");
- obj = js_toobject(J, 1);
- jsR_unflattenarray(J, obj);
- obj->extensible = 0;
- js_copy(J, 1);
- }
- 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);
- }
- static void O_seal_walk(js_State *J, js_Property *ref)
- {
- if (ref->left->level)
- O_seal_walk(J, ref->left);
- ref->atts |= JS_DONTCONF;
- if (ref->right->level)
- O_seal_walk(J, ref->right);
- }
- static void O_seal(js_State *J)
- {
- js_Object *obj;
- if (!js_isobject(J, 1))
- js_typeerror(J, "not an object");
- obj = js_toobject(J, 1);
- jsR_unflattenarray(J, obj);
- obj->extensible = 0;
- if (obj->properties->level)
- O_seal_walk(J, obj->properties);
- js_copy(J, 1);
- }
- static int O_isSealed_walk(js_State *J, js_Property *ref)
- {
- if (ref->left->level)
- if (!O_isSealed_walk(J, ref->left))
- return 0;
- if (!(ref->atts & JS_DONTCONF))
- return 0;
- if (ref->right->level)
- if (!O_isSealed_walk(J, ref->right))
- return 0;
- return 1;
- }
- static void O_isSealed(js_State *J)
- {
- js_Object *obj;
- if (!js_isobject(J, 1))
- js_typeerror(J, "not an object");
- obj = js_toobject(J, 1);
- if (obj->extensible) {
- js_pushboolean(J, 0);
- return;
- }
- if (obj->properties->level)
- js_pushboolean(J, O_isSealed_walk(J, obj->properties));
- else
- js_pushboolean(J, 1);
- }
- static void O_freeze_walk(js_State *J, js_Property *ref)
- {
- if (ref->left->level)
- O_freeze_walk(J, ref->left);
- ref->atts |= JS_READONLY | JS_DONTCONF;
- if (ref->right->level)
- O_freeze_walk(J, ref->right);
- }
- static void O_freeze(js_State *J)
- {
- js_Object *obj;
- if (!js_isobject(J, 1))
- js_typeerror(J, "not an object");
- obj = js_toobject(J, 1);
- jsR_unflattenarray(J, obj);
- obj->extensible = 0;
- if (obj->properties->level)
- O_freeze_walk(J, obj->properties);
- js_copy(J, 1);
- }
- static int O_isFrozen_walk(js_State *J, js_Property *ref)
- {
- if (ref->left->level)
- if (!O_isFrozen_walk(J, ref->left))
- return 0;
- if (!(ref->atts & JS_READONLY))
- return 0;
- if (!(ref->atts & JS_DONTCONF))
- return 0;
- if (ref->right->level)
- if (!O_isFrozen_walk(J, ref->right))
- return 0;
- return 1;
- }
- static void O_isFrozen(js_State *J)
- {
- js_Object *obj;
- if (!js_isobject(J, 1))
- js_typeerror(J, "not an object");
- obj = js_toobject(J, 1);
- if (obj->properties->level) {
- if (!O_isFrozen_walk(J, obj->properties)) {
- js_pushboolean(J, 0);
- return;
- }
- }
- js_pushboolean(J, !obj->extensible);
- }
- void jsB_initobject(js_State *J)
- {
- js_pushobject(J, J->Object_prototype);
- {
- jsB_propf(J, "Object.prototype.toString", Op_toString, 0);
- jsB_propf(J, "Object.prototype.toLocaleString", Op_toString, 0);
- jsB_propf(J, "Object.prototype.valueOf", Op_valueOf, 0);
- jsB_propf(J, "Object.prototype.hasOwnProperty", Op_hasOwnProperty, 1);
- jsB_propf(J, "Object.prototype.isPrototypeOf", Op_isPrototypeOf, 1);
- jsB_propf(J, "Object.prototype.propertyIsEnumerable", Op_propertyIsEnumerable, 1);
- }
- js_newcconstructor(J, jsB_Object, jsB_new_Object, "Object", 1);
- {
- /* ES5 */
- jsB_propf(J, "Object.getPrototypeOf", O_getPrototypeOf, 1);
- jsB_propf(J, "Object.getOwnPropertyDescriptor", O_getOwnPropertyDescriptor, 2);
- jsB_propf(J, "Object.getOwnPropertyNames", O_getOwnPropertyNames, 1);
- jsB_propf(J, "Object.create", O_create, 2);
- jsB_propf(J, "Object.defineProperty", O_defineProperty, 3);
- jsB_propf(J, "Object.defineProperties", O_defineProperties, 2);
- jsB_propf(J, "Object.seal", O_seal, 1);
- jsB_propf(J, "Object.freeze", O_freeze, 1);
- jsB_propf(J, "Object.preventExtensions", O_preventExtensions, 1);
- jsB_propf(J, "Object.isSealed", O_isSealed, 1);
- jsB_propf(J, "Object.isFrozen", O_isFrozen, 1);
- jsB_propf(J, "Object.isExtensible", O_isExtensible, 1);
- jsB_propf(J, "Object.keys", O_keys, 1);
- }
- js_defglobal(J, "Object", JS_DONTENUM);
- }
|