cosmopolitan/third_party/quickjs/mem.c

190 lines
5.6 KiB
C
Raw Normal View History

/*
* QuickJS Javascript Engine
*
* Copyright (c) 2017-2021 Fabrice Bellard
* Copyright (c) 2017-2021 Charlie Gordon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "third_party/quickjs/internal.h"
#include "third_party/quickjs/libregexp.h"
#include "third_party/quickjs/quickjs.h"
asm(".ident\t\"\\n\\n\
QuickJS (MIT License)\\n\
Copyright (c) 2017-2021 Fabrice Bellard\\n\
Copyright (c) 2017-2021 Charlie Gordon\"");
asm(".include \"libc/disclaimer.inc\"");
/* clang-format off */
JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx)
{
return JS_ThrowTypeError(ctx, "revoked proxy");
}
JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id)
{
JSRuntime *rt = ctx->rt;
JSAtom name;
name = rt->class_array[class_id].class_name;
return JS_ThrowTypeErrorAtom(ctx, "%s object expected", name);
}
/* warning: the refcount of the context is not incremented. Return
NULL in case of exception (case of revoked proxy only) */
JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj)
{
JSObject *p;
JSContext *realm;
if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)
return ctx;
p = JS_VALUE_GET_OBJ(func_obj);
switch(p->class_id) {
case JS_CLASS_C_FUNCTION:
realm = p->u.cfunc.realm;
break;
case JS_CLASS_BYTECODE_FUNCTION:
case JS_CLASS_GENERATOR_FUNCTION:
case JS_CLASS_ASYNC_FUNCTION:
case JS_CLASS_ASYNC_GENERATOR_FUNCTION:
{
JSFunctionBytecode *b;
b = p->u.func.function_bytecode;
realm = b->realm;
}
break;
case JS_CLASS_PROXY:
{
JSProxyData *s = p->u.opaque;
if (!s)
return ctx;
if (s->is_revoked) {
JS_ThrowTypeErrorRevokedProxy(ctx);
return NULL;
} else {
realm = JS_GetFunctionRealm(ctx, s->target);
}
}
break;
case JS_CLASS_BOUND_FUNCTION:
{
JSBoundFunction *bf = p->u.bound_function;
realm = JS_GetFunctionRealm(ctx, bf->func_obj);
}
break;
default:
realm = ctx;
break;
}
return realm;
}
JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor,
int class_id)
{
JSValue proto, obj;
JSContext *realm;
if (JS_IsUndefined(ctor)) {
proto = JS_DupValue(ctx, ctx->class_proto[class_id]);
} else {
proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype);
if (JS_IsException(proto))
return proto;
if (!JS_IsObject(proto)) {
JS_FreeValue(ctx, proto);
realm = JS_GetFunctionRealm(ctx, ctor);
if (!realm)
return JS_EXCEPTION;
proto = JS_DupValue(ctx, realm->class_proto[class_id]);
}
}
obj = JS_NewObjectProtoClass(ctx, proto, class_id);
JS_FreeValue(ctx, proto);
return obj;
}
int JS_ToBoolFree(JSContext *ctx, JSValue val)
{
uint32_t tag = JS_VALUE_GET_TAG(val);
switch(tag) {
case JS_TAG_INT:
return JS_VALUE_GET_INT(val) != 0;
case JS_TAG_BOOL:
case JS_TAG_NULL:
case JS_TAG_UNDEFINED:
return JS_VALUE_GET_INT(val);
case JS_TAG_EXCEPTION:
return -1;
case JS_TAG_STRING:
{
BOOL ret = JS_VALUE_GET_STRING(val)->len != 0;
JS_FreeValue(ctx, val);
return ret;
}
#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
case JS_TAG_BIG_FLOAT:
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
BOOL ret;
ret = p->num.expn != BF_EXP_ZERO && p->num.expn != BF_EXP_NAN;
JS_FreeValue(ctx, val);
return ret;
}
case JS_TAG_BIG_DECIMAL:
{
JSBigDecimal *p = JS_VALUE_GET_PTR(val);
BOOL ret;
ret = p->num.expn != BF_EXP_ZERO && p->num.expn != BF_EXP_NAN;
JS_FreeValue(ctx, val);
return ret;
}
#endif
case JS_TAG_OBJECT:
{
JSObject *p = JS_VALUE_GET_OBJ(val);
BOOL ret;
ret = !p->is_HTMLDDA;
JS_FreeValue(ctx, val);
return ret;
}
break;
default:
if (JS_TAG_IS_FLOAT64(tag)) {
double d = JS_VALUE_GET_FLOAT64(val);
return !isnan(d) && d != 0;
} else {
JS_FreeValue(ctx, val);
return TRUE;
}
}
}
int JS_ToBool(JSContext *ctx, JSValueConst val)
{
return JS_ToBoolFree(ctx, JS_DupValue(ctx, val));
}
JSValue js_get_this(JSContext *ctx, JSValueConst this_val)
{
return JS_DupValue(ctx, this_val);
}