static void Ap_sort(js_State *J) { struct sortslot *array = NULL; int i, n, len; len = js_getlength(J, 0); if (len <= 0) { js_copy(J, 0); return; } if (len >= INT_MAX / (int)sizeof(*array)) js_rangeerror(J, "array is too large to sort"); array = js_malloc(J, len * sizeof *array); /* Holding objects where the GC cannot see them is illegal, but if we * don't allow the GC to run we can use qsort() on a temporary array of * js_Values for fast sorting. */ ++J->gcpause; if (js_try(J)) { --J->gcpause; js_free(J, array); js_throw(J); } n = 0; for (i = 0; i < len; ++i) { if (js_hasindex(J, 0, i)) { array[n].v = *js_tovalue(J, -1); array[n].J = J; js_pop(J, 1); ++n; } } qsort(array, n, sizeof *array, sortcmp); for (i = 0; i < n; ++i) { js_pushvalue(J, array[i].v); js_setindex(J, 0, i); } for (i = n; i < len; ++i) { js_delindex(J, 0, i); } --J->gcpause; js_endtry(J); js_free(J, array); js_copy(J, 0); }
static void wrapmethod(js_State *J) { pdf_jsimp_obj *args[MAXARGS]; pdf_jsimp_obj *ret; pdf_jsimp_method *meth; const char *type; void *jsctx; void *obj; int i; int argc = js_gettop(J) - 1; js_getregistry(J, "jsctx"); jsctx = js_touserdata(J, "jsctx", -1); js_pop(J, 1); js_currentfunction(J); { js_getproperty(J, -1, "__call"); meth = js_touserdata(J, "method", -1); js_pop(J, 1); js_getproperty(J, -1, "__type"); type = js_tostring(J, -1); js_pop(J, 1); } js_pop(J, 1); if (js_isuserdata(J, type, 0)) obj = js_touserdata(J, type, 0); else obj = NULL; if (argc > MAXARGS) js_rangeerror(J, "too many arguments"); for (i = 0; i < argc; ++i) args[i] = OBJ(i+1); ret = meth(jsctx, obj, argc, args); if (ret) js_copy(J, IDX(ret)); else js_pushundefined(J); }
static void jsR_setproperty(js_State *J, js_Object *obj, const char *name, js_Value *value) { js_Property *ref; unsigned int k; int own; if (obj->type == JS_CARRAY) { if (!strcmp(name, "length")) { double rawlen = jsV_tonumber(J, value); unsigned int newlen = jsV_numbertouint32(rawlen); if (newlen != rawlen) js_rangeerror(J, "array length"); jsV_resizearray(J, obj, newlen); return; } if (js_isarrayindex(J, name, &k)) if (k >= obj->u.a.length) obj->u.a.length = k + 1; } if (obj->type == JS_CSTRING) { if (!strcmp(name, "length")) goto readonly; if (js_isarrayindex(J, name, &k)) if (js_runeat(J, obj->u.s.string, k)) goto readonly; } if (obj->type == JS_CREGEXP) { if (!strcmp(name, "source")) goto readonly; if (!strcmp(name, "global")) goto readonly; if (!strcmp(name, "ignoreCase")) goto readonly; if (!strcmp(name, "multiline")) goto readonly; if (!strcmp(name, "lastIndex")) { obj->u.r.last = jsV_tointeger(J, value); return; } } /* First try to find a setter in prototype chain */ ref = jsV_getpropertyx(J, obj, name, &own); if (ref && ref->setter) { js_pushobject(J, ref->setter); js_pushobject(J, obj); js_pushvalue(J, *value); js_call(J, 1); js_pop(J, 1); return; } /* Property not found on this object, so create one */ if (!ref || !own) ref = jsV_setproperty(J, obj, name); if (ref) { if (!(ref->atts & JS_READONLY)) ref->value = *value; else goto readonly; } return; readonly: if (J->strict) js_typeerror(J, "'%s' is read-only", name); }