From: Dmitry Volyntsev Date: Wed, 3 Jun 2026 02:05:19 +0000 (-0700) Subject: Fetch: fixed exception classes X-Git-Tag: 1.0.0~29 X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/NGINX-js-1660x332.png%20%22NGINX%20JavaScript%20Banner%22?a=commitdiff_plain;h=6292a22a73ada499549ec9b5d99117c29570bd9d;p=njs.git Fetch: fixed exception classes Report API misuse in Fetch, Request, Response, and Headers as TypeError, and report status bounds violations as RangeError. Keep internal host failures as InternalError and preserve conversion helper exceptions where they already provide the real cause. --- diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index b1bf55ec..145617f0 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -540,7 +540,7 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (u.host.len >= NGX_JS_HOST_MAX_LEN) { - njs_vm_error(vm, "Host name too long"); + njs_vm_type_error(vm, "Host name too long"); goto fail; } @@ -608,7 +608,7 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, &http->proxy.url, &http->proxy.auth) != NGX_OK) { - njs_vm_error(vm, "failed to evaluate proxy URL"); + njs_vm_internal_error(vm, "failed to evaluate proxy URL"); goto fail; } @@ -628,7 +628,7 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (ngx_js_check_request_line_component(u.uri.data, u.uri.len) != NGX_OK) { - njs_vm_error(vm, "invalid url"); + njs_vm_type_error(vm, "invalid url"); goto fail; } @@ -649,7 +649,7 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (ctx == NGX_NO_RESOLVER) { - njs_vm_error(vm, "no resolver defined"); + njs_vm_internal_error(vm, "no resolver defined"); goto fail; } @@ -801,13 +801,12 @@ ngx_js_ext_response_constructor(njs_vm_t *vm, njs_value_t *args, value = njs_vm_object_prop(vm, init, &status, &lvalue); if (value != NULL) { if (ngx_js_integer(vm, value, &response->code) != NGX_OK) { - njs_vm_error(vm, "invalid Response status"); return NJS_ERROR; } if (response->code < 200 || response->code > 599) { - njs_vm_error(vm, "status provided (%i) is outside of " - "[200, 599] range", response->code); + njs_vm_range_error(vm, "status provided (%i) is outside of " + "[200, 599] range", response->code); return NJS_ERROR; } } @@ -815,7 +814,6 @@ ngx_js_ext_response_constructor(njs_vm_t *vm, njs_value_t *args, value = njs_vm_object_prop(vm, init, &status_text, &lvalue); if (value != NULL) { if (ngx_js_ngx_string(vm, value, &response->status_text) != NGX_OK) { - njs_vm_error(vm, "invalid Response statusText"); return NJS_ERROR; } @@ -824,7 +822,7 @@ ngx_js_ext_response_constructor(njs_vm_t *vm, njs_value_t *args, while (p < end) { if (*p != '\t' && *p < ' ') { - njs_vm_error(vm, "invalid Response statusText"); + njs_vm_type_error(vm, "invalid Response statusText"); return NJS_ERROR; } @@ -835,7 +833,7 @@ ngx_js_ext_response_constructor(njs_vm_t *vm, njs_value_t *args, value = njs_vm_object_prop(vm, init, &headers, &lvalue); if (value != NULL) { if (!njs_value_is_object(value)) { - njs_vm_error(vm, "Headers is not an object"); + njs_vm_type_error(vm, "Headers is not an object"); return NJS_ERROR; } @@ -852,7 +850,6 @@ ngx_js_ext_response_constructor(njs_vm_t *vm, njs_value_t *args, if (!njs_value_is_null_or_undefined(body)) { if (ngx_js_string(vm, body, &bd) != NGX_OK) { - njs_vm_error(vm, "invalid Response body"); return NJS_ERROR; } @@ -908,13 +905,13 @@ ngx_js_method_process(njs_vm_t *vm, ngx_js_request_t *request) request->method.len) != NGX_OK) { - njs_vm_error(vm, "invalid Request method"); + njs_vm_type_error(vm, "invalid Request method"); return NJS_ERROR; } for (m = &forbidden[0]; m->length != 0; m++) { if (njs_strstr_case_eq(&str, m)) { - njs_vm_error(vm, "forbidden method: %V", m); + njs_vm_type_error(vm, "forbidden method: %V", m); return NJS_ERROR; } } @@ -1012,7 +1009,8 @@ ngx_js_headers_fill(njs_vm_t *vm, ngx_js_headers_t *headers, njs_value_t *init) start++; if (len != 2) { - njs_vm_error(vm, "header does not contain exactly two items"); + njs_vm_type_error(vm, + "header does not contain exactly two items"); return NJS_ERROR; } @@ -1143,7 +1141,7 @@ ngx_js_fetch_alloc(njs_vm_t *vm, ngx_pool_t *pool, ngx_log_t *log, failed: - njs_vm_error(vm, "internal error"); + njs_vm_internal_error(vm, "internal error"); return NULL; } @@ -1220,7 +1218,7 @@ ngx_js_fetch_promissified_result(njs_vm_t *vm, njs_value_t *result, error: - njs_vm_error(vm, "internal error"); + njs_vm_internal_error(vm, "internal error"); return NJS_ERROR; } @@ -1299,7 +1297,7 @@ ngx_js_request_constructor(njs_vm_t *vm, ngx_js_request_t *request, input = njs_arg(args, nargs, 1); if (njs_value_is_undefined(input)) { - njs_vm_error(vm, "1st argument is required"); + njs_vm_type_error(vm, "1st argument is required"); return NJS_ERROR; } @@ -1334,14 +1332,13 @@ ngx_js_request_constructor(njs_vm_t *vm, ngx_js_request_t *request, if (njs_value_is_string(input)) { ret = ngx_js_ngx_string(vm, input, &request->url); if (ret != NJS_OK) { - njs_vm_error(vm, "failed to convert url arg"); return NJS_ERROR; } } else { orig = njs_vm_external(vm, ngx_http_js_fetch_request_proto_id, input); if (orig == NULL) { - njs_vm_error(vm, "input is not string or a Request object"); + njs_vm_type_error(vm, "input is not string or a Request object"); return NJS_ERROR; } @@ -1385,13 +1382,13 @@ ngx_js_request_constructor(njs_vm_t *vm, ngx_js_request_t *request, #endif } else { - njs_vm_error(vm, "unsupported URL schema (only http or https are" - " supported)"); + njs_vm_type_error(vm, "unsupported URL schema (only http or https are" + " supported)"); return NJS_ERROR; } if (ngx_parse_url(pool, u) != NGX_OK) { - njs_vm_error(vm, "invalid url"); + njs_vm_type_error(vm, "invalid url"); return NJS_ERROR; } @@ -1402,7 +1399,6 @@ ngx_js_request_constructor(njs_vm_t *vm, ngx_js_request_t *request, if (value != NULL && ngx_js_ngx_string(vm, value, &request->method) != NGX_OK) { - njs_vm_error(vm, "invalid Request method"); return NJS_ERROR; } @@ -1446,7 +1442,7 @@ ngx_js_request_constructor(njs_vm_t *vm, ngx_js_request_t *request, headers = njs_vm_object_prop(vm, init, &headers_key, &lvalue); if (headers != NULL) { if (!njs_value_is_object(headers)) { - njs_vm_error(vm, "Headers is not an object"); + njs_vm_type_error(vm, "Headers is not an object"); return NJS_ERROR; } @@ -1474,7 +1470,6 @@ ngx_js_request_constructor(njs_vm_t *vm, ngx_js_request_t *request, value = njs_vm_object_prop(vm, init, &body_key, &lvalue); if (value != NULL) { if (ngx_js_ngx_string(vm, value, &request->body) != NGX_OK) { - njs_vm_error(vm, "invalid Request body"); return NJS_ERROR; } @@ -1543,18 +1538,18 @@ ngx_js_headers_append(njs_vm_t *vm, ngx_js_headers_t *headers, ret = ngx_js_check_header_name(name, len); if (ret != NGX_OK) { - njs_vm_error(vm, "invalid header name"); + njs_vm_type_error(vm, "invalid header name"); return NJS_ERROR; } ret = ngx_js_check_header_value(value, vlen); if (ret != NGX_OK) { - njs_vm_error(vm, "invalid header value"); + njs_vm_type_error(vm, "invalid header value"); return NJS_ERROR; } if (headers->guard == GUARD_IMMUTABLE) { - njs_vm_error(vm, "cannot append to immutable object"); + njs_vm_type_error(vm, "cannot append to immutable object"); return NJS_ERROR; } @@ -1724,7 +1719,7 @@ ngx_headers_js_ext_append(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, headers = njs_vm_external(vm, ngx_http_js_fetch_headers_proto_id, njs_argument(args, 0)); if (headers == NULL) { - njs_vm_error(vm, "\"this\" is not fetch headers object"); + njs_vm_type_error(vm, "\"this\" is not fetch headers object"); return NJS_ERROR; } @@ -1764,7 +1759,7 @@ ngx_headers_js_ext_delete(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, headers = njs_vm_external(vm, ngx_http_js_fetch_headers_proto_id, njs_argument(args, 0)); if (headers == NULL) { - njs_vm_error(vm, "\"this\" is not fetch headers object"); + njs_vm_type_error(vm, "\"this\" is not fetch headers object"); return NJS_ERROR; } @@ -1827,14 +1822,14 @@ ngx_headers_js_ext_for_each(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, headers = njs_vm_external(vm, ngx_http_js_fetch_headers_proto_id, this); if (headers == NULL) { - njs_vm_error(vm, "\"this\" is not fetch headers object"); + njs_vm_type_error(vm, "\"this\" is not fetch headers object"); return NJS_ERROR; } callback = njs_arg(args, nargs, 1); if (!njs_value_is_function(callback)) { - njs_vm_error(vm, "\"callback\" is not a function"); + njs_vm_type_error(vm, "\"callback\" is not a function"); return NJS_ERROR; } @@ -2064,7 +2059,7 @@ ngx_headers_js_ext_set(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, headers = njs_vm_external(vm, ngx_http_js_fetch_headers_proto_id, njs_argument(args, 0)); if (headers == NULL) { - njs_vm_error(vm, "\"this\" is not fetch headers object"); + njs_vm_type_error(vm, "\"this\" is not fetch headers object"); return NJS_ERROR; } @@ -2145,7 +2140,7 @@ ngx_request_js_ext_body(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (request->body_used) { - njs_vm_error(vm, "body stream already read"); + njs_vm_type_error(vm, "body stream already read"); return NJS_ERROR; } @@ -2258,7 +2253,7 @@ ngx_request_js_ext_headers(njs_vm_t *vm, njs_object_prop_t *prop, ngx_http_js_fetch_headers_proto_id, &request->headers, 0); if (ret != NJS_OK) { - njs_vm_error(vm, "fetch header creation failed"); + njs_vm_memory_error(vm); return NJS_ERROR; } } @@ -2303,7 +2298,7 @@ ngx_response_js_ext_body(njs_vm_t *vm, njs_value_t *args, } if (response->body_used) { - njs_vm_error(vm, "body stream already read"); + njs_vm_type_error(vm, "body stream already read"); return NJS_ERROR; } @@ -2385,7 +2380,7 @@ ngx_response_js_ext_headers(njs_vm_t *vm, njs_object_prop_t *prop, ngx_http_js_fetch_headers_proto_id, &response->headers, 0); if (ret != NJS_OK) { - njs_vm_error(vm, "fetch header creation failed"); + njs_vm_memory_error(vm); return NJS_ERROR; } } @@ -2509,7 +2504,7 @@ ngx_fetch_flag_set(njs_vm_t *vm, const ngx_js_entry_t *entries, } } - njs_vm_error(vm, "unknown %s type: %V", type, &flag); + njs_vm_type_error(vm, "unknown %s type: %V", type, &flag); return NJS_ERROR; } diff --git a/nginx/ngx_qjs_fetch.c b/nginx/ngx_qjs_fetch.c index 162531e5..4aa8f54f 100644 --- a/nginx/ngx_qjs_fetch.c +++ b/nginx/ngx_qjs_fetch.c @@ -260,7 +260,7 @@ ngx_qjs_ext_fetch(JSContext *cx, JSValueConst this_val, int argc, } if (u.host.len >= NGX_JS_HOST_MAX_LEN) { - JS_ThrowInternalError(cx, "Host name too long"); + JS_ThrowTypeError(cx, "Host name too long"); goto fail; } @@ -365,7 +365,7 @@ ngx_qjs_ext_fetch(JSContext *cx, JSValueConst this_val, int argc, } if (ngx_js_check_request_line_component(u.uri.data, u.uri.len) != NGX_OK) { - JS_ThrowInternalError(cx, "invalid url"); + JS_ThrowTypeError(cx, "invalid url"); goto fail; } @@ -522,7 +522,7 @@ ngx_qjs_request_ctor(JSContext *cx, ngx_js_request_t *request, input = argv[0]; if (JS_IsUndefined(input)) { - JS_ThrowInternalError(cx, "1st argument is required"); + JS_ThrowTypeError(cx, "1st argument is required"); return NGX_ERROR; } @@ -568,8 +568,8 @@ ngx_qjs_request_ctor(JSContext *cx, ngx_js_request_t *request, } else { orig = JS_GetOpaque(input, NGX_QJS_CLASS_ID_FETCH_REQUEST); if (orig == NULL) { - JS_ThrowInternalError(cx, - "input is not string or a Request object"); + JS_ThrowTypeError(cx, + "input is not string or a Request object"); return NGX_ERROR; } @@ -612,13 +612,13 @@ ngx_qjs_request_ctor(JSContext *cx, ngx_js_request_t *request, #endif } else { - JS_ThrowInternalError(cx, "unsupported URL schema (only http or https" - " are supported)"); + JS_ThrowTypeError(cx, "unsupported URL schema (only http or https" + " are supported)"); return NGX_ERROR; } if (ngx_parse_url(pool, u) != NGX_OK) { - JS_ThrowInternalError(cx, "invalid url"); + JS_ThrowTypeError(cx, "invalid url"); return NGX_ERROR; } @@ -626,7 +626,6 @@ ngx_qjs_request_ctor(JSContext *cx, ngx_js_request_t *request, init = argv[1]; value = JS_GetPropertyStr(cx, init, "method"); if (JS_IsException(value)) { - JS_ThrowInternalError(cx, "invalid Request method"); return NGX_ERROR; } @@ -673,14 +672,13 @@ ngx_qjs_request_ctor(JSContext *cx, ngx_js_request_t *request, value = JS_GetPropertyStr(cx, init, "headers"); if (JS_IsException(value)) { - JS_ThrowInternalError(cx, "invalid Request headers"); return NGX_ERROR; } if (!JS_IsUndefined(value)) { if (!JS_IsObject(value)) { JS_FreeValue(cx, value); - JS_ThrowInternalError(cx, "Headers is not an object"); + JS_ThrowTypeError(cx, "Headers is not an object"); return NGX_ERROR; } @@ -710,7 +708,6 @@ ngx_qjs_request_ctor(JSContext *cx, ngx_js_request_t *request, value = JS_GetPropertyStr(cx, init, "body"); if (JS_IsException(value)) { - JS_ThrowInternalError(cx, "invalid Request body"); return NGX_ERROR; } @@ -788,7 +785,7 @@ ngx_qjs_fetch_response_ctor(JSContext *cx, JSValueConst new_target, int argc, if (JS_IsObject(init)) { value = JS_GetPropertyStr(cx, init, "status"); if (JS_IsException(value)) { - return JS_ThrowInternalError(cx, "invalid Response status"); + return JS_EXCEPTION; } if (!JS_IsUndefined(value)) { @@ -800,15 +797,15 @@ ngx_qjs_fetch_response_ctor(JSContext *cx, JSValueConst new_target, int argc, } if (response->code < 200 || response->code > 599) { - return JS_ThrowInternalError(cx, "status provided (%d) is " - "outside of [200, 599] range", - (int) response->code); + return JS_ThrowRangeError(cx, "status provided (%d) is " + "outside of [200, 599] range", + (int) response->code); } } value = JS_GetPropertyStr(cx, init, "statusText"); if (JS_IsException(value)) { - return JS_ThrowInternalError(cx, "invalid Response statusText"); + return JS_EXCEPTION; } if (!JS_IsUndefined(value)) { @@ -828,8 +825,8 @@ ngx_qjs_fetch_response_ctor(JSContext *cx, JSValueConst new_target, int argc, while (p < end) { if (*p != '\t' && *p < ' ') { - return JS_ThrowInternalError(cx, - "invalid Response statusText"); + return JS_ThrowTypeError(cx, + "invalid Response statusText"); } p++; @@ -838,13 +835,13 @@ ngx_qjs_fetch_response_ctor(JSContext *cx, JSValueConst new_target, int argc, value = JS_GetPropertyStr(cx, init, "headers"); if (JS_IsException(value)) { - return JS_ThrowInternalError(cx, "invalid Response headers"); + return JS_EXCEPTION; } if (!JS_IsUndefined(value)) { if (!JS_IsObject(value)) { JS_FreeValue(cx, value); - return JS_ThrowInternalError(cx, "Headers is not an object"); + return JS_ThrowTypeError(cx, "Headers is not an object"); } rc = ngx_qjs_headers_fill(cx, &response->headers, value); @@ -962,7 +959,7 @@ ngx_qjs_method_process(JSContext *cx, ngx_js_request_t *request) request->method.len) != NGX_OK) { - JS_ThrowInternalError(cx, "invalid Request method"); + JS_ThrowTypeError(cx, "invalid Request method"); return NGX_ERROR; } @@ -970,8 +967,8 @@ ngx_qjs_method_process(JSContext *cx, ngx_js_request_t *request) if (request->method.len == m->len && ngx_strncasecmp(request->method.data, m->data, m->len) == 0) { - JS_ThrowInternalError(cx, "forbidden method: %.*s", - (int) m->len, m->data); + JS_ThrowTypeError(cx, "forbidden method: %.*s", + (int) m->len, m->data); return NGX_ERROR; } } @@ -1109,8 +1106,8 @@ ngx_qjs_headers_fill(JSContext *cx, ngx_js_headers_t *headers, JSValue init) if (length != 2) { JS_FreeValue(cx, header); - JS_ThrowInternalError(cx, - "header does not contain exactly two items"); + JS_ThrowTypeError(cx, + "header does not contain exactly two items"); goto fail; } @@ -1368,18 +1365,18 @@ ngx_qjs_headers_append(JSContext *cx, ngx_js_headers_t *headers, ret = ngx_js_check_header_name(name, len); if (ret != NGX_OK) { - JS_ThrowInternalError(cx, "invalid header name"); + JS_ThrowTypeError(cx, "invalid header name"); return NGX_ERROR; } ret = ngx_js_check_header_value(value, vlen); if (ret != NGX_OK) { - JS_ThrowInternalError(cx, "invalid header value"); + JS_ThrowTypeError(cx, "invalid header value"); return NGX_ERROR; } if (headers->guard == GUARD_IMMUTABLE) { - JS_ThrowInternalError(cx, "cannot append to immutable object"); + JS_ThrowTypeError(cx, "cannot append to immutable object"); return NGX_ERROR; } @@ -1699,9 +1696,9 @@ ngx_qjs_fetch_headers_own_property_names(JSContext *cx, JSPropertyEnum **ptab, ngx_js_tb_elt_t *h; ngx_js_headers_t *headers; - headers = JS_GetOpaque2(cx, obj, NGX_QJS_CLASS_ID_FETCH_HEADERS); + headers = JS_GetOpaque(obj, NGX_QJS_CLASS_ID_FETCH_HEADERS); if (headers == NULL) { - (void) JS_ThrowInternalError(cx, "\"this\" is not a Headers object"); + (void) JS_ThrowTypeError(cx, "\"this\" is not a Headers object"); return -1; } @@ -1766,10 +1763,10 @@ ngx_qjs_ext_fetch_headers_append(JSContext *cx, JSValueConst this_val, ngx_int_t rc; ngx_js_headers_t *headers; - headers = JS_GetOpaque2(cx, this_val, NGX_QJS_CLASS_ID_FETCH_HEADERS); + headers = JS_GetOpaque(this_val, NGX_QJS_CLASS_ID_FETCH_HEADERS); if (headers == NULL) { - return JS_ThrowInternalError(cx, - "\"this\" is not fetch headers object"); + return JS_ThrowTypeError(cx, + "\"this\" is not fetch headers object"); } rc = ngx_qjs_headers_fill_header_free(cx, headers, @@ -1793,10 +1790,10 @@ ngx_qjs_ext_fetch_headers_delete(JSContext *cx, JSValueConst this_val, ngx_js_tb_elt_t *h; ngx_js_headers_t *headers; - headers = JS_GetOpaque2(cx, this_val, NGX_QJS_CLASS_ID_FETCH_HEADERS); + headers = JS_GetOpaque(this_val, NGX_QJS_CLASS_ID_FETCH_HEADERS); if (headers == NULL) { - return JS_ThrowInternalError(cx, - "\"this\" is not fetch headers object"); + return JS_ThrowTypeError(cx, + "\"this\" is not fetch headers object"); } name.data = (u_char *) JS_ToCStringLen(cx, &name.len, argv[0]); @@ -1854,16 +1851,16 @@ ngx_qjs_ext_fetch_headers_foreach(JSContext *cx, JSValueConst this_val, ngx_uint_t i; ngx_js_headers_t *headers; - headers = JS_GetOpaque2(cx, this_val, NGX_QJS_CLASS_ID_FETCH_HEADERS); + headers = JS_GetOpaque(this_val, NGX_QJS_CLASS_ID_FETCH_HEADERS); if (headers == NULL) { - return JS_ThrowInternalError(cx, - "\"this\" is not fetch headers object"); + return JS_ThrowTypeError(cx, + "\"this\" is not fetch headers object"); } callback = argv[0]; if (!JS_IsFunction(cx, callback)) { - return JS_ThrowInternalError(cx, "\"callback\" is not a function"); + return JS_ThrowTypeError(cx, "\"callback\" is not a function"); } keys = ngx_qjs_headers_ext_keys(cx, this_val); @@ -1974,10 +1971,10 @@ ngx_qjs_ext_fetch_headers_set(JSContext *cx, JSValueConst this_val, ngx_js_tb_elt_t *h, **ph, **pp; ngx_js_headers_t *headers; - headers = JS_GetOpaque2(cx, this_val, NGX_QJS_CLASS_ID_FETCH_HEADERS); + headers = JS_GetOpaque(this_val, NGX_QJS_CLASS_ID_FETCH_HEADERS); if (headers == NULL) { - return JS_ThrowInternalError(cx, - "\"this\" is not fetch headers object"); + return JS_ThrowTypeError(cx, + "\"this\" is not fetch headers object"); } name.data = (u_char *) JS_ToCStringLen(cx, &name.len, argv[0]); @@ -2057,7 +2054,7 @@ ngx_qjs_ext_fetch_request_body(JSContext *cx, JSValueConst this_val, } if (request->body_used) { - return JS_ThrowInternalError(cx, "body stream already read"); + return JS_ThrowTypeError(cx, "body stream already read"); } request->body_used = 1; @@ -2171,7 +2168,7 @@ ngx_qjs_ext_fetch_request_headers(JSContext *cx, JSValueConst this_val) if (JS_IsUndefined(header)) { header = JS_NewObjectClass(cx, NGX_QJS_CLASS_ID_FETCH_HEADERS); if (JS_IsException(header)) { - return JS_ThrowInternalError(cx, "fetch header creation failed"); + return JS_ThrowOutOfMemory(cx); } JS_SetOpaque(header, &request->headers); @@ -2298,7 +2295,7 @@ ngx_qjs_ext_fetch_response_headers(JSContext *cx, JSValueConst this_val) if (JS_IsUndefined(header)) { header = JS_NewObjectClass(cx, NGX_QJS_CLASS_ID_FETCH_HEADERS); if (JS_IsException(header)) { - return JS_ThrowInternalError(cx, "fetch header creation failed"); + return JS_ThrowOutOfMemory(cx); } JS_SetOpaque(header, &response->headers); @@ -2339,7 +2336,7 @@ ngx_qjs_ext_fetch_response_body(JSContext *cx, JSValueConst this_val, } if (response->body_used) { - return JS_ThrowInternalError(cx, "body stream already read"); + return JS_ThrowTypeError(cx, "body stream already read"); } response->body_used = 1; @@ -2463,7 +2460,6 @@ ngx_qjs_fetch_flag_set(JSContext *cx, const ngx_qjs_entry_t *entries, value = JS_GetPropertyStr(cx, object, prop); if (JS_IsException(value)) { - JS_ThrowInternalError(cx, "failed to get %s property", prop); return NGX_ERROR; } @@ -2486,8 +2482,8 @@ ngx_qjs_fetch_flag_set(JSContext *cx, const ngx_qjs_entry_t *entries, } } - JS_ThrowInternalError(cx, "unknown %s type: %.*s", prop, - (int) flag.len, flag.data); + JS_ThrowTypeError(cx, "unknown %s type: %.*s", prop, + (int) flag.len, flag.data); JS_FreeCString(cx, (const char *) flag.data); diff --git a/nginx/t/js_fetch_objects.t b/nginx/t/js_fetch_objects.t index 8bf9cf1d..8a6806ac 100644 --- a/nginx/t/js_fetch_objects.t +++ b/nginx/t/js_fetch_objects.t @@ -239,6 +239,21 @@ $t->write_file('test.js', < { r.push(`\${v}:\${k}`)}) return r.join('|'); }, 'a:0, 4|c:2|q:5|z:3'], + ['receiver', () => { + try { + (new Headers()).append.call({}, 'a', 'b'); + throw new Error('no error'); + + } catch (e) { + if (!(e instanceof TypeError) + || e.message != '"this" is not fetch headers object') + { + throw e; + } + } + + return 'OK'; + }, 'OK'], ['set', () => { var h = new Headers([['A', 'x'], ['a', 'y'], ['a', 'z']]); h.set('a', '#'); @@ -376,7 +391,9 @@ $t->write_file('test.js', <write_file('test.js', <write_file('test.js', < { + try { + new Response(null, {status: 199}); + throw new Error('no error'); + + } catch (e) { + if (!(e instanceof RangeError) + || !e.message.startsWith('status provided (199) is')) + { + throw e; + } + } + + return 'OK'; + }, 'OK'], ];