mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-24 06:12:27 +00:00
Reduce build latency and fix old cpu bugs
This commit is contained in:
parent
df8ab0aa0c
commit
533f3d1ef1
69 changed files with 43069 additions and 43683 deletions
509
third_party/quickjs/gen.c
vendored
Normal file
509
third_party/quickjs/gen.c
vendored
Normal file
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
* 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 "libc/assert.h"
|
||||
#include "third_party/quickjs/internal.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 */
|
||||
|
||||
typedef enum JSGeneratorStateEnum {
|
||||
JS_GENERATOR_STATE_SUSPENDED_START,
|
||||
JS_GENERATOR_STATE_SUSPENDED_YIELD,
|
||||
JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR,
|
||||
JS_GENERATOR_STATE_EXECUTING,
|
||||
JS_GENERATOR_STATE_COMPLETED,
|
||||
} JSGeneratorStateEnum;
|
||||
|
||||
typedef struct JSGeneratorData {
|
||||
JSGeneratorStateEnum state;
|
||||
JSAsyncFunctionState func_state;
|
||||
} JSGeneratorData;
|
||||
|
||||
static void free_generator_stack_rt(JSRuntime *rt, JSGeneratorData *s)
|
||||
{
|
||||
if (s->state == JS_GENERATOR_STATE_COMPLETED)
|
||||
return;
|
||||
async_func_free(rt, &s->func_state);
|
||||
s->state = JS_GENERATOR_STATE_COMPLETED;
|
||||
}
|
||||
|
||||
void js_generator_finalizer(JSRuntime *rt, JSValue obj)
|
||||
{
|
||||
JSGeneratorData *s = JS_GetOpaque(obj, JS_CLASS_GENERATOR);
|
||||
if (s) {
|
||||
free_generator_stack_rt(rt, s);
|
||||
js_free_rt(rt, s);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_generator_stack(JSContext *ctx, JSGeneratorData *s)
|
||||
{
|
||||
free_generator_stack_rt(ctx->rt, s);
|
||||
}
|
||||
|
||||
void js_generator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)
|
||||
{
|
||||
JSObject *p = JS_VALUE_GET_OBJ(val);
|
||||
JSGeneratorData *s = p->u.generator_data;
|
||||
if (!s || s->state == JS_GENERATOR_STATE_COMPLETED)
|
||||
return;
|
||||
async_func_mark(rt, &s->func_state, mark_func);
|
||||
}
|
||||
|
||||
static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv,
|
||||
BOOL *pdone, int magic)
|
||||
{
|
||||
JSGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_GENERATOR);
|
||||
JSStackFrame *sf;
|
||||
JSValue ret, func_ret;
|
||||
*pdone = TRUE;
|
||||
if (!s)
|
||||
return JS_ThrowTypeError(ctx, "not a generator");
|
||||
sf = &s->func_state.frame;
|
||||
switch(s->state) {
|
||||
default:
|
||||
case JS_GENERATOR_STATE_SUSPENDED_START:
|
||||
if (magic == GEN_MAGIC_NEXT) {
|
||||
goto exec_no_arg;
|
||||
} else {
|
||||
free_generator_stack(ctx, s);
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR:
|
||||
case JS_GENERATOR_STATE_SUSPENDED_YIELD:
|
||||
/* cur_sp[-1] was set to JS_UNDEFINED in the previous call */
|
||||
ret = JS_DupValue(ctx, argv[0]);
|
||||
if (magic == GEN_MAGIC_THROW &&
|
||||
s->state == JS_GENERATOR_STATE_SUSPENDED_YIELD) {
|
||||
JS_Throw(ctx, ret);
|
||||
s->func_state.throw_flag = TRUE;
|
||||
} else {
|
||||
sf->cur_sp[-1] = ret;
|
||||
sf->cur_sp[0] = JS_NewInt32(ctx, magic);
|
||||
sf->cur_sp++;
|
||||
exec_no_arg:
|
||||
s->func_state.throw_flag = FALSE;
|
||||
}
|
||||
s->state = JS_GENERATOR_STATE_EXECUTING;
|
||||
func_ret = async_func_resume(ctx, &s->func_state);
|
||||
s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD;
|
||||
if (JS_IsException(func_ret)) {
|
||||
/* finalize the execution in case of exception */
|
||||
free_generator_stack(ctx, s);
|
||||
return func_ret;
|
||||
}
|
||||
if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {
|
||||
/* get the returned yield value at the top of the stack */
|
||||
ret = sf->cur_sp[-1];
|
||||
sf->cur_sp[-1] = JS_UNDEFINED;
|
||||
if (JS_VALUE_GET_INT(func_ret) == FUNC_RET_YIELD_STAR) {
|
||||
s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR;
|
||||
/* return (value, done) object */
|
||||
*pdone = 2;
|
||||
} else {
|
||||
*pdone = FALSE;
|
||||
}
|
||||
} else {
|
||||
/* end of iterator */
|
||||
ret = sf->cur_sp[-1];
|
||||
sf->cur_sp[-1] = JS_UNDEFINED;
|
||||
JS_FreeValue(ctx, func_ret);
|
||||
free_generator_stack(ctx, s);
|
||||
}
|
||||
break;
|
||||
case JS_GENERATOR_STATE_COMPLETED:
|
||||
done:
|
||||
/* execution is finished */
|
||||
switch(magic) {
|
||||
default:
|
||||
case GEN_MAGIC_NEXT:
|
||||
ret = JS_UNDEFINED;
|
||||
break;
|
||||
case GEN_MAGIC_RETURN:
|
||||
ret = JS_DupValue(ctx, argv[0]);
|
||||
break;
|
||||
case GEN_MAGIC_THROW:
|
||||
ret = JS_Throw(ctx, JS_DupValue(ctx, argv[0]));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case JS_GENERATOR_STATE_EXECUTING:
|
||||
ret = JS_ThrowTypeError(ctx, "cannot invoke a running generator");
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,
|
||||
JSValueConst this_obj, int argc,
|
||||
JSValueConst *argv, int flags)
|
||||
{
|
||||
JSValue obj, func_ret;
|
||||
JSGeneratorData *s;
|
||||
s = js_mallocz(ctx, sizeof(*s));
|
||||
if (!s)
|
||||
return JS_EXCEPTION;
|
||||
s->state = JS_GENERATOR_STATE_SUSPENDED_START;
|
||||
if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {
|
||||
s->state = JS_GENERATOR_STATE_COMPLETED;
|
||||
goto fail;
|
||||
}
|
||||
/* execute the function up to 'OP_initial_yield' */
|
||||
func_ret = async_func_resume(ctx, &s->func_state);
|
||||
if (JS_IsException(func_ret))
|
||||
goto fail;
|
||||
JS_FreeValue(ctx, func_ret);
|
||||
obj = js_create_from_ctor(ctx, func_obj, JS_CLASS_GENERATOR);
|
||||
if (JS_IsException(obj))
|
||||
goto fail;
|
||||
JS_SetOpaque(obj, s);
|
||||
return obj;
|
||||
fail:
|
||||
free_generator_stack_rt(ctx->rt, s);
|
||||
js_free(ctx, s);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
static JSValue js_async_generator_resolve_function(JSContext *ctx,
|
||||
JSValueConst this_obj,
|
||||
int argc, JSValueConst *argv,
|
||||
int magic, JSValue *func_data);
|
||||
|
||||
static int js_async_generator_resolve_function_create(JSContext *ctx,
|
||||
JSValueConst generator,
|
||||
JSValue *resolving_funcs,
|
||||
BOOL is_resume_next)
|
||||
{
|
||||
int i;
|
||||
JSValue func;
|
||||
for(i = 0; i < 2; i++) {
|
||||
func = JS_NewCFunctionData(ctx, js_async_generator_resolve_function, 1,
|
||||
i + is_resume_next * 2, 1, &generator);
|
||||
if (JS_IsException(func)) {
|
||||
if (i == 1)
|
||||
JS_FreeValue(ctx, resolving_funcs[0]);
|
||||
return -1;
|
||||
}
|
||||
resolving_funcs[i] = func;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int js_async_generator_await(JSContext *ctx,
|
||||
JSAsyncGeneratorData *s,
|
||||
JSValueConst value)
|
||||
{
|
||||
JSValue promise, resolving_funcs[2], resolving_funcs1[2];
|
||||
int i, res;
|
||||
promise = js_promise_resolve(ctx, ctx->promise_ctor,
|
||||
1, &value, 0);
|
||||
if (JS_IsException(promise))
|
||||
goto fail;
|
||||
if (js_async_generator_resolve_function_create(ctx, JS_MKPTR(JS_TAG_OBJECT, s->generator),
|
||||
resolving_funcs, FALSE)) {
|
||||
JS_FreeValue(ctx, promise);
|
||||
goto fail;
|
||||
}
|
||||
/* Note: no need to create 'thrownawayCapability' as in
|
||||
the spec */
|
||||
for(i = 0; i < 2; i++)
|
||||
resolving_funcs1[i] = JS_UNDEFINED;
|
||||
res = perform_promise_then(ctx, promise,
|
||||
(JSValueConst *)resolving_funcs,
|
||||
(JSValueConst *)resolving_funcs1);
|
||||
JS_FreeValue(ctx, promise);
|
||||
for(i = 0; i < 2; i++)
|
||||
JS_FreeValue(ctx, resolving_funcs[i]);
|
||||
if (res)
|
||||
goto fail;
|
||||
return 0;
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void js_async_generator_resolve_or_reject(JSContext *ctx,
|
||||
JSAsyncGeneratorData *s,
|
||||
JSValueConst result,
|
||||
int is_reject)
|
||||
{
|
||||
JSAsyncGeneratorRequest *next;
|
||||
JSValue ret;
|
||||
next = list_entry(s->queue.next, JSAsyncGeneratorRequest, link);
|
||||
list_del(&next->link);
|
||||
ret = JS_Call(ctx, next->resolving_funcs[is_reject], JS_UNDEFINED, 1,
|
||||
&result);
|
||||
JS_FreeValue(ctx, ret);
|
||||
JS_FreeValue(ctx, next->result);
|
||||
JS_FreeValue(ctx, next->promise);
|
||||
JS_FreeValue(ctx, next->resolving_funcs[0]);
|
||||
JS_FreeValue(ctx, next->resolving_funcs[1]);
|
||||
js_free(ctx, next);
|
||||
}
|
||||
|
||||
static void js_async_generator_resolve(JSContext *ctx,
|
||||
JSAsyncGeneratorData *s,
|
||||
JSValueConst value,
|
||||
BOOL done)
|
||||
{
|
||||
JSValue result;
|
||||
result = js_create_iterator_result(ctx, JS_DupValue(ctx, value), done);
|
||||
/* XXX: better exception handling ? */
|
||||
js_async_generator_resolve_or_reject(ctx, s, result, 0);
|
||||
JS_FreeValue(ctx, result);
|
||||
}
|
||||
|
||||
static void js_async_generator_reject(JSContext *ctx,
|
||||
JSAsyncGeneratorData *s,
|
||||
JSValueConst exception)
|
||||
{
|
||||
js_async_generator_resolve_or_reject(ctx, s, exception, 1);
|
||||
}
|
||||
|
||||
static void js_async_generator_complete(JSContext *ctx,
|
||||
JSAsyncGeneratorData *s)
|
||||
{
|
||||
if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED) {
|
||||
s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;
|
||||
async_func_free(ctx->rt, &s->func_state);
|
||||
}
|
||||
}
|
||||
|
||||
static int js_async_generator_completed_return(JSContext *ctx,
|
||||
JSAsyncGeneratorData *s,
|
||||
JSValueConst value)
|
||||
{
|
||||
JSValue promise, resolving_funcs[2], resolving_funcs1[2];
|
||||
int res;
|
||||
|
||||
promise = js_promise_resolve(ctx, ctx->promise_ctor,
|
||||
1, (JSValueConst *)&value, 0);
|
||||
if (JS_IsException(promise))
|
||||
return -1;
|
||||
if (js_async_generator_resolve_function_create(ctx,
|
||||
JS_MKPTR(JS_TAG_OBJECT, s->generator),
|
||||
resolving_funcs1,
|
||||
TRUE)) {
|
||||
JS_FreeValue(ctx, promise);
|
||||
return -1;
|
||||
}
|
||||
resolving_funcs[0] = JS_UNDEFINED;
|
||||
resolving_funcs[1] = JS_UNDEFINED;
|
||||
res = perform_promise_then(ctx, promise,
|
||||
(JSValueConst *)resolving_funcs1,
|
||||
(JSValueConst *)resolving_funcs);
|
||||
JS_FreeValue(ctx, resolving_funcs1[0]);
|
||||
JS_FreeValue(ctx, resolving_funcs1[1]);
|
||||
JS_FreeValue(ctx, promise);
|
||||
return res;
|
||||
}
|
||||
|
||||
void js_async_generator_resume_next(JSContext *ctx, JSAsyncGeneratorData *s)
|
||||
{
|
||||
JSAsyncGeneratorRequest *next;
|
||||
JSValue func_ret, value;
|
||||
for(;;) {
|
||||
if (list_empty(&s->queue))
|
||||
break;
|
||||
next = list_entry(s->queue.next, JSAsyncGeneratorRequest, link);
|
||||
switch(s->state) {
|
||||
case JS_ASYNC_GENERATOR_STATE_EXECUTING:
|
||||
/* only happens when restarting execution after await() */
|
||||
goto resume_exec;
|
||||
case JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN:
|
||||
goto done;
|
||||
case JS_ASYNC_GENERATOR_STATE_SUSPENDED_START:
|
||||
if (next->completion_type == GEN_MAGIC_NEXT) {
|
||||
goto exec_no_arg;
|
||||
} else {
|
||||
js_async_generator_complete(ctx, s);
|
||||
}
|
||||
break;
|
||||
case JS_ASYNC_GENERATOR_STATE_COMPLETED:
|
||||
if (next->completion_type == GEN_MAGIC_NEXT) {
|
||||
js_async_generator_resolve(ctx, s, JS_UNDEFINED, TRUE);
|
||||
} else if (next->completion_type == GEN_MAGIC_RETURN) {
|
||||
s->state = JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN;
|
||||
js_async_generator_completed_return(ctx, s, next->result);
|
||||
goto done;
|
||||
} else {
|
||||
js_async_generator_reject(ctx, s, next->result);
|
||||
}
|
||||
goto done;
|
||||
case JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD:
|
||||
case JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR:
|
||||
value = JS_DupValue(ctx, next->result);
|
||||
if (next->completion_type == GEN_MAGIC_THROW &&
|
||||
s->state == JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD) {
|
||||
JS_Throw(ctx, value);
|
||||
s->func_state.throw_flag = TRUE;
|
||||
} else {
|
||||
/* 'yield' returns a value. 'yield *' also returns a value
|
||||
in case the 'throw' method is called */
|
||||
s->func_state.frame.cur_sp[-1] = value;
|
||||
s->func_state.frame.cur_sp[0] =
|
||||
JS_NewInt32(ctx, next->completion_type);
|
||||
s->func_state.frame.cur_sp++;
|
||||
exec_no_arg:
|
||||
s->func_state.throw_flag = FALSE;
|
||||
}
|
||||
s->state = JS_ASYNC_GENERATOR_STATE_EXECUTING;
|
||||
resume_exec:
|
||||
func_ret = async_func_resume(ctx, &s->func_state);
|
||||
if (JS_IsException(func_ret)) {
|
||||
value = JS_GetException(ctx);
|
||||
js_async_generator_complete(ctx, s);
|
||||
js_async_generator_reject(ctx, s, value);
|
||||
JS_FreeValue(ctx, value);
|
||||
} else if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {
|
||||
int func_ret_code;
|
||||
value = s->func_state.frame.cur_sp[-1];
|
||||
s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;
|
||||
func_ret_code = JS_VALUE_GET_INT(func_ret);
|
||||
switch(func_ret_code) {
|
||||
case FUNC_RET_YIELD:
|
||||
case FUNC_RET_YIELD_STAR:
|
||||
if (func_ret_code == FUNC_RET_YIELD_STAR)
|
||||
s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR;
|
||||
else
|
||||
s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD;
|
||||
js_async_generator_resolve(ctx, s, value, FALSE);
|
||||
JS_FreeValue(ctx, value);
|
||||
break;
|
||||
case FUNC_RET_AWAIT:
|
||||
js_async_generator_await(ctx, s, value);
|
||||
JS_FreeValue(ctx, value);
|
||||
goto done;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
assert(JS_IsUndefined(func_ret));
|
||||
/* end of function */
|
||||
value = s->func_state.frame.cur_sp[-1];
|
||||
s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;
|
||||
js_async_generator_complete(ctx, s);
|
||||
js_async_generator_resolve(ctx, s, value, TRUE);
|
||||
JS_FreeValue(ctx, value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
done: ;
|
||||
}
|
||||
|
||||
static JSValue js_async_generator_resolve_function(JSContext *ctx,
|
||||
JSValueConst this_obj,
|
||||
int argc, JSValueConst *argv,
|
||||
int magic, JSValue *func_data)
|
||||
{
|
||||
BOOL is_reject = magic & 1;
|
||||
JSAsyncGeneratorData *s = JS_GetOpaque(func_data[0], JS_CLASS_ASYNC_GENERATOR);
|
||||
JSValueConst arg = argv[0];
|
||||
/* XXX: what if s == NULL */
|
||||
if (magic >= 2) {
|
||||
/* resume next case in AWAITING_RETURN state */
|
||||
assert(s->state == JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN ||
|
||||
s->state == JS_ASYNC_GENERATOR_STATE_COMPLETED);
|
||||
s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;
|
||||
if (is_reject) {
|
||||
js_async_generator_reject(ctx, s, arg);
|
||||
} else {
|
||||
js_async_generator_resolve(ctx, s, arg, TRUE);
|
||||
}
|
||||
} else {
|
||||
/* restart function execution after await() */
|
||||
assert(s->state == JS_ASYNC_GENERATOR_STATE_EXECUTING);
|
||||
s->func_state.throw_flag = is_reject;
|
||||
if (is_reject) {
|
||||
JS_Throw(ctx, JS_DupValue(ctx, arg));
|
||||
} else {
|
||||
/* return value of await */
|
||||
s->func_state.frame.cur_sp[-1] = JS_DupValue(ctx, arg);
|
||||
}
|
||||
js_async_generator_resume_next(ctx, s);
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
void js_async_generator_free(JSRuntime *rt, JSAsyncGeneratorData *s)
|
||||
{
|
||||
struct list_head *el, *el1;
|
||||
JSAsyncGeneratorRequest *req;
|
||||
list_for_each_safe(el, el1, &s->queue) {
|
||||
req = list_entry(el, JSAsyncGeneratorRequest, link);
|
||||
JS_FreeValueRT(rt, req->result);
|
||||
JS_FreeValueRT(rt, req->promise);
|
||||
JS_FreeValueRT(rt, req->resolving_funcs[0]);
|
||||
JS_FreeValueRT(rt, req->resolving_funcs[1]);
|
||||
js_free_rt(rt, req);
|
||||
}
|
||||
if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED &&
|
||||
s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) {
|
||||
async_func_free(rt, &s->func_state);
|
||||
}
|
||||
js_free_rt(rt, s);
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_generator_function_proto_funcs[] = {
|
||||
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "GeneratorFunction", JS_PROP_CONFIGURABLE),
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_generator_proto_funcs[] = {
|
||||
JS_ITERATOR_NEXT_DEF("next", 1, js_generator_next, GEN_MAGIC_NEXT ),
|
||||
JS_ITERATOR_NEXT_DEF("return", 1, js_generator_next, GEN_MAGIC_RETURN ),
|
||||
JS_ITERATOR_NEXT_DEF("throw", 1, js_generator_next, GEN_MAGIC_THROW ),
|
||||
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Generator", JS_PROP_CONFIGURABLE),
|
||||
};
|
||||
|
||||
void JS_AddIntrinsicGenerator(JSContext *ctx)
|
||||
{
|
||||
JSValue obj1;
|
||||
ctx->class_proto[JS_CLASS_GENERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto);
|
||||
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_GENERATOR],
|
||||
js_generator_proto_funcs,
|
||||
countof(js_generator_proto_funcs));
|
||||
ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto);
|
||||
obj1 = JS_NewCFunctionMagic(ctx, js_function_constructor,
|
||||
"GeneratorFunction", 1,
|
||||
JS_CFUNC_constructor_or_func_magic, JS_FUNC_GENERATOR);
|
||||
JS_SetPropertyFunctionList(ctx,
|
||||
ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION],
|
||||
js_generator_function_proto_funcs,
|
||||
countof(js_generator_function_proto_funcs));
|
||||
JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION],
|
||||
ctx->class_proto[JS_CLASS_GENERATOR],
|
||||
JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE);
|
||||
JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION],
|
||||
0, JS_PROP_CONFIGURABLE);
|
||||
JS_FreeValue(ctx, obj1);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue