in src/couch_quickjs/quickjs/run-test262.c [1217:1409]
static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len,
const char *filename, int is_test, int is_negative,
const char *error_type, FILE *outfile, int eval_flags,
int is_async)
{
JSValue res_val, exception_val;
int ret, error_line, pos, pos_line;
BOOL is_error, has_error_line, ret_promise;
const char *error_name;
pos = skip_comments(buf, 1, &pos_line);
error_line = pos_line;
has_error_line = FALSE;
exception_val = JS_UNDEFINED;
error_name = NULL;
/* a module evaluation returns a promise */
ret_promise = ((eval_flags & JS_EVAL_TYPE_MODULE) != 0);
async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */
res_val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
if ((is_async || ret_promise) && !JS_IsException(res_val)) {
JSValue promise = JS_UNDEFINED;
if (ret_promise) {
promise = res_val;
} else {
JS_FreeValue(ctx, res_val);
}
for(;;) {
JSContext *ctx1;
ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
if (ret < 0) {
res_val = JS_EXCEPTION;
break;
} else if (ret == 0) {
if (is_async) {
/* test if the test called $DONE() once */
if (async_done != 1) {
res_val = JS_ThrowTypeError(ctx, "$DONE() not called");
} else {
res_val = JS_UNDEFINED;
}
} else {
/* check that the returned promise is fulfilled */
JSPromiseStateEnum state = JS_PromiseState(ctx, promise);
if (state == JS_PROMISE_FULFILLED)
res_val = JS_UNDEFINED;
else if (state == JS_PROMISE_REJECTED)
res_val = JS_Throw(ctx, JS_PromiseResult(ctx, promise));
else
res_val = JS_ThrowTypeError(ctx, "promise is pending");
}
break;
}
}
JS_FreeValue(ctx, promise);
}
if (JS_IsException(res_val)) {
exception_val = JS_GetException(ctx);
is_error = JS_IsError(ctx, exception_val);
/* XXX: should get the filename and line number */
if (outfile) {
if (!is_error)
fprintf(outfile, "%sThrow: ", (eval_flags & JS_EVAL_FLAG_STRICT) ?
"strict mode: " : "");
js_print(ctx, JS_NULL, 1, &exception_val);
}
if (is_error) {
JSValue name, stack;
const char *stack_str;
name = JS_GetPropertyStr(ctx, exception_val, "name");
error_name = JS_ToCString(ctx, name);
stack = JS_GetPropertyStr(ctx, exception_val, "stack");
if (!JS_IsUndefined(stack)) {
stack_str = JS_ToCString(ctx, stack);
if (stack_str) {
const char *p;
int len;
if (outfile)
fprintf(outfile, "%s", stack_str);
len = strlen(filename);
p = strstr(stack_str, filename);
if (p != NULL && p[len] == ':') {
error_line = atoi(p + len + 1);
has_error_line = TRUE;
}
JS_FreeCString(ctx, stack_str);
}
}
JS_FreeValue(ctx, stack);
JS_FreeValue(ctx, name);
}
if (is_negative) {
ret = 0;
if (error_type) {
char *error_class;
const char *msg;
msg = JS_ToCString(ctx, exception_val);
error_class = strdup_len(msg, strcspn(msg, ":"));
if (!str_equal(error_class, error_type))
ret = -1;
free(error_class);
JS_FreeCString(ctx, msg);
}
} else {
ret = -1;
}
} else {
if (is_negative)
ret = -1;
else
ret = 0;
}
if (verbose && is_test) {
JSValue msg_val = JS_UNDEFINED;
const char *msg = NULL;
int s_line;
char *s = find_error(filename, &s_line, eval_flags & JS_EVAL_FLAG_STRICT);
const char *strict_mode = (eval_flags & JS_EVAL_FLAG_STRICT) ? "strict mode: " : "";
if (!JS_IsUndefined(exception_val)) {
msg_val = JS_ToString(ctx, exception_val);
msg = JS_ToCString(ctx, msg_val);
}
if (is_negative) { // expect error
if (ret == 0) {
if (msg && s &&
(str_equal(s, "expected error") ||
strstart(s, "unexpected error type:", NULL) ||
str_equal(s, msg))) { // did not have error yet
if (!has_error_line) {
longest_match(buf, msg, pos, &pos, pos_line, &error_line);
}
printf("%s:%d: %sOK, now has error %s\n",
filename, error_line, strict_mode, msg);
fixed_errors++;
}
} else {
if (!s) { // not yet reported
if (msg) {
fprintf(error_out, "%s:%d: %sunexpected error type: %s\n",
filename, error_line, strict_mode, msg);
} else {
fprintf(error_out, "%s:%d: %sexpected error\n",
filename, error_line, strict_mode);
}
new_errors++;
}
}
} else { // should not have error
if (msg) {
if (!s || !str_equal(s, msg)) {
if (!has_error_line) {
char *p = skip_prefix(msg, "Test262 Error: ");
if (strstr(p, "Test case returned non-true value!")) {
longest_match(buf, "runTestCase", pos, &pos, pos_line, &error_line);
} else {
longest_match(buf, p, pos, &pos, pos_line, &error_line);
}
}
fprintf(error_out, "%s:%d: %s%s%s\n", filename, error_line, strict_mode,
error_file ? "unexpected error: " : "", msg);
if (s && (!str_equal(s, msg) || error_line != s_line)) {
printf("%s:%d: %sprevious error: %s\n", filename, s_line, strict_mode, s);
changed_errors++;
} else {
new_errors++;
}
}
} else {
if (s) {
printf("%s:%d: %sOK, fixed error: %s\n", filename, s_line, strict_mode, s);
fixed_errors++;
}
}
}
JS_FreeValue(ctx, msg_val);
JS_FreeCString(ctx, msg);
free(s);
}
JS_FreeCString(ctx, error_name);
JS_FreeValue(ctx, exception_val);
JS_FreeValue(ctx, res_val);
return ret;
}