From noreply at nginx.com Thu Apr 3 04:11:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Thu, 3 Apr 2025 04:11:02 +0000 (UTC) Subject: [njs] QuickJS: fix exception handling during configuration phase. Message-ID: <20250403041102.3695B4839F@pubserv1.nginx> details: https://github.com/nginx/njs/commit/a4d0f9478dc0fb5c0cd5e9003a208ca3fb8ecb15 branches: master commit: a4d0f9478dc0fb5c0cd5e9003a208ca3fb8ecb15 user: Zhidao HONG date: Thu, 3 Apr 2025 11:44:57 +0800 description: QuickJS: fix exception handling during configuration phase. The issue was introduced in 9010aee (not released yet). --- nginx/ngx_js.c | 50 +++++++++++++++++++++----------------------- nginx/ngx_js.h | 2 +- nginx/ngx_stream_js_module.c | 2 +- 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/nginx/ngx_js.c b/nginx/ngx_js.c index c91a5530..ba0fee92 100644 --- a/nginx/ngx_js.c +++ b/nginx/ngx_js.c @@ -101,7 +101,7 @@ static void ngx_qjs_rejection_tracker(JSContext *ctx, JSValueConst promise, JSValueConst reason, JS_BOOL is_handled, void *opaque); static JSValue ngx_qjs_value(JSContext *cx, const ngx_str_t *path); -static ngx_int_t ngx_qjs_dump_obj(JSContext *cx, JSValueConst val, +static ngx_int_t ngx_qjs_dump_obj(ngx_engine_t *e, JSValueConst val, ngx_str_t *dst); static JSModuleDef *ngx_qjs_core_init(JSContext *cx, const char *name); @@ -849,7 +849,7 @@ ngx_engine_qjs_compile(ngx_js_loc_conf_t *conf, ngx_log_t *log, u_char *start, JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); if (JS_IsException(code)) { - ngx_qjs_exception(cx, &text); + ngx_qjs_exception(engine, &text); ngx_log_error(NGX_LOG_EMERG, log, 0, "js compile %V", &text); return NGX_ERROR; } @@ -972,7 +972,7 @@ ngx_qjs_clone(ngx_js_ctx_t *ctx, ngx_js_loc_conf_t *cf, void *external) rv = JS_ReadObject(cx, pc[i].code, pc[i].code_size, JS_READ_OBJ_BYTECODE); if (JS_IsException(rv)) { - ngx_qjs_exception(cx, &exception); + ngx_qjs_exception(engine, &exception); ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js load module exception: %V", &exception); @@ -988,7 +988,7 @@ ngx_qjs_clone(ngx_js_ctx_t *ctx, ngx_js_loc_conf_t *cf, void *external) rv = JS_EvalFunction(cx, rv); if (JS_IsException(rv)) { - ngx_qjs_exception(cx, &exception); + ngx_qjs_exception(engine, &exception); ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js eval exception: %V", &exception); @@ -997,7 +997,7 @@ ngx_qjs_clone(ngx_js_ctx_t *ctx, ngx_js_loc_conf_t *cf, void *external) rv = js_std_await(cx, rv); if (JS_IsException(rv)) { - ngx_qjs_exception(cx, &exception); + ngx_qjs_exception(engine, &exception); ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js eval exception: %V", &exception); @@ -1042,7 +1042,7 @@ ngx_engine_qjs_call(ngx_js_ctx_t *ctx, ngx_str_t *fname, val = JS_Call(cx, fn, JS_UNDEFINED, nargs, &ngx_qjs_arg(args[0])); JS_FreeValue(cx, fn); if (JS_IsException(val)) { - ngx_qjs_exception(cx, &exception); + ngx_qjs_exception(ctx->engine, &exception); ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js call exception: %V", &exception); @@ -1059,7 +1059,7 @@ ngx_engine_qjs_call(ngx_js_ctx_t *ctx, ngx_str_t *fname, rc = JS_ExecutePendingJob(rt, &cx1); if (rc <= 0) { if (rc == -1) { - ngx_qjs_exception(cx, &exception); + ngx_qjs_exception(ctx->engine, &exception); ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js job exception: %V", &exception); @@ -1093,7 +1093,7 @@ static ngx_int_t ngx_engine_qjs_string(ngx_engine_t *e, njs_opaque_value_t *value, ngx_str_t *str) { - return ngx_qjs_dump_obj(e->u.qjs.ctx, ngx_qjs_arg(*value), str); + return ngx_qjs_dump_obj(e, ngx_qjs_arg(*value), str); } @@ -1150,7 +1150,7 @@ ngx_engine_qjs_destroy(ngx_engine_t *e, ngx_js_ctx_t *ctx, } if (ngx_qjs_unhandled_rejection(ctx)) { - ngx_qjs_exception(cx, &exception); + ngx_qjs_exception(e, &exception); ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js unhandled rejection: %V", &exception); } @@ -1255,17 +1255,13 @@ ngx_qjs_value(JSContext *cx, const ngx_str_t *path) static ngx_int_t -ngx_qjs_dump_obj(JSContext *cx, JSValueConst val, ngx_str_t *dst) +ngx_qjs_dump_obj(ngx_engine_t *e, JSValueConst val, ngx_str_t *dst) { - size_t len, byte_offset, byte_length; - u_char *start, *p; - JSValue buffer, stack; - ngx_str_t str, stack_str; - ngx_js_ctx_t *ctx; - ngx_engine_t *e; - - ctx = ngx_qjs_external_ctx(cx, JS_GetContextOpaque(cx)); - e = ctx->engine; + size_t len, byte_offset, byte_length; + u_char *start, *p; + JSValue buffer, stack; + ngx_str_t str, stack_str; + JSContext *cx; if (JS_IsNullOrUndefined(val)) { dst->data = NULL; @@ -1367,7 +1363,7 @@ ngx_qjs_call(JSContext *cx, JSValue fn, JSValue *argv, int argc) ret = JS_Call(cx, fn, JS_UNDEFINED, argc, argv); if (JS_IsException(ret)) { - ngx_qjs_exception(cx, &exception); + ngx_qjs_exception(ctx->engine, &exception); ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js call exception: %V", &exception); @@ -1383,7 +1379,7 @@ ngx_qjs_call(JSContext *cx, JSValue fn, JSValue *argv, int argc) rc = JS_ExecutePendingJob(rt, &cx1); if (rc <= 0) { if (rc == -1) { - ngx_qjs_exception(cx, &exception); + ngx_qjs_exception(ctx->engine, &exception); ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js job exception: %V", &exception); @@ -1400,16 +1396,16 @@ ngx_qjs_call(JSContext *cx, JSValue fn, JSValue *argv, int argc) ngx_int_t -ngx_qjs_exception(JSContext *cx, ngx_str_t *s) +ngx_qjs_exception(ngx_engine_t *e, ngx_str_t *s) { JSValue exception; - exception = JS_GetException(cx); - if (ngx_qjs_dump_obj(cx, exception, s) != NGX_OK) { + exception = JS_GetException(e->u.qjs.ctx); + if (ngx_qjs_dump_obj(e, exception, s) != NGX_OK) { return NGX_ERROR; } - JS_FreeValue(cx, exception); + JS_FreeValue(e->u.qjs.ctx, exception); return NGX_OK; } @@ -1746,6 +1742,7 @@ ngx_qjs_ext_log(JSContext *cx, JSValueConst this_val, int argc, char *p; uint32_t level; ngx_str_t msg; + ngx_js_ctx_t *ctx; ngx_connection_t *c; p = JS_GetContextOpaque(cx); @@ -1764,10 +1761,11 @@ ngx_qjs_ext_log(JSContext *cx, JSValueConst this_val, int argc, argv++; } + ctx = ngx_qjs_external_ctx(cx, p); c = ngx_qjs_external_connection(cx, p); for ( ; argc > 0; argc--, argv++) { - if (ngx_qjs_dump_obj(cx, argv[0], &msg) != NGX_OK) { + if (ngx_qjs_dump_obj(ctx->engine, argv[0], &msg) != NGX_OK) { return JS_EXCEPTION; } diff --git a/nginx/ngx_js.h b/nginx/ngx_js.h index ba4cbdf9..51b8916c 100644 --- a/nginx/ngx_js.h +++ b/nginx/ngx_js.h @@ -342,7 +342,7 @@ void ngx_engine_qjs_destroy(ngx_engine_t *e, ngx_js_ctx_t *ctx, ngx_js_loc_conf_t *conf); ngx_int_t ngx_qjs_call(JSContext *cx, JSValue function, JSValue *argv, int argc); -ngx_int_t ngx_qjs_exception(JSContext *cx, ngx_str_t *s); +ngx_int_t ngx_qjs_exception(ngx_engine_t *e, ngx_str_t *s); ngx_int_t ngx_qjs_integer(JSContext *cx, JSValueConst val, ngx_int_t *n); ngx_int_t ngx_qjs_string(JSContext *cx, JSValueConst val, ngx_str_t *str); diff --git a/nginx/ngx_stream_js_module.c b/nginx/ngx_stream_js_module.c index a7dddd04..b1e175d2 100644 --- a/nginx/ngx_stream_js_module.c +++ b/nginx/ngx_stream_js_module.c @@ -2672,7 +2672,7 @@ ngx_stream_qjs_run_event(ngx_stream_session_t *s, ngx_stream_js_ctx_t *ctx, if (rc == NGX_ERROR) { error: - ngx_qjs_exception(cx, &exception); + ngx_qjs_exception(ctx->engine, &exception); ngx_log_error(NGX_LOG_ERR, c->log, 0, "js exception: %V", &exception); From noreply at nginx.com Fri Apr 4 05:21:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Fri, 4 Apr 2025 05:21:02 +0000 (UTC) Subject: [njs] QuickJS: added xml to nginx modules. Message-ID: <20250404052102.60C6E4788F@pubserv1.nginx> details: https://github.com/nginx/njs/commit/f678c9048b734a6cfff36e6de9ecfe11bed266b4 branches: master commit: f678c9048b734a6cfff36e6de9ecfe11bed266b4 user: Dmitry Volyntsev date: Wed, 2 Apr 2025 17:47:10 -0700 description: QuickJS: added xml to nginx modules. Missed in cec9a1650. --- nginx/config | 4 ++++ nginx/ngx_http_js_module.c | 3 +++ nginx/ngx_js.h | 1 + nginx/ngx_stream_js_module.c | 3 +++ 4 files changed, 11 insertions(+) diff --git a/nginx/config b/nginx/config index 2edf7a3d..03ec03d0 100644 --- a/nginx/config +++ b/nginx/config @@ -129,6 +129,10 @@ if [ $NJS_LIBXSLT != NO ]; then have=NJS_HAVE_XML . auto/have NJS_SRCS="$NJS_SRCS $ngx_addon_dir/../external/njs_xml_module.c" + if [ "$NJS_HAVE_QUICKJS" = "YES" ]; then + NJS_SRCS="$NJS_SRCS $ngx_addon_dir/../external/qjs_xml_module.c" + fi + echo " enabled xml module" fi diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index 0c8215c5..5a131bc9 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -1140,6 +1140,9 @@ qjs_module_t *njs_http_qjs_addon_modules[] = { #ifdef NJS_HAVE_OPENSSL &qjs_webcrypto_module, #endif +#ifdef NJS_HAVE_XML + &qjs_xml_module, +#endif #ifdef NJS_HAVE_ZLIB &qjs_zlib_module, #endif diff --git a/nginx/ngx_js.h b/nginx/ngx_js.h index 51b8916c..0a99a696 100644 --- a/nginx/ngx_js.h +++ b/nginx/ngx_js.h @@ -378,6 +378,7 @@ ngx_int_t ngx_qjs_string(JSContext *cx, JSValueConst val, ngx_str_t *str); ((ngx_js_external_ctx_pt) ngx_qjs_meta(cx, 11))(e) extern qjs_module_t qjs_webcrypto_module; +extern qjs_module_t qjs_xml_module; extern qjs_module_t qjs_zlib_module; extern qjs_module_t ngx_qjs_ngx_module; extern qjs_module_t ngx_qjs_ngx_shared_dict_module; diff --git a/nginx/ngx_stream_js_module.c b/nginx/ngx_stream_js_module.c index b1e175d2..44c7af17 100644 --- a/nginx/ngx_stream_js_module.c +++ b/nginx/ngx_stream_js_module.c @@ -841,6 +841,9 @@ qjs_module_t *njs_stream_qjs_addon_modules[] = { #ifdef NJS_HAVE_OPENSSL &qjs_webcrypto_module, #endif +#ifdef NJS_HAVE_XML + &qjs_xml_module, +#endif #ifdef NJS_HAVE_ZLIB &qjs_zlib_module, #endif From noreply at nginx.com Tue Apr 8 05:15:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 8 Apr 2025 05:15:02 +0000 (UTC) Subject: [njs] QuickJS: ignoring rejected promises while destroying context. Message-ID: <20250408051502.5227A478F2@pubserv1.nginx> details: https://github.com/nginx/njs/commit/113fac87c8a123d0627e82cfe3771334baa11edd branches: master commit: 113fac87c8a123d0627e82cfe3771334baa11edd user: Dmitry Volyntsev date: Mon, 7 Apr 2025 18:28:50 -0700 description: QuickJS: ignoring rejected promises while destroying context. --- nginx/ngx_js.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nginx/ngx_js.c b/nginx/ngx_js.c index ba0fee92..316a2076 100644 --- a/nginx/ngx_js.c +++ b/nginx/ngx_js.c @@ -1155,6 +1155,8 @@ ngx_engine_qjs_destroy(ngx_engine_t *e, ngx_js_ctx_t *ctx, "js unhandled rejection: %V", &exception); } + JS_SetHostPromiseRejectionTracker(JS_GetRuntime(cx), NULL, NULL); + class_id = JS_GetClassID(ngx_qjs_arg(ctx->args[0])); opaque = JS_GetOpaque(ngx_qjs_arg(ctx->args[0]), class_id); opaque->external = NULL; From noreply at nginx.com Tue Apr 8 05:15:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 8 Apr 2025 05:15:02 +0000 (UTC) Subject: [njs] Version 0.8.10. Message-ID: <20250408051502.55E1148380@pubserv1.nginx> details: https://github.com/nginx/njs/commit/9d3e71ca656b920e3e63b0e647aca8e91669d29a branches: master commit: 9d3e71ca656b920e3e63b0e647aca8e91669d29a user: Dmitry Volyntsev date: Mon, 7 Apr 2025 18:53:52 -0700 description: Version 0.8.10. --- CHANGES | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/CHANGES b/CHANGES index c67eaf8b..87392f4c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,52 @@ +Changes with njs 0.8.10 08 Apr 2025 + + nginx modules: + + *) Feature: reading r.requestText or r.requestBuffer from + a temp file. + Previously, an exception was thrown when accessing r.requestText + or r.requestBuffer if a client request body size exceeded + client_body_buffer_size. + + *) Improvement: improved reporting of unhandled promise rejections. + + *) Bugfix: fixed name corruption in variable and header processing. + + *) Bugfix: fixed SharedDict.incr() with empty init argument + for QuickJS engine. + + *) Bugfix: accepting response headers with underscore characters + in Fetch API. + + Core: + + *) Change: fixed serializeToString(). + Previously, serializeToString() was exclusiveC14n() which returned + string instead of Buffer. According to the published documentation it + should be c14n(). + + *) Feature: added WebCrypto API for QuickJS engine. + + *) Feature: added TextEncoder/TextDecoder for QuickJS engine. + + *) Feature: added querystring module for QuickJS engine. + + *) Feature: added crypto module for QuickJS engine. + + *) Feature: added xml module for QuickJS engine. + + *) Feature: added support for QuickJS-NG library. + + *) Bugfix: fixed buffer.concat() with a single argument in quickjs. + + *) Bugfix: added missed syntax error for await in template literal. + + *) Bugfix: fixed non-NULL terminated strings formatting in + exceptions for QuickJS engine. + + *) Bugfix: fixed compatibility with recent change in QuickJS + and QuickJS-NG. + Changes with njs 0.8.9 14 Jan 2025 nginx modules: From noreply at nginx.com Tue Apr 8 05:16:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 8 Apr 2025 05:16:02 +0000 (UTC) Subject: [njs] Lightweight tag created: 0.8.10 Message-ID: <20250408051602.196A148380@pubserv1.nginx> details: https://github.com/nginx/njs/releases/tag/0.8.10 branches: commit: 9d3e71ca656b920e3e63b0e647aca8e91669d29a user: Dmitry Volyntsev date: Mon Apr 7 18:53:52 2025 -0700 description: Version 0.8.10. From noreply at nginx.com Wed Apr 9 15:38:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 9 Apr 2025 15:38:02 +0000 (UTC) Subject: [nginx] Charset filter: improved validation of charset_map with utf-8. Message-ID: <20250409153802.A8DD1477D2@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/a813c639211728a1441945dee149b44a0935f48b branches: master commit: a813c639211728a1441945dee149b44a0935f48b user: Sergey Kandaurov date: Thu, 27 Feb 2025 18:42:06 +0400 description: Charset filter: improved validation of charset_map with utf-8. It was possible to write outside of the buffer used to keep UTF-8 decoded values when parsing conversion table configuration. Since this happened before UTF-8 decoding, the fix is to check in advance if character codes are of more than 3-byte sequence. Note that this is already enforced by a later check for ngx_utf8_decode() decoded values for 0xffff, which corresponds to the maximum value encoded as a valid 3-byte sequence, so the fix does not affect the valid values. Found with AddressSanitizer. Fixes GitHub issue #529. --- src/http/modules/ngx_http_charset_filter_module.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c index e52b96e9b..d44da6233 100644 --- a/src/http/modules/ngx_http_charset_filter_module.c +++ b/src/http/modules/ngx_http_charset_filter_module.c @@ -1332,6 +1332,12 @@ ngx_http_charset_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) table = ctx->table; if (ctx->charset->utf8) { + if (value[1].len / 2 > NGX_UTF_LEN - 1) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid value \"%V\"", &value[1]); + return NGX_CONF_ERROR; + } + p = &table->src2dst[src * NGX_UTF_LEN]; *p++ = (u_char) (value[1].len / 2); From noreply at nginx.com Thu Apr 10 01:55:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Thu, 10 Apr 2025 01:55:02 +0000 (UTC) Subject: [njs] Version bump. Message-ID: <20250410015502.CC9D9489DB@pubserv1.nginx> details: https://github.com/nginx/njs/commit/b5d64ed6eeb0323917f83459fae80c59965a8725 branches: master commit: b5d64ed6eeb0323917f83459fae80c59965a8725 user: Dmitry Volyntsev date: Wed, 9 Apr 2025 17:18:53 -0700 description: Version bump. --- src/njs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/njs.h b/src/njs.h index c7e67aca..0e2855d1 100644 --- a/src/njs.h +++ b/src/njs.h @@ -11,8 +11,8 @@ #include -#define NJS_VERSION "0.8.10" -#define NJS_VERSION_NUMBER 0x00080a +#define NJS_VERSION "0.9.0" +#define NJS_VERSION_NUMBER 0x000900 #include From noreply at nginx.com Thu Apr 10 01:55:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Thu, 10 Apr 2025 01:55:02 +0000 (UTC) Subject: [njs] Fixed typo in stream event handler debug message. Message-ID: <20250410015502.D10A1489E2@pubserv1.nginx> details: https://github.com/nginx/njs/commit/0c9c847d3350c5cefbdc8bbc28918768271e4a7d branches: master commit: 0c9c847d3350c5cefbdc8bbc28918768271e4a7d user: Dmitry Volyntsev date: Wed, 9 Apr 2025 17:19:37 -0700 description: Fixed typo in stream event handler debug message. --- nginx/ngx_stream_js_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nginx/ngx_stream_js_module.c b/nginx/ngx_stream_js_module.c index 44c7af17..7620f2e0 100644 --- a/nginx/ngx_stream_js_module.c +++ b/nginx/ngx_stream_js_module.c @@ -1914,7 +1914,7 @@ static void ngx_stream_js_event_finalize(ngx_stream_session_t *s, ngx_int_t rc) { ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, - "http js event finalize rc: %i", rc); + "stream js event finalize rc: %i", rc); if (rc == NGX_ERROR) { if (s->health_check) { From noreply at nginx.com Thu Apr 10 02:16:01 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Thu, 10 Apr 2025 02:16:01 +0000 (UTC) Subject: [njs] Fetch: remove unused parameter in ngx_js_http_error(). Message-ID: <20250410021601.E330E489E2@pubserv1.nginx> details: https://github.com/nginx/njs/commit/4f96013f83ec3e84314d2dfcf2f81d47897fa6e4 branches: master commit: 4f96013f83ec3e84314d2dfcf2f81d47897fa6e4 user: Zhidao HONG date: Tue, 8 Apr 2025 23:00:42 +0800 description: Fetch: remove unused parameter in ngx_js_http_error(). No functional changes. --- nginx/ngx_js_fetch.c | 58 ++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index cd6e54f6..a803ab4c 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -158,7 +158,7 @@ struct ngx_js_http_s { -#define ngx_js_http_error(http, err, fmt, ...) \ +#define ngx_js_http_error(http, fmt, ...) \ do { \ njs_vm_error((http)->vm, fmt, ##__VA_ARGS__); \ njs_vm_exception_get((http)->vm, \ @@ -1343,7 +1343,7 @@ ngx_js_resolve_handler(ngx_resolver_ctx_t *ctx) http = ctx->data; if (ctx->state) { - ngx_js_http_error(http, 0, "\"%V\" could not be resolved (%i: %s)", + ngx_js_http_error(http, "\"%V\" could not be resolved (%i: %s)", &ctx->name, ctx->state, ngx_resolver_strerror(ctx->state)); return; @@ -1410,7 +1410,7 @@ ngx_js_resolve_handler(ngx_resolver_ctx_t *ctx) failed: - ngx_js_http_error(http, 0, "memory error"); + ngx_js_http_error(http, "memory error"); } @@ -1577,7 +1577,7 @@ ngx_js_http_connect(ngx_js_http_t *http) rc = ngx_event_connect_peer(&http->peer); if (rc == NGX_ERROR) { - ngx_js_http_error(http, 0, "connect failed"); + ngx_js_http_error(http, "connect failed"); return; } @@ -1627,14 +1627,14 @@ ngx_js_http_ssl_init_connection(ngx_js_http_t *http) if (ngx_ssl_create_connection(http->ssl, c, NGX_SSL_BUFFER|NGX_SSL_CLIENT) != NGX_OK) { - ngx_js_http_error(http, 0, "failed to create ssl connection"); + ngx_js_http_error(http, "failed to create ssl connection"); return; } c->sendfile = 0; if (ngx_js_http_ssl_name(http) != NGX_OK) { - ngx_js_http_error(http, 0, "failed to create ssl connection"); + ngx_js_http_error(http, "failed to create ssl connection"); return; } @@ -1770,7 +1770,7 @@ ngx_js_http_next(ngx_js_http_t *http) ngx_log_debug0(NGX_LOG_DEBUG_EVENT, http->log, 0, "js fetch next addr"); if (++http->naddr >= http->naddrs) { - ngx_js_http_error(http, 0, "connect failed"); + ngx_js_http_error(http, "connect failed"); return; } @@ -1799,7 +1799,7 @@ ngx_js_http_write_handler(ngx_event_t *wev) ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0, "js fetch write handler"); if (wev->timedout) { - ngx_js_http_error(http, NGX_ETIMEDOUT, "write timed out"); + ngx_js_http_error(http, "write timed out"); return; } @@ -1815,13 +1815,13 @@ ngx_js_http_write_handler(ngx_event_t *wev) if (b == NULL) { size = njs_chb_size(&http->chain); if (size < 0) { - ngx_js_http_error(http, 0, "memory error"); + ngx_js_http_error(http, "memory error"); return; } b = ngx_create_temp_buf(http->pool, size); if (b == NULL) { - ngx_js_http_error(http, 0, "memory error"); + ngx_js_http_error(http, "memory error"); return; } @@ -1853,7 +1853,7 @@ ngx_js_http_write_handler(ngx_event_t *wev) } if (ngx_handle_write_event(wev, 0) != NGX_OK) { - ngx_js_http_error(http, 0, "write failed"); + ngx_js_http_error(http, "write failed"); } return; @@ -1881,14 +1881,14 @@ ngx_js_http_read_handler(ngx_event_t *rev) ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0, "js fetch read handler"); if (rev->timedout) { - ngx_js_http_error(http, NGX_ETIMEDOUT, "read timed out"); + ngx_js_http_error(http, "read timed out"); return; } if (http->buffer == NULL) { b = ngx_create_temp_buf(http->pool, http->buffer_size); if (b == NULL) { - ngx_js_http_error(http, 0, "memory error"); + ngx_js_http_error(http, "memory error"); return; } @@ -1915,7 +1915,7 @@ ngx_js_http_read_handler(ngx_event_t *rev) if (n == NGX_AGAIN) { if (ngx_handle_read_event(rev, 0) != NGX_OK) { - ngx_js_http_error(http, 0, "read failed"); + ngx_js_http_error(http, "read failed"); } return; @@ -1939,7 +1939,7 @@ ngx_js_http_read_handler(ngx_event_t *rev) } if (rc == NGX_AGAIN) { - ngx_js_http_error(http, 0, "prematurely closed connection"); + ngx_js_http_error(http, "prematurely closed connection"); } } @@ -2374,7 +2374,7 @@ ngx_js_http_process_status_line(ngx_js_http_t *http) /* rc == NGX_ERROR */ - ngx_js_http_error(http, 0, "invalid fetch status line"); + ngx_js_http_error(http, "invalid fetch status line"); return NGX_ERROR; } @@ -2397,7 +2397,7 @@ ngx_js_http_process_headers(ngx_js_http_t *http) rc = ngx_list_init(&http->response.headers.header_list, http->pool, 4, sizeof(ngx_js_tb_elt_t)); if (rc != NGX_OK) { - ngx_js_http_error(http, 0, "alloc failed"); + ngx_js_http_error(http, "alloc failed"); return NGX_ERROR; } } @@ -2414,7 +2414,7 @@ ngx_js_http_process_headers(ngx_js_http_t *http) hp->header_start, vlen); if (ret == NJS_ERROR) { - ngx_js_http_error(http, 0, "cannot add respose header"); + ngx_js_http_error(http, "cannot add respose header"); return NGX_ERROR; } @@ -2438,7 +2438,7 @@ ngx_js_http_process_headers(ngx_js_http_t *http) { hp->content_length_n = ngx_atoof(hp->header_start, vlen); if (hp->content_length_n == NGX_ERROR) { - ngx_js_http_error(http, 0, "invalid fetch content length"); + ngx_js_http_error(http, "invalid fetch content length"); return NGX_ERROR; } @@ -2446,7 +2446,7 @@ ngx_js_http_process_headers(ngx_js_http_t *http) && hp->content_length_n > (off_t) http->max_response_body_size) { - ngx_js_http_error(http, 0, + ngx_js_http_error(http, "fetch content length is too large"); return NGX_ERROR; } @@ -2466,7 +2466,7 @@ ngx_js_http_process_headers(ngx_js_http_t *http) /* rc == NGX_ERROR */ - ngx_js_http_error(http, 0, "invalid fetch header"); + ngx_js_http_error(http, "invalid fetch header"); return NGX_ERROR; } @@ -2495,7 +2495,7 @@ ngx_js_http_process_body(ngx_js_http_t *http) if (http->done) { size = njs_chb_size(&http->response.chain); if (size < 0) { - ngx_js_http_error(http, 0, "memory error"); + ngx_js_http_error(http, "memory error"); return NGX_ERROR; } @@ -2503,7 +2503,7 @@ ngx_js_http_process_body(ngx_js_http_t *http) && http->http_parse.chunked && http->http_parse.content_length_n == -1) { - ngx_js_http_error(http, 0, "invalid fetch chunked response"); + ngx_js_http_error(http, "invalid fetch chunked response"); return NGX_ERROR; } @@ -2516,7 +2516,7 @@ ngx_js_http_process_body(ngx_js_http_t *http) ngx_http_js_fetch_response_proto_id, &http->response, 0); if (ret != NJS_OK) { - ngx_js_http_error(http, 0, "fetch response creation failed"); + ngx_js_http_error(http, "fetch response creation failed"); return NGX_ERROR; } @@ -2528,7 +2528,7 @@ ngx_js_http_process_body(ngx_js_http_t *http) return NGX_AGAIN; } - ngx_js_http_error(http, 0, "fetch trailing data"); + ngx_js_http_error(http, "fetch trailing data"); return NGX_ERROR; } @@ -2538,7 +2538,7 @@ ngx_js_http_process_body(ngx_js_http_t *http) rc = ngx_js_http_parse_chunked(&http->http_chunk_parse, b, &http->response.chain); if (rc == NGX_ERROR) { - ngx_js_http_error(http, 0, "invalid fetch chunked response"); + ngx_js_http_error(http, "invalid fetch chunked response"); return NGX_ERROR; } @@ -2549,7 +2549,7 @@ ngx_js_http_process_body(ngx_js_http_t *http) } if (size > http->max_response_body_size * 10) { - ngx_js_http_error(http, 0, "very large fetch chunked response"); + ngx_js_http_error(http, "very large fetch chunked response"); return NGX_ERROR; } @@ -2571,7 +2571,7 @@ ngx_js_http_process_body(ngx_js_http_t *http) chsize = ngx_min(need, b->last - b->pos); if (size + chsize > http->max_response_body_size) { - ngx_js_http_error(http, 0, "fetch response body is too large"); + ngx_js_http_error(http, "fetch response body is too large"); return NGX_ERROR; } @@ -2587,7 +2587,7 @@ ngx_js_http_process_body(ngx_js_http_t *http) if (http->chunk == NULL) { b = ngx_create_temp_buf(http->pool, http->buffer_size); if (b == NULL) { - ngx_js_http_error(http, 0, "memory error"); + ngx_js_http_error(http, "memory error"); return NGX_ERROR; } From noreply at nginx.com Thu Apr 10 13:28:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Thu, 10 Apr 2025 13:28:02 +0000 (UTC) Subject: [nginx] Upstream: fixed passwords support for dynamic certificates. Message-ID: <20250410132802.926D8489C7@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/6c3a9d561271ec451f479a84fbe54c81a63dad2e branches: master commit: 6c3a9d561271ec451f479a84fbe54c81a63dad2e user: Sergey Kandaurov date: Wed, 5 Feb 2025 19:16:05 +0400 description: Upstream: fixed passwords support for dynamic certificates. Passwords were not preserved in optimized SSL contexts, the bug had appeared in d791b4aab (1.23.1), as in the following configuration: server { proxy_ssl_password_file password; proxy_ssl_certificate $ssl_server_name.crt; proxy_ssl_certificate_key $ssl_server_name.key; location /original/ { proxy_pass https://u1/; } location /optimized/ { proxy_pass https://u2/; } } The fix is to always preserve passwords, by copying to the configuration pool, if dynamic certificates are used. This is done as part of merging "ssl_passwords" configuration. To minimize the number of copies, a preserved version is then used for inheritance. A notable exception is inheritance of preserved empty passwords to the context with statically configured certificates: server { proxy_ssl_certificate $ssl_server_name.crt; proxy_ssl_certificate_key $ssl_server_name.key; location / { proxy_pass ...; proxy_ssl_certificate example.com.crt; proxy_ssl_certificate_key example.com.key; } } In this case, an unmodified version (NULL) of empty passwords is set, to allow reading them from the password prompt on nginx startup. As an additional optimization, a preserved instance of inherited configured passwords is set to the previous level, to inherit it to other contexts: server { proxy_ssl_password_file password; location /1/ { proxy_pass https://u1/; proxy_ssl_certificate $ssl_server_name.crt; proxy_ssl_certificate_key $ssl_server_name.key; } location /2/ { proxy_pass https://u2/; proxy_ssl_certificate $ssl_server_name.crt; proxy_ssl_certificate_key $ssl_server_name.key; } } --- src/http/modules/ngx_http_grpc_module.c | 20 +++++----- src/http/modules/ngx_http_proxy_module.c | 20 +++++----- src/http/modules/ngx_http_uwsgi_module.c | 20 +++++----- src/http/ngx_http_upstream.c | 55 ++++++++++++++++++++++++++ src/http/ngx_http_upstream.h | 4 ++ src/stream/ngx_stream_proxy_module.c | 68 +++++++++++++++++++++++++++----- 6 files changed, 144 insertions(+), 43 deletions(-) diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c index 8e246c3cf..80046d6a4 100644 --- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -4509,8 +4509,13 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) prev->upstream.ssl_certificate_key, NULL); ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_cache, prev->upstream.ssl_certificate_cache, NULL); - ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, - prev->upstream.ssl_passwords, NULL); + + if (ngx_http_upstream_merge_ssl_passwords(cf, &conf->upstream, + &prev->upstream) + != NGX_OK) + { + return NGX_CONF_ERROR; + } ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -5077,16 +5082,9 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf) return NGX_ERROR; } - if (glcf->upstream.ssl_certificate->lengths - || glcf->upstream.ssl_certificate_key->lengths) + if (glcf->upstream.ssl_certificate->lengths == NULL + && glcf->upstream.ssl_certificate_key->lengths == NULL) { - glcf->upstream.ssl_passwords = - ngx_ssl_preserve_passwords(cf, glcf->upstream.ssl_passwords); - if (glcf->upstream.ssl_passwords == NULL) { - return NGX_ERROR; - } - - } else { if (ngx_ssl_certificate(cf, glcf->upstream.ssl, &glcf->upstream.ssl_certificate->value, &glcf->upstream.ssl_certificate_key->value, diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index 27c34fef2..d4c5abf62 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -3976,8 +3976,13 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) prev->upstream.ssl_certificate_key, NULL); ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_cache, prev->upstream.ssl_certificate_cache, NULL); - ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, - prev->upstream.ssl_passwords, NULL); + + if (ngx_http_upstream_merge_ssl_passwords(cf, &conf->upstream, + &prev->upstream) + != NGX_OK) + { + return NGX_CONF_ERROR; + } ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -5337,16 +5342,9 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf) return NGX_ERROR; } - if (plcf->upstream.ssl_certificate->lengths - || plcf->upstream.ssl_certificate_key->lengths) + if (plcf->upstream.ssl_certificate->lengths == NULL + && plcf->upstream.ssl_certificate_key->lengths == NULL) { - plcf->upstream.ssl_passwords = - ngx_ssl_preserve_passwords(cf, plcf->upstream.ssl_passwords); - if (plcf->upstream.ssl_passwords == NULL) { - return NGX_ERROR; - } - - } else { if (ngx_ssl_certificate(cf, plcf->upstream.ssl, &plcf->upstream.ssl_certificate->value, &plcf->upstream.ssl_certificate_key->value, diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c index 14aae5bf1..51a861d9a 100644 --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -1933,8 +1933,13 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) prev->upstream.ssl_certificate_key, NULL); ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_cache, prev->upstream.ssl_certificate_cache, NULL); - ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, - prev->upstream.ssl_passwords, NULL); + + if (ngx_http_upstream_merge_ssl_passwords(cf, &conf->upstream, + &prev->upstream) + != NGX_OK) + { + return NGX_CONF_ERROR; + } ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -2685,16 +2690,9 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf) return NGX_ERROR; } - if (uwcf->upstream.ssl_certificate->lengths - || uwcf->upstream.ssl_certificate_key->lengths) + if (uwcf->upstream.ssl_certificate->lengths == NULL + && uwcf->upstream.ssl_certificate_key->lengths == NULL) { - uwcf->upstream.ssl_passwords = - ngx_ssl_preserve_passwords(cf, uwcf->upstream.ssl_passwords); - if (uwcf->upstream.ssl_passwords == NULL) { - return NGX_ERROR; - } - - } else { if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, &uwcf->upstream.ssl_certificate->value, &uwcf->upstream.ssl_certificate_key->value, diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 77dc032f2..d4cf1b7fe 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -6921,6 +6921,61 @@ ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf, } +#if (NGX_HTTP_SSL) + +ngx_int_t +ngx_http_upstream_merge_ssl_passwords(ngx_conf_t *cf, + ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev) +{ + ngx_uint_t preserve; + + ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + + if (conf->ssl_certificate == NULL + || conf->ssl_certificate->value.len == 0 + || conf->ssl_certificate_key == NULL) + { + return NGX_OK; + } + + if (conf->ssl_certificate->lengths == NULL + && conf->ssl_certificate_key->lengths == NULL) + { + if (conf->ssl_passwords && conf->ssl_passwords->pool == NULL) { + /* un-preserve empty password list */ + conf->ssl_passwords = NULL; + } + + return NGX_OK; + } + + if (conf->ssl_passwords && conf->ssl_passwords->pool != cf->temp_pool) { + /* already preserved */ + return NGX_OK; + } + + preserve = (conf->ssl_passwords == prev->ssl_passwords) ? 1 : 0; + + conf->ssl_passwords = ngx_ssl_preserve_passwords(cf, conf->ssl_passwords); + if (conf->ssl_passwords == NULL) { + return NGX_ERROR; + } + + /* + * special handling to keep a preserved ssl_passwords copy + * in the previous configuration to inherit it to all children + */ + + if (preserve) { + prev->ssl_passwords = conf->ssl_passwords; + } + + return NGX_OK; +} + +#endif + + static void * ngx_http_upstream_create_main_conf(ngx_conf_t *cf) { diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 069c0f7a4..e0a903669 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -437,6 +437,10 @@ char *ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, ngx_int_t ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf, ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev, ngx_str_t *default_hide_headers, ngx_hash_init_t *hash); +#if (NGX_HTTP_SSL) +ngx_int_t ngx_http_upstream_merge_ssl_passwords(ngx_conf_t *cf, + ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev); +#endif #define ngx_http_conf_upstream_srv_conf(uscf, module) \ diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c index 7f8bfc4e0..6e51585f6 100644 --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -108,6 +108,8 @@ static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s); static ngx_int_t ngx_stream_proxy_ssl_certificate(ngx_stream_session_t *s); static ngx_int_t ngx_stream_proxy_merge_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *conf, ngx_stream_proxy_srv_conf_t *prev); +static ngx_int_t ngx_stream_proxy_merge_ssl_passwords(ngx_conf_t *cf, + ngx_stream_proxy_srv_conf_t *conf, ngx_stream_proxy_srv_conf_t *prev); static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf); @@ -2315,7 +2317,9 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_ptr_value(conf->ssl_certificate_cache, prev->ssl_certificate_cache, NULL); - ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + if (ngx_stream_proxy_merge_ssl_passwords(cf, conf, prev) != NGX_OK) { + return NGX_CONF_ERROR; + } ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -2381,6 +2385,57 @@ ngx_stream_proxy_merge_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *conf, } +static ngx_int_t +ngx_stream_proxy_merge_ssl_passwords(ngx_conf_t *cf, + ngx_stream_proxy_srv_conf_t *conf, ngx_stream_proxy_srv_conf_t *prev) +{ + ngx_uint_t preserve; + + ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + + if (conf->ssl_certificate == NULL + || conf->ssl_certificate->value.len == 0 + || conf->ssl_certificate_key == NULL) + { + return NGX_OK; + } + + if (conf->ssl_certificate->lengths == NULL + && conf->ssl_certificate_key->lengths == NULL) + { + if (conf->ssl_passwords && conf->ssl_passwords->pool == NULL) { + /* un-preserve empty password list */ + conf->ssl_passwords = NULL; + } + + return NGX_OK; + } + + if (conf->ssl_passwords && conf->ssl_passwords->pool != cf->temp_pool) { + /* already preserved */ + return NGX_OK; + } + + preserve = (conf->ssl_passwords == prev->ssl_passwords) ? 1 : 0; + + conf->ssl_passwords = ngx_ssl_preserve_passwords(cf, conf->ssl_passwords); + if (conf->ssl_passwords == NULL) { + return NGX_ERROR; + } + + /* + * special handling to keep a preserved ssl_passwords copy + * in the previous configuration to inherit it to all children + */ + + if (preserve) { + prev->ssl_passwords = conf->ssl_passwords; + } + + return NGX_OK; +} + + static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf) { @@ -2418,16 +2473,9 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf) return NGX_ERROR; } - if (pscf->ssl_certificate->lengths - || pscf->ssl_certificate_key->lengths) + if (pscf->ssl_certificate->lengths == NULL + && pscf->ssl_certificate_key->lengths == NULL) { - pscf->ssl_passwords = - ngx_ssl_preserve_passwords(cf, pscf->ssl_passwords); - if (pscf->ssl_passwords == NULL) { - return NGX_ERROR; - } - - } else { if (ngx_ssl_certificate(cf, pscf->ssl, &pscf->ssl_certificate->value, &pscf->ssl_certificate_key->value, From noreply at nginx.com Thu Apr 10 14:52:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Thu, 10 Apr 2025 14:52:02 +0000 (UTC) Subject: [nginx] SSL: external groups support in $ssl_curve and $ssl_curves. Message-ID: <20250410145202.3FDE7489E2@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/b6e7eb0f5792d7a52d2675ee3906e502d63c48e3 branches: master commit: b6e7eb0f5792d7a52d2675ee3906e502d63c48e3 user: Sergey Kandaurov date: Thu, 3 Apr 2025 15:29:31 +0400 description: SSL: external groups support in $ssl_curve and $ssl_curves. Starting with OpenSSL 3.0, groups may be added externally with pluggable KEM providers. Using SSL_get_negotiated_group(), which makes lookup in a static table with known groups, doesn't allow to list such groups by names leaving them in hex. Adding X25519MLKEM768 to the default group list in OpenSSL 3.5 made this problem more visible. SSL_get0_group_name() and, apparently, SSL_group_to_name() allow to resolve such provider-implemented groups, which is also "generally preferred" over SSL_get_negotiated_group() as documented in OpenSSL git commit 93d4f6133f. This change makes external groups listing by name using SSL_group_to_name() available since OpenSSL 3.0. To preserve "prime256v1" naming for the group 0x0017, and to avoid breaking BoringSSL and older OpenSSL versions support, it is used supplementary for a group that appears to be unknown. See https://github.com/openssl/openssl/issues/27137 for related discussion. --- src/event/ngx_event_openssl.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 865c78540..6992cc4a4 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -5040,7 +5040,8 @@ ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { #ifdef SSL_get_negotiated_group - int nid; + int nid; + const char *name; nid = SSL_get_negotiated_group(c->ssl->connection); @@ -5052,14 +5053,24 @@ ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) return NGX_OK; } - s->len = sizeof("0x0000") - 1; +#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL) + name = SSL_group_to_name(c->ssl->connection, nid); +#else + name = NULL; +#endif + s->len = name ? ngx_strlen(name) : sizeof("0x0000") - 1; s->data = ngx_pnalloc(pool, s->len); if (s->data == NULL) { return NGX_ERROR; } - ngx_sprintf(s->data, "0x%04xd", nid & 0xffff); + if (name) { + ngx_memcpy(s->data, name, s->len); + + } else { + ngx_sprintf(s->data, "0x%04xd", nid & 0xffff); + } return NGX_OK; } @@ -5079,6 +5090,7 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) int *curves, n, i, nid; u_char *p; size_t len; + const char *name; n = SSL_get1_curves(c->ssl->connection, NULL); @@ -5099,7 +5111,13 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) nid = curves[i]; if (nid & TLSEXT_nid_unknown) { - len += sizeof("0x0000") - 1; +#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL) + name = SSL_group_to_name(c->ssl->connection, nid); +#else + name = NULL; +#endif + + len += name ? ngx_strlen(name) : sizeof("0x0000") - 1; } else { len += ngx_strlen(OBJ_nid2sn(nid)); @@ -5119,7 +5137,14 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) nid = curves[i]; if (nid & TLSEXT_nid_unknown) { - p = ngx_sprintf(p, "0x%04xd", nid & 0xffff); +#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL) + name = SSL_group_to_name(c->ssl->connection, nid); +#else + name = NULL; +#endif + + p = name ? ngx_cpymem(p, name, ngx_strlen(name)) + : ngx_sprintf(p, "0x%04xd", nid & 0xffff); } else { p = ngx_sprintf(p, "%s", OBJ_nid2sn(nid)); From noreply at nginx.com Fri Apr 11 15:29:01 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Fri, 11 Apr 2025 15:29:01 +0000 (UTC) Subject: [njs] Fetch: generalize ngx_js_http_error(). Message-ID: <20250411152901.F3BA948F29@pubserv1.nginx> details: https://github.com/nginx/njs/commit/48070f44bd9d44dfd92a8f7873c38bf252d53b45 branches: master commit: 48070f44bd9d44dfd92a8f7873c38bf252d53b45 user: Zhidao HONG date: Fri, 11 Apr 2025 21:47:52 +0800 description: Fetch: generalize ngx_js_http_error(). Refactored to support both njs and QuickJS, which have different error formats when throwing exceptions. --- nginx/ngx_js_fetch.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index a803ab4c..2db73904 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -156,17 +156,6 @@ struct ngx_js_http_s { }; - - -#define ngx_js_http_error(http, fmt, ...) \ - do { \ - njs_vm_error((http)->vm, fmt, ##__VA_ARGS__); \ - njs_vm_exception_get((http)->vm, \ - njs_value_arg(&(http)->response_value)); \ - ngx_js_http_fetch_done(http, &(http)->response_value, NJS_ERROR); \ - } while (0) - - static njs_int_t ngx_js_method_process(njs_vm_t *vm, ngx_js_request_t *r); static njs_int_t ngx_js_headers_inherit(njs_vm_t *vm, ngx_js_headers_t *headers, ngx_js_headers_t *orig); @@ -1330,6 +1319,26 @@ failed: } +static void +ngx_js_http_error(ngx_js_http_t *http, const char *fmt, ...) +{ + u_char *p, *end; + va_list args; + u_char err[NGX_MAX_ERROR_STR]; + + end = err + NGX_MAX_ERROR_STR - 1; + + va_start(args, fmt); + p = njs_vsprintf(err, end, fmt, args); + *p = '\0'; + va_end(args); + + njs_vm_error(http->vm, (const char *) err); + njs_vm_exception_get(http->vm, njs_value_arg(&http->response_value)); + ngx_js_http_fetch_done(http, &http->response_value, NJS_ERROR); +} + + static void ngx_js_resolve_handler(ngx_resolver_ctx_t *ctx) { From noreply at nginx.com Fri Apr 11 15:29:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Fri, 11 Apr 2025 15:29:02 +0000 (UTC) Subject: [njs] Fetch: renamed njs_js_http_destructor() as ngx_js_http_destructor(). Message-ID: <20250411152902.040A248F2A@pubserv1.nginx> details: https://github.com/nginx/njs/commit/3aa2ed4b4dad5867920e2b8a6da28840c44e67eb branches: master commit: 3aa2ed4b4dad5867920e2b8a6da28840c44e67eb user: Zhidao HONG date: Fri, 11 Apr 2025 21:57:02 +0800 description: Fetch: renamed njs_js_http_destructor() as ngx_js_http_destructor(). --- nginx/ngx_js_fetch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index 2db73904..5abd43bd 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -163,7 +163,7 @@ static njs_int_t ngx_js_headers_fill(njs_vm_t *vm, ngx_js_headers_t *headers, njs_value_t *init); static ngx_js_http_t *ngx_js_http_alloc(njs_vm_t *vm, ngx_pool_t *pool, ngx_log_t *log); -static void njs_js_http_destructor(ngx_js_event_t *event); +static void ngx_js_http_destructor(ngx_js_event_t *event); static void ngx_js_resolve_handler(ngx_resolver_ctx_t *ctx); static njs_int_t ngx_js_fetch_promissified_result(njs_vm_t *vm, njs_value_t *result, njs_int_t rc, njs_value_t *retval); @@ -1299,7 +1299,7 @@ ngx_js_http_alloc(njs_vm_t *vm, ngx_pool_t *pool, ngx_log_t *log) event->ctx = vm; njs_value_function_set(njs_value_arg(&event->function), callback); - event->destructor = njs_js_http_destructor; + event->destructor = ngx_js_http_destructor; event->fd = ctx->event_id++; event->data = http; @@ -1447,7 +1447,7 @@ ngx_js_http_close_connection(ngx_connection_t *c) static void -njs_js_http_destructor(ngx_js_event_t *event) +ngx_js_http_destructor(ngx_js_event_t *event) { ngx_js_http_t *http; From noreply at nginx.com Fri Apr 11 15:29:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Fri, 11 Apr 2025 15:29:02 +0000 (UTC) Subject: [njs] Fetch: refactored out ngx_js_http_close_peer(). Message-ID: <20250411152902.0F62C48F36@pubserv1.nginx> details: https://github.com/nginx/njs/commit/78b55af1e689eac4c87961a65592a094845ed482 branches: master commit: 78b55af1e689eac4c87961a65592a094845ed482 user: Zhidao HONG date: Fri, 11 Apr 2025 22:02:16 +0800 description: Fetch: refactored out ngx_js_http_close_peer(). --- nginx/ngx_js_fetch.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index d3f8b356..944ed28e 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -164,6 +164,7 @@ static njs_int_t ngx_js_headers_fill(njs_vm_t *vm, ngx_js_headers_t *headers, static ngx_js_http_t *ngx_js_http_alloc(njs_vm_t *vm, ngx_pool_t *pool, ngx_log_t *log); static void ngx_js_http_resolve_done(ngx_js_http_t *http); +static void ngx_js_http_close_peer(ngx_js_http_t *http); static void ngx_js_http_destructor(ngx_js_event_t *event); static void ngx_js_resolve_handler(ngx_resolver_ctx_t *ctx); static njs_int_t ngx_js_fetch_promissified_result(njs_vm_t *vm, @@ -1456,6 +1457,16 @@ ngx_js_http_resolve_done(ngx_js_http_t *http) } +static void +ngx_js_http_close_peer(ngx_js_http_t *http) +{ + if (http->peer.connection != NULL) { + ngx_js_http_close_connection(http->peer.connection); + http->peer.connection = NULL; + } +} + + static void ngx_js_http_destructor(ngx_js_event_t *event) { @@ -1467,11 +1478,7 @@ ngx_js_http_destructor(ngx_js_event_t *event) http); ngx_js_http_resolve_done(http); - - if (http->peer.connection != NULL) { - ngx_js_http_close_connection(http->peer.connection); - http->peer.connection = NULL; - } + ngx_js_http_close_peer(http); } @@ -1532,10 +1539,7 @@ ngx_js_http_fetch_done(ngx_js_http_t *http, njs_opaque_value_t *retval, ngx_log_debug2(NGX_LOG_DEBUG_EVENT, http->log, 0, "js fetch done http:%p rc:%i", http, (ngx_int_t) rc); - if (http->peer.connection != NULL) { - ngx_js_http_close_connection(http->peer.connection); - http->peer.connection = NULL; - } + ngx_js_http_close_peer(http); if (http->event != NULL) { action = &http->promise_callbacks[(rc != NJS_OK)]; From noreply at nginx.com Fri Apr 11 15:29:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Fri, 11 Apr 2025 15:29:02 +0000 (UTC) Subject: [njs] Fetch: refactored out ngx_js_http_resolve_done(). Message-ID: <20250411152902.09EDE48F35@pubserv1.nginx> details: https://github.com/nginx/njs/commit/befd1d603a9c898657702439644fd8f609610804 branches: master commit: befd1d603a9c898657702439644fd8f609610804 user: Zhidao HONG date: Fri, 11 Apr 2025 21:59:16 +0800 description: Fetch: refactored out ngx_js_http_resolve_done(). --- nginx/ngx_js_fetch.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index 5abd43bd..d3f8b356 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -163,6 +163,7 @@ static njs_int_t ngx_js_headers_fill(njs_vm_t *vm, ngx_js_headers_t *headers, njs_value_t *init); static ngx_js_http_t *ngx_js_http_alloc(njs_vm_t *vm, ngx_pool_t *pool, ngx_log_t *log); +static void ngx_js_http_resolve_done(ngx_js_http_t *http); static void ngx_js_http_destructor(ngx_js_event_t *event); static void ngx_js_resolve_handler(ngx_resolver_ctx_t *ctx); static njs_int_t ngx_js_fetch_promissified_result(njs_vm_t *vm, @@ -1410,8 +1411,7 @@ ngx_js_resolve_handler(ngx_resolver_ctx_t *ctx) http->addrs[i].name.data = p; } - ngx_resolve_name_done(ctx); - http->ctx = NULL; + ngx_js_http_resolve_done(http); ngx_js_http_connect(http); @@ -1446,6 +1446,16 @@ ngx_js_http_close_connection(ngx_connection_t *c) } +static void +ngx_js_http_resolve_done(ngx_js_http_t *http) +{ + if (http->ctx != NULL) { + ngx_resolve_name_done(http->ctx); + http->ctx = NULL; + } +} + + static void ngx_js_http_destructor(ngx_js_event_t *event) { @@ -1456,10 +1466,7 @@ ngx_js_http_destructor(ngx_js_event_t *event) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, http->log, 0, "js fetch destructor:%p", http); - if (http->ctx != NULL) { - ngx_resolve_name_done(http->ctx); - http->ctx = NULL; - } + ngx_js_http_resolve_done(http); if (http->peer.connection != NULL) { ngx_js_http_close_connection(http->peer.connection); From noreply at nginx.com Fri Apr 11 15:29:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Fri, 11 Apr 2025 15:29:02 +0000 (UTC) Subject: [njs] Fetch: refactored out ngx_js_http_resolve(). Message-ID: <20250411152902.14FDB48F38@pubserv1.nginx> details: https://github.com/nginx/njs/commit/dbf556f235af1f42a7d9e3b90682de090170cd0f branches: master commit: dbf556f235af1f42a7d9e3b90682de090170cd0f user: Zhidao HONG date: Fri, 11 Apr 2025 22:43:31 +0800 description: Fetch: refactored out ngx_js_http_resolve(). --- nginx/ngx_js_fetch.c | 59 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index 944ed28e..9539a687 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -166,7 +166,9 @@ static ngx_js_http_t *ngx_js_http_alloc(njs_vm_t *vm, ngx_pool_t *pool, static void ngx_js_http_resolve_done(ngx_js_http_t *http); static void ngx_js_http_close_peer(ngx_js_http_t *http); static void ngx_js_http_destructor(ngx_js_event_t *event); -static void ngx_js_resolve_handler(ngx_resolver_ctx_t *ctx); +static ngx_resolver_ctx_t *ngx_js_http_resolve(ngx_js_http_t *http, + ngx_resolver_t *r, ngx_str_t *host, in_port_t port, ngx_msec_t timeout); +static void ngx_js_http_resolve_handler(ngx_resolver_ctx_t *ctx); static njs_int_t ngx_js_fetch_promissified_result(njs_vm_t *vm, njs_value_t *result, njs_int_t rc, njs_value_t *retval); static void ngx_js_http_fetch_done(ngx_js_http_t *http, @@ -832,7 +834,9 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (u.addrs == NULL) { - ctx = ngx_resolve_start(ngx_external_resolver(vm, external), NULL); + ctx = ngx_js_http_resolve(http, ngx_external_resolver(vm, external), + &u.host, u.port, + ngx_external_resolver_timeout(vm, external)); if (ctx == NULL) { njs_vm_memory_error(vm); return NJS_ERROR; @@ -843,21 +847,6 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto fail; } - http->ctx = ctx; - http->port = u.port; - - ctx->name = u.host; - ctx->handler = ngx_js_resolve_handler; - ctx->data = http; - ctx->timeout = ngx_external_resolver_timeout(vm, external); - - ret = ngx_resolve_name(http->ctx); - if (ret != NGX_OK) { - http->ctx = NULL; - njs_vm_memory_error(vm); - return NJS_ERROR; - } - njs_value_assign(retval, njs_value_arg(&http->promise)); return NJS_OK; @@ -1341,8 +1330,42 @@ ngx_js_http_error(ngx_js_http_t *http, const char *fmt, ...) } +static ngx_resolver_ctx_t * +ngx_js_http_resolve(ngx_js_http_t *http, ngx_resolver_t *r, ngx_str_t *host, + in_port_t port, ngx_msec_t timeout) +{ + ngx_int_t ret; + ngx_resolver_ctx_t *ctx; + + ctx = ngx_resolve_start(r, NULL); + if (ctx == NULL) { + return NULL; + } + + if (ctx == NGX_NO_RESOLVER) { + return ctx; + } + + http->ctx = ctx; + http->port = port; + + ctx->name = *host; + ctx->handler = ngx_js_http_resolve_handler; + ctx->data = http; + ctx->timeout = timeout; + + ret = ngx_resolve_name(ctx); + if (ret != NGX_OK) { + http->ctx = NULL; + return NULL; + } + + return ctx; +} + + static void -ngx_js_resolve_handler(ngx_resolver_ctx_t *ctx) +ngx_js_http_resolve_handler(ngx_resolver_ctx_t *ctx) { u_char *p; size_t len; From noreply at nginx.com Tue Apr 15 15:02:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 15 Apr 2025 15:02:02 +0000 (UTC) Subject: [nginx] QUIC: prevent spurious congestion control recovery mode. Message-ID: <20250415150202.DCD5048F63@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/38236bf74f3e5728eeea488bef381c61842ac1d2 branches: master commit: 38236bf74f3e5728eeea488bef381c61842ac1d2 user: Roman Arutyunyan date: Fri, 3 Jan 2025 13:01:06 +0400 description: QUIC: prevent spurious congestion control recovery mode. Since recovery_start field was initialized with ngx_current_msec, all congestion events that happened within the same millisecond or cycle iteration, were treated as in recovery mode. Also, when handling persistent congestion, initializing recovery_start with ngx_current_msec resulted in treating all sent packets as in recovery mode, which violates RFC 9002, see example in Appendix B.8. While here, also fixed recovery_start wrap protection. Previously it used 2 * max_idle_timeout time frame for all sent frames, which is not a reliable protection since max_idle_timeout is unrelated to congestion control. Now recovery_start <= now condition is enforced. Note that recovery_start wrap is highly unlikely and can only occur on a 32-bit system if there are no congestion events for 24 days. --- src/event/quic/ngx_event_quic.c | 2 +- src/event/quic/ngx_event_quic_ack.c | 54 ++++++++++++++++++++++++------- src/event/quic/ngx_event_quic_migration.c | 2 +- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c index 70d9748bd..11497a6d7 100644 --- a/src/event/quic/ngx_event_quic.c +++ b/src/event/quic/ngx_event_quic.c @@ -312,7 +312,7 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf, ngx_max(2 * NGX_QUIC_MIN_INITIAL_SIZE, 14720)); qc->congestion.ssthresh = (size_t) -1; - qc->congestion.recovery_start = ngx_current_msec; + qc->congestion.recovery_start = ngx_current_msec - 1; if (pkt->validated && pkt->retried) { qc->tp.retry_scid.len = pkt->dcid.len; diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c index 4616e7053..29c5bfed1 100644 --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -41,6 +41,7 @@ static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st); static ngx_msec_t ngx_quic_pcg_duration(ngx_connection_t *c); static void ngx_quic_persistent_congestion(ngx_connection_t *c); +static ngx_msec_t ngx_quic_oldest_sent_packet(ngx_connection_t *c); static void ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *frame); static void ngx_quic_lost_handler(ngx_event_t *ev); @@ -335,6 +336,14 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) cg->in_flight -= f->plen; + /* prevent recovery_start from wrapping */ + + timer = now - cg->recovery_start; + + if ((ngx_msec_int_t) timer < 0) { + cg->recovery_start = ngx_quic_oldest_sent_packet(c) - 1; + } + timer = f->send_time - cg->recovery_start; if ((ngx_msec_int_t) timer <= 0) { @@ -360,14 +369,6 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) now, cg->window, cg->in_flight); } - /* prevent recovery_start from wrapping */ - - timer = cg->recovery_start - now + qc->tp.max_idle_timeout * 2; - - if ((ngx_msec_int_t) timer < 0) { - cg->recovery_start = now - qc->tp.max_idle_timeout * 2; - } - done: if (blocked && cg->in_flight < cg->window) { @@ -543,19 +544,48 @@ ngx_quic_pcg_duration(ngx_connection_t *c) static void ngx_quic_persistent_congestion(ngx_connection_t *c) { - ngx_msec_t now; ngx_quic_congestion_t *cg; ngx_quic_connection_t *qc; qc = ngx_quic_get_connection(c); cg = &qc->congestion; - now = ngx_current_msec; - cg->recovery_start = now; + cg->recovery_start = ngx_quic_oldest_sent_packet(c) - 1; cg->window = qc->path->mtu * 2; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic congestion persistent t:%M win:%uz", now, cg->window); + "quic congestion persistent t:%M win:%uz", + ngx_current_msec, cg->window); +} + + +static ngx_msec_t +ngx_quic_oldest_sent_packet(ngx_connection_t *c) +{ + ngx_msec_t oldest; + ngx_uint_t i; + ngx_queue_t *q; + ngx_quic_frame_t *start; + ngx_quic_send_ctx_t *ctx; + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); + oldest = ngx_current_msec; + + for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { + ctx = &qc->send_ctx[i]; + + if (!ngx_queue_empty(&ctx->sent)) { + q = ngx_queue_head(&ctx->sent); + start = ngx_queue_data(q, ngx_quic_frame_t, queue); + + if ((ngx_msec_int_t) (start->send_time - oldest) < 0) { + oldest = start->send_time; + } + } + } + + return oldest; } diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c index ac22b1327..3caae88e5 100644 --- a/src/event/quic/ngx_event_quic_migration.c +++ b/src/event/quic/ngx_event_quic_migration.c @@ -186,7 +186,7 @@ valid: ngx_max(2 * NGX_QUIC_MIN_INITIAL_SIZE, 14720)); qc->congestion.ssthresh = (size_t) -1; - qc->congestion.recovery_start = ngx_current_msec; + qc->congestion.recovery_start = ngx_current_msec - 1; ngx_quic_init_rtt(qc); } From noreply at nginx.com Tue Apr 15 15:02:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 15 Apr 2025 15:02:02 +0000 (UTC) Subject: [nginx] QUIC: all-levels commit and revert functions. Message-ID: <20250415150202.E658A48F76@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/04c65ccd9a094c00f33bac3a7e0d43cc692409c8 branches: master commit: 04c65ccd9a094c00f33bac3a7e0d43cc692409c8 user: Roman Arutyunyan date: Sun, 9 Mar 2025 16:09:28 +0400 description: QUIC: all-levels commit and revert functions. Previously, these functions operated on a per-level basis. This however resulted in excessive logging of in_flight and will also led to extra work detecting underutilized congestion window in the followup patches. --- src/event/quic/ngx_event_quic_output.c | 96 +++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c index f087e2bfa..9aa7f37ba 100644 --- a/src/event/quic/ngx_event_quic_output.c +++ b/src/event/quic/ngx_event_quic_output.c @@ -45,9 +45,9 @@ static ngx_int_t ngx_quic_create_datagrams(ngx_connection_t *c); -static void ngx_quic_commit_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx); -static void ngx_quic_revert_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, - uint64_t pnum); +static void ngx_quic_commit_send(ngx_connection_t *c); +static void ngx_quic_revert_send(ngx_connection_t *c, + uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST]); #if ((NGX_HAVE_UDP_SEGMENT) && (NGX_HAVE_MSGHDR_MSG_CONTROL)) static ngx_uint_t ngx_quic_allow_segmentation(ngx_connection_t *c); static ngx_int_t ngx_quic_create_segments(ngx_connection_t *c); @@ -127,6 +127,10 @@ ngx_quic_create_datagrams(ngx_connection_t *c) cg = &qc->congestion; path = qc->path; +#if (NGX_SUPPRESS_WARN) + ngx_memzero(preserved_pnum, sizeof(preserved_pnum)); +#endif + while (cg->in_flight < cg->window) { p = dst; @@ -150,12 +154,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c) if (min > len) { /* padding can't be applied - avoid sending the packet */ - - while (i-- > 0) { - ctx = &qc->send_ctx[i]; - ngx_quic_revert_send(c, ctx, preserved_pnum[i]); - } - + ngx_quic_revert_send(c, preserved_pnum); return NGX_OK; } @@ -180,17 +179,12 @@ ngx_quic_create_datagrams(ngx_connection_t *c) } if (n == NGX_AGAIN) { - for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { - ngx_quic_revert_send(c, &qc->send_ctx[i], preserved_pnum[i]); - } - + ngx_quic_revert_send(c, preserved_pnum); ngx_add_timer(&qc->push, NGX_QUIC_SOCKET_RETRY_DELAY); break; } - for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { - ngx_quic_commit_send(c, &qc->send_ctx[i]); - } + ngx_quic_commit_send(c); path->sent += len; } @@ -200,31 +194,36 @@ ngx_quic_create_datagrams(ngx_connection_t *c) static void -ngx_quic_commit_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx) +ngx_quic_commit_send(ngx_connection_t *c) { + ngx_uint_t i; ngx_queue_t *q; ngx_quic_frame_t *f; + ngx_quic_send_ctx_t *ctx; ngx_quic_congestion_t *cg; ngx_quic_connection_t *qc; qc = ngx_quic_get_connection(c); - cg = &qc->congestion; - while (!ngx_queue_empty(&ctx->sending)) { + for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { + ctx = &qc->send_ctx[i]; - q = ngx_queue_head(&ctx->sending); - f = ngx_queue_data(q, ngx_quic_frame_t, queue); + while (!ngx_queue_empty(&ctx->sending)) { - ngx_queue_remove(q); + q = ngx_queue_head(&ctx->sending); + f = ngx_queue_data(q, ngx_quic_frame_t, queue); - if (f->pkt_need_ack && !qc->closing) { - ngx_queue_insert_tail(&ctx->sent, q); + ngx_queue_remove(q); - cg->in_flight += f->plen; + if (f->pkt_need_ack && !qc->closing) { + ngx_queue_insert_tail(&ctx->sent, q); - } else { - ngx_quic_free_frame(c, f); + cg->in_flight += f->plen; + + } else { + ngx_quic_free_frame(c, f); + } } } @@ -234,19 +233,30 @@ ngx_quic_commit_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx) static void -ngx_quic_revert_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, - uint64_t pnum) +ngx_quic_revert_send(ngx_connection_t *c, uint64_t pnum[NGX_QUIC_SEND_CTX_LAST]) { - ngx_queue_t *q; + ngx_uint_t i; + ngx_queue_t *q; + ngx_quic_send_ctx_t *ctx; + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); - while (!ngx_queue_empty(&ctx->sending)) { + for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { + ctx = &qc->send_ctx[i]; - q = ngx_queue_last(&ctx->sending); - ngx_queue_remove(q); - ngx_queue_insert_head(&ctx->frames, q); - } + if (ngx_queue_empty(&ctx->sending)) { + continue; + } - ctx->pnum = pnum; + do { + q = ngx_queue_last(&ctx->sending); + ngx_queue_remove(q); + ngx_queue_insert_head(&ctx->frames, q); + } while (!ngx_queue_empty(&ctx->sending)); + + ctx->pnum = pnum[i]; + } } @@ -311,13 +321,13 @@ ngx_quic_create_segments(ngx_connection_t *c) size_t len, segsize; ssize_t n; u_char *p, *end; - uint64_t preserved_pnum; - ngx_uint_t nseg; + ngx_uint_t nseg, level; ngx_quic_path_t *path; ngx_quic_send_ctx_t *ctx; ngx_quic_congestion_t *cg; ngx_quic_connection_t *qc; static u_char dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF]; + static uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST]; qc = ngx_quic_get_connection(c); cg = &qc->congestion; @@ -335,7 +345,8 @@ ngx_quic_create_segments(ngx_connection_t *c) nseg = 0; - preserved_pnum = ctx->pnum; + level = ctx - qc->send_ctx; + preserved_pnum[level] = ctx->pnum; for ( ;; ) { @@ -369,19 +380,18 @@ ngx_quic_create_segments(ngx_connection_t *c) } if (n == NGX_AGAIN) { - ngx_quic_revert_send(c, ctx, preserved_pnum); - + ngx_quic_revert_send(c, preserved_pnum); ngx_add_timer(&qc->push, NGX_QUIC_SOCKET_RETRY_DELAY); break; } - ngx_quic_commit_send(c, ctx); + ngx_quic_commit_send(c); path->sent += n; p = dst; nseg = 0; - preserved_pnum = ctx->pnum; + preserved_pnum[level] = ctx->pnum; } } From noreply at nginx.com Tue Apr 15 15:02:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 15 Apr 2025 15:02:02 +0000 (UTC) Subject: [nginx] QUIC: do not increase underutilized congestion window. Message-ID: <20250415150202.EBADF48F77@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/cd5e4fa1446dff86fafc3b6ffcc11afd527a024f branches: master commit: cd5e4fa1446dff86fafc3b6ffcc11afd527a024f user: Roman Arutyunyan date: Sat, 4 Jan 2025 18:03:46 +0400 description: QUIC: do not increase underutilized congestion window. As per RFC 9002, Section 7.8, congestion window should not be increased when it's underutilized. --- src/event/quic/ngx_event_quic_ack.c | 24 ++++++++++++++++++++++++ src/event/quic/ngx_event_quic_ack.h | 1 + src/event/quic/ngx_event_quic_connection.h | 1 + src/event/quic/ngx_event_quic_output.c | 12 +++++++++++- 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c index a6f34348b..bc99947bd 100644 --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -354,6 +354,14 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) goto done; } + if (cg->idle) { + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion ack idle t:%M win:%uz if:%uz", + now, cg->window, cg->in_flight); + + goto done; + } + if (cg->window < cg->ssthresh) { cg->window += f->plen; @@ -377,6 +385,22 @@ done: } +void +ngx_quic_congestion_idle(ngx_connection_t *c, ngx_uint_t idle) +{ + ngx_quic_congestion_t *cg; + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); + cg = &qc->congestion; + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion idle:%ui", idle); + + cg->idle = idle; +} + + static void ngx_quic_drop_ack_ranges(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, uint64_t pn) diff --git a/src/event/quic/ngx_event_quic_ack.h b/src/event/quic/ngx_event_quic_ack.h index 56920c2a5..4ad59660f 100644 --- a/src/event/quic/ngx_event_quic_ack.h +++ b/src/event/quic/ngx_event_quic_ack.h @@ -17,6 +17,7 @@ ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c, void ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *frame); +void ngx_quic_congestion_idle(ngx_connection_t *c, ngx_uint_t idle); void ngx_quic_resend_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx); void ngx_quic_set_lost_timer(ngx_connection_t *c); void ngx_quic_pto_handler(ngx_event_t *ev); diff --git a/src/event/quic/ngx_event_quic_connection.h b/src/event/quic/ngx_event_quic_connection.h index 824c92b57..acc09c142 100644 --- a/src/event/quic/ngx_event_quic_connection.h +++ b/src/event/quic/ngx_event_quic_connection.h @@ -169,6 +169,7 @@ typedef struct { size_t window; size_t ssthresh; ngx_msec_t recovery_start; + ngx_uint_t idle; /* unsigned idle:1; */ } ngx_quic_congestion_t; diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c index 9aa7f37ba..a92a539f3 100644 --- a/src/event/quic/ngx_event_quic_output.c +++ b/src/event/quic/ngx_event_quic_output.c @@ -196,7 +196,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c) static void ngx_quic_commit_send(ngx_connection_t *c) { - ngx_uint_t i; + ngx_uint_t i, idle; ngx_queue_t *q; ngx_quic_frame_t *f; ngx_quic_send_ctx_t *ctx; @@ -206,9 +206,15 @@ ngx_quic_commit_send(ngx_connection_t *c) qc = ngx_quic_get_connection(c); cg = &qc->congestion; + idle = 1; + for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { ctx = &qc->send_ctx[i]; + if (!ngx_queue_empty(&ctx->frames)) { + idle = 0; + } + while (!ngx_queue_empty(&ctx->sending)) { q = ngx_queue_head(&ctx->sending); @@ -229,6 +235,8 @@ ngx_quic_commit_send(ngx_connection_t *c) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic congestion send if:%uz", cg->in_flight); + + ngx_quic_congestion_idle(c, idle); } @@ -257,6 +265,8 @@ ngx_quic_revert_send(ngx_connection_t *c, uint64_t pnum[NGX_QUIC_SEND_CTX_LAST]) ctx->pnum = pnum[i]; } + + ngx_quic_congestion_idle(c, 1); } From noreply at nginx.com Tue Apr 15 15:02:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 15 Apr 2025 15:02:02 +0000 (UTC) Subject: [nginx] QUIC: do not shrink congestion window after losing an MTU probe. Message-ID: <20250415150202.F0C7D48F78@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/6bf13e9d57bbc664ac055cdb58c738b09a0f0189 branches: master commit: 6bf13e9d57bbc664ac055cdb58c738b09a0f0189 user: Roman Arutyunyan date: Mon, 6 Jan 2025 16:27:03 +0400 description: QUIC: do not shrink congestion window after losing an MTU probe. As per RFC 9000, Section 14.4: Loss of a QUIC packet that is carried in a PMTU probe is therefore not a reliable indication of congestion and SHOULD NOT trigger a congestion control reaction. --- src/event/quic/ngx_event_quic_ack.c | 8 ++++++++ src/event/quic/ngx_event_quic_migration.c | 1 + src/event/quic/ngx_event_quic_transport.h | 1 + 3 files changed, 10 insertions(+) diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c index bc99947bd..d16545a1d 100644 --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -755,6 +755,14 @@ ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f) goto done; } + if (f->ignore_loss) { + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion lost ignore t:%M win:%uz if:%uz", + now, cg->window, cg->in_flight); + + goto done; + } + cg->recovery_start = now; cg->window /= 2; diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c index 3caae88e5..463eeb503 100644 --- a/src/event/quic/ngx_event_quic_migration.c +++ b/src/event/quic/ngx_event_quic_migration.c @@ -923,6 +923,7 @@ ngx_quic_send_path_mtu_probe(ngx_connection_t *c, ngx_quic_path_t *path) frame->level = ssl_encryption_application; frame->type = NGX_QUIC_FT_PING; + frame->ignore_loss = 1; qc = ngx_quic_get_connection(c); ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application); diff --git a/src/event/quic/ngx_event_quic_transport.h b/src/event/quic/ngx_event_quic_transport.h index 3e320391a..dcd763df1 100644 --- a/src/event/quic/ngx_event_quic_transport.h +++ b/src/event/quic/ngx_event_quic_transport.h @@ -271,6 +271,7 @@ struct ngx_quic_frame_s { unsigned need_ack:1; unsigned pkt_need_ack:1; unsigned ignore_congestion:1; + unsigned ignore_loss:1; ngx_chain_t *data; union { From noreply at nginx.com Tue Apr 15 15:02:03 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 15 Apr 2025 15:02:03 +0000 (UTC) Subject: [nginx] QUIC: CUBIC congestion control. Message-ID: <20250415150203.06C6A48F92@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/f9a7e7cc11e71b2c62d4c5b9ac4feb7e92913c64 branches: master commit: f9a7e7cc11e71b2c62d4c5b9ac4feb7e92913c64 user: Roman Arutyunyan date: Thu, 7 Nov 2024 17:25:45 +0400 description: QUIC: CUBIC congestion control. --- src/event/quic/ngx_event_quic.c | 1 + src/event/quic/ngx_event_quic_ack.c | 189 +++++++++++++++++++++++++++-- src/event/quic/ngx_event_quic_connection.h | 6 + src/event/quic/ngx_event_quic_migration.c | 1 + 4 files changed, 185 insertions(+), 12 deletions(-) diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c index 11497a6d7..49d30e82a 100644 --- a/src/event/quic/ngx_event_quic.c +++ b/src/event/quic/ngx_event_quic.c @@ -312,6 +312,7 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf, ngx_max(2 * NGX_QUIC_MIN_INITIAL_SIZE, 14720)); qc->congestion.ssthresh = (size_t) -1; + qc->congestion.mtu = NGX_QUIC_MIN_INITIAL_SIZE; qc->congestion.recovery_start = ngx_current_msec - 1; if (pkt->validated && pkt->retried) { diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c index d16545a1d..6b0eef35e 100644 --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -20,6 +20,10 @@ /* RFC 9002, 7.6.1. Duration: kPersistentCongestionThreshold */ #define NGX_QUIC_PERSISTENT_CONGESTION_THR 3 +/* CUBIC parameters x10 */ +#define NGX_QUIC_CUBIC_BETA 7 +#define MGX_QUIC_CUBIC_C 4 + /* send time of ACK'ed packets */ typedef struct { @@ -35,10 +39,12 @@ static void ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack, static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, uint64_t min, uint64_t max, ngx_quic_ack_stat_t *st); +static size_t ngx_quic_congestion_cubic(ngx_connection_t *c); static void ngx_quic_drop_ack_ranges(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, uint64_t pn); static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st); +static ngx_msec_t ngx_quic_congestion_cubic_time(ngx_connection_t *c); static ngx_msec_t ngx_quic_pcg_duration(ngx_connection_t *c); static void ngx_quic_persistent_congestion(ngx_connection_t *c); static ngx_msec_t ngx_quic_oldest_sent_packet(ngx_connection_t *c); @@ -314,6 +320,7 @@ ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, void ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) { + size_t w_cubic; ngx_uint_t blocked; ngx_msec_t now, timer; ngx_quic_congestion_t *cg; @@ -370,11 +377,46 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) now, cg->window, cg->ssthresh, cg->in_flight); } else { - cg->window += (uint64_t) qc->path->mtu * f->plen / cg->window; - ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic congestion ack reno t:%M win:%uz if:%uz", - now, cg->window, cg->in_flight); + /* RFC 9438, 4.2. Window Increase Function */ + + w_cubic = ngx_quic_congestion_cubic(c); + + if (cg->window < cg->w_prior) { + cg->w_est += (uint64_t) cg->mtu * f->plen + * 3 * (10 - NGX_QUIC_CUBIC_BETA) + / (10 + NGX_QUIC_CUBIC_BETA) / cg->window; + + } else { + cg->w_est += (uint64_t) cg->mtu * f->plen / cg->window; + } + + if (w_cubic < cg->w_est) { + cg->window = cg->w_est; + + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion ack reno t:%M win:%uz c:%uz if:%uz", + now, cg->window, w_cubic, cg->in_flight); + + } else if (w_cubic > cg->window) { + + if (w_cubic >= cg->window * 3 / 2) { + cg->window += cg->mtu / 2; + + } else { + cg->window += (uint64_t) cg->mtu * (w_cubic - cg->window) + / cg->window; + } + + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion ack cubic t:%M win:%uz c:%uz if:%uz", + now, cg->window, w_cubic, cg->in_flight); + + } else { + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion ack skip t:%M win:%uz c:%uz if:%uz", + now, cg->window, w_cubic, cg->in_flight); + } } done: @@ -385,9 +427,62 @@ done: } +static size_t +ngx_quic_congestion_cubic(ngx_connection_t *c) +{ + int64_t w, t, cc; + ngx_msec_t now; + ngx_quic_congestion_t *cg; + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); + cg = &qc->congestion; + + ngx_quic_congestion_idle(c, cg->idle); + + now = ngx_current_msec; + t = (ngx_msec_int_t) (now - cg->k); + + if (t > 1000000) { + w = NGX_MAX_SIZE_T_VALUE; + goto done; + } + + if (t < -1000000) { + w = 0; + goto done; + } + + /* + * RFC 9438, Figure 1 + * + * w_cubic = C * (t_msec / 1000) ^ 3 * mtu + w_max + */ + + cc = 10000000000ll / (int64_t) cg->mtu / MGX_QUIC_CUBIC_C; + w = t * t * t / cc + (int64_t) cg->w_max; + + if (w > NGX_MAX_SIZE_T_VALUE) { + w = NGX_MAX_SIZE_T_VALUE; + } + + if (w < 0) { + w = 0; + } + +done: + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic cubic t:%L w:%L wm:%uz", t, w, cg->w_max); + + return w; +} + + void ngx_quic_congestion_idle(ngx_connection_t *c, ngx_uint_t idle) { + ngx_msec_t now; ngx_quic_congestion_t *cg; ngx_quic_connection_t *qc; @@ -397,6 +492,18 @@ ngx_quic_congestion_idle(ngx_connection_t *c, ngx_uint_t idle) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic congestion idle:%ui", idle); + if (cg->window >= cg->ssthresh) { + /* RFC 9438, 5.8. Behavior for Application-Limited Flows */ + + now = ngx_current_msec; + + if (cg->idle) { + cg->k += now - cg->idle_start; + } + + cg->idle_start = now; + } + cg->idle = idle; } @@ -580,8 +687,9 @@ ngx_quic_persistent_congestion(ngx_connection_t *c) qc = ngx_quic_get_connection(c); cg = &qc->congestion; + cg->mtu = qc->path->mtu; cg->recovery_start = ngx_quic_oldest_sent_packet(c) - 1; - cg->window = qc->path->mtu * 2; + cg->window = cg->mtu * 2; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic congestion persistent t:%M win:%uz", @@ -763,14 +871,19 @@ ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f) goto done; } - cg->recovery_start = now; - cg->window /= 2; - - if (cg->window < qc->path->mtu * 2) { - cg->window = qc->path->mtu * 2; - } + /* RFC 9438, 4.6. Multiplicative Decrease */ - cg->ssthresh = cg->window; + cg->mtu = qc->path->mtu; + cg->recovery_start = now; + cg->w_prior = cg->window; + /* RFC 9438, 4.7. Fast Convergence */ + cg->w_max = (cg->window < cg->w_max) + ? cg->window * (10 + NGX_QUIC_CUBIC_BETA) / 20 : cg->window; + cg->ssthresh = cg->in_flight * NGX_QUIC_CUBIC_BETA / 10; + cg->window = ngx_max(cg->ssthresh, cg->mtu * 2); + cg->w_est = cg->window; + cg->k = now + ngx_quic_congestion_cubic_time(c); + cg->idle_start = now; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic congestion lost t:%M win:%uz if:%uz", @@ -784,6 +897,58 @@ done: } +static ngx_msec_t +ngx_quic_congestion_cubic_time(ngx_connection_t *c) +{ + int64_t v, x, d, cc; + ngx_uint_t n; + ngx_quic_congestion_t *cg; + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); + cg = &qc->congestion; + + /* + * RFC 9438, Figure 2 + * + * k_msec = ((w_max - cwnd_epoch) / C / mtu) ^ 1/3 * 1000 + */ + + if (cg->w_max <= cg->window) { + return 0; + } + + cc = 10000000000ll / (int64_t) cg->mtu / MGX_QUIC_CUBIC_C; + v = (int64_t) (cg->w_max - cg->window) * cc; + + /* + * Newton-Raphson method for x ^ 3 = v: + * + * x_next = (2 * x_prev + v / x_prev ^ 2) / 3 + */ + + x = 5000; + + for (n = 1; n <= 10; n++) { + d = (v / x / x - x) / 3; + x += d; + + if (ngx_abs(d) <= 100) { + break; + } + } + + if (x > NGX_MAX_SIZE_T_VALUE) { + return NGX_MAX_SIZE_T_VALUE; + } + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic cubic time:%L n:%ui", x, n); + + return x; +} + + void ngx_quic_set_lost_timer(ngx_connection_t *c) { diff --git a/src/event/quic/ngx_event_quic_connection.h b/src/event/quic/ngx_event_quic_connection.h index acc09c142..716d62308 100644 --- a/src/event/quic/ngx_event_quic_connection.h +++ b/src/event/quic/ngx_event_quic_connection.h @@ -168,7 +168,13 @@ typedef struct { size_t in_flight; size_t window; size_t ssthresh; + size_t w_max; + size_t w_est; + size_t w_prior; + size_t mtu; ngx_msec_t recovery_start; + ngx_msec_t idle_start; + ngx_msec_t k; ngx_uint_t idle; /* unsigned idle:1; */ } ngx_quic_congestion_t; diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c index 1d914ffd8..6befc3427 100644 --- a/src/event/quic/ngx_event_quic_migration.c +++ b/src/event/quic/ngx_event_quic_migration.c @@ -186,6 +186,7 @@ valid: ngx_max(2 * NGX_QUIC_MIN_INITIAL_SIZE, 14720)); qc->congestion.ssthresh = (size_t) -1; + qc->congestion.mtu = NGX_QUIC_MIN_INITIAL_SIZE; qc->congestion.recovery_start = ngx_current_msec - 1; ngx_quic_init_rtt(qc); From noreply at nginx.com Tue Apr 15 15:02:03 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 15 Apr 2025 15:02:03 +0000 (UTC) Subject: [nginx] QUIC: ignore congestion control when sending MTU probes. Message-ID: <20250415150203.00FB448F79@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/a40cc700238796d6668a461e121f6ffee5066394 branches: master commit: a40cc700238796d6668a461e121f6ffee5066394 user: Roman Arutyunyan date: Mon, 6 Jan 2025 10:19:56 +0400 description: QUIC: ignore congestion control when sending MTU probes. If connection is network-limited, MTU probes have little chance of being sent since congestion window is almost always full. As a result, PMTUD may not be able to reach the real MTU and the connection may operate with a reduced MTU. The solution is to ignore the congestion window. This may lead to a temporary increase in in-flight count beyond congestion window. --- src/event/quic/ngx_event_quic_migration.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c index 463eeb503..1d914ffd8 100644 --- a/src/event/quic/ngx_event_quic_migration.c +++ b/src/event/quic/ngx_event_quic_migration.c @@ -924,6 +924,7 @@ ngx_quic_send_path_mtu_probe(ngx_connection_t *c, ngx_quic_path_t *path) frame->level = ssl_encryption_application; frame->type = NGX_QUIC_FT_PING; frame->ignore_loss = 1; + frame->ignore_congestion = 1; qc = ngx_quic_get_connection(c); ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application); From noreply at nginx.com Tue Apr 15 15:02:03 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 15 Apr 2025 15:02:03 +0000 (UTC) Subject: [nginx] QUIC: optimized connection frame threshold. Message-ID: <20250415150203.0C3E348F9D@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/2fb32ff24d431211b673ff9c854352ca0c74e27c branches: master commit: 2fb32ff24d431211b673ff9c854352ca0c74e27c user: Roman Arutyunyan date: Fri, 4 Apr 2025 17:39:05 +0400 description: QUIC: optimized connection frame threshold. Previosly the threshold was hardcoded at 10000. This value is too low for high BDP networks. For example, if all frames are STREAM frames, and MTU is 1500, the upper limit for congestion window would be roughly 15M (10000 * 1500). With 100ms RTT it's just a 1.2Gbps network (15M * 10 * 8). In reality, the limit is even lower because of other frame types. Also, the number of frames that could be used simultaneously depends on the total amount of data buffered in all server streams, and client flow control. The change sets frame threshold based on max concurrent streams and stream buffer size, the product of which is the maximum number of in-flight stream data in all server streams at any moment. The value is divided by 2000 to account for a typical MTU 1500 and the fact that not all frames are STREAM frames. --- src/event/quic/ngx_event_quic.c | 4 ++++ src/event/quic/ngx_event_quic_connection.h | 1 + src/event/quic/ngx_event_quic_frames.c | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c index 49d30e82a..4682ecad9 100644 --- a/src/event/quic/ngx_event_quic.c +++ b/src/event/quic/ngx_event_quic.c @@ -315,6 +315,10 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf, qc->congestion.mtu = NGX_QUIC_MIN_INITIAL_SIZE; qc->congestion.recovery_start = ngx_current_msec - 1; + qc->max_frames = (conf->max_concurrent_streams_uni + + conf->max_concurrent_streams_bidi) + * conf->stream_buffer_size / 2000; + if (pkt->validated && pkt->retried) { qc->tp.retry_scid.len = pkt->dcid.len; qc->tp.retry_scid.data = ngx_pstrdup(c->pool, &pkt->dcid); diff --git a/src/event/quic/ngx_event_quic_connection.h b/src/event/quic/ngx_event_quic_connection.h index 716d62308..04cda859e 100644 --- a/src/event/quic/ngx_event_quic_connection.h +++ b/src/event/quic/ngx_event_quic_connection.h @@ -261,6 +261,7 @@ struct ngx_quic_connection_s { ngx_buf_t *free_shadow_bufs; ngx_uint_t nframes; + ngx_uint_t max_frames; #ifdef NGX_QUIC_DEBUG_ALLOC ngx_uint_t nbufs; ngx_uint_t nshadowbufs; diff --git a/src/event/quic/ngx_event_quic_frames.c b/src/event/quic/ngx_event_quic_frames.c index 6ea908cc1..888e8bda2 100644 --- a/src/event/quic/ngx_event_quic_frames.c +++ b/src/event/quic/ngx_event_quic_frames.c @@ -214,7 +214,7 @@ ngx_quic_alloc_frame(ngx_connection_t *c) "quic reuse frame n:%ui", qc->nframes); #endif - } else if (qc->nframes < 10000) { + } else if (qc->nframes < qc->max_frames) { frame = ngx_palloc(c->pool, sizeof(ngx_quic_frame_t)); if (frame == NULL) { return NULL; From noreply at nginx.com Tue Apr 15 15:02:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 15 Apr 2025 15:02:02 +0000 (UTC) Subject: [nginx] HTTP/3: graceful shutdown on keepalive timeout expiration. Message-ID: <20250415150202.D1FC148F60@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/3a97111adfb6e538ddef1828bbf04a35a8915c1f branches: master commit: 3a97111adfb6e538ddef1828bbf04a35a8915c1f user: Roman Arutyunyan date: Tue, 7 Jan 2025 21:14:58 +0400 description: HTTP/3: graceful shutdown on keepalive timeout expiration. Previously, the expiration caused QUIC connection finalization even if there are application-terminated streams finishing sending data. Such finalization terminated these streams. An easy way to trigger this is to request a large file from HTTP/3 over a small MTU. In this case keepalive timeout expiration may abruptly terminate the request stream. --- src/http/v3/ngx_http_v3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http/v3/ngx_http_v3.c b/src/http/v3/ngx_http_v3.c index 8db229b29..d8597ec5c 100644 --- a/src/http/v3/ngx_http_v3.c +++ b/src/http/v3/ngx_http_v3.c @@ -70,7 +70,7 @@ ngx_http_v3_keepalive_handler(ngx_event_t *ev) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 keepalive handler"); - ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_NO_ERROR, + ngx_http_v3_shutdown_connection(c, NGX_HTTP_V3_ERR_NO_ERROR, "keepalive timeout"); } From noreply at nginx.com Tue Apr 15 15:02:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 15 Apr 2025 15:02:02 +0000 (UTC) Subject: [nginx] QUIC: use path MTU in congestion window computations. Message-ID: <20250415150202.D761E48F62@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/53e7e9eb542fb1d3d885bbca03ed1d704aa08f31 branches: master commit: 53e7e9eb542fb1d3d885bbca03ed1d704aa08f31 user: Roman Arutyunyan date: Fri, 3 Jan 2025 11:17:07 +0400 description: QUIC: use path MTU in congestion window computations. As per RFC 9002, Section B.2, max_datagram_size used in congestion window computations should be based on path MTU. --- src/event/quic/ngx_event_quic.c | 4 ++-- src/event/quic/ngx_event_quic_ack.c | 8 ++++---- src/event/quic/ngx_event_quic_migration.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c index 308597e27..70d9748bd 100644 --- a/src/event/quic/ngx_event_quic.c +++ b/src/event/quic/ngx_event_quic.c @@ -308,8 +308,8 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf, qc->streams.client_max_streams_uni = qc->tp.initial_max_streams_uni; qc->streams.client_max_streams_bidi = qc->tp.initial_max_streams_bidi; - qc->congestion.window = ngx_min(10 * qc->tp.max_udp_payload_size, - ngx_max(2 * qc->tp.max_udp_payload_size, + qc->congestion.window = ngx_min(10 * NGX_QUIC_MIN_INITIAL_SIZE, + ngx_max(2 * NGX_QUIC_MIN_INITIAL_SIZE, 14720)); qc->congestion.ssthresh = (size_t) -1; qc->congestion.recovery_start = ngx_current_msec; diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c index 2487ea60d..4616e7053 100644 --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -353,7 +353,7 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) now, cg->window, cg->ssthresh, cg->in_flight); } else { - cg->window += qc->tp.max_udp_payload_size * f->plen / cg->window; + cg->window += (uint64_t) qc->path->mtu * f->plen / cg->window; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic congestion ack reno t:%M win:%uz if:%uz", @@ -552,7 +552,7 @@ ngx_quic_persistent_congestion(ngx_connection_t *c) now = ngx_current_msec; cg->recovery_start = now; - cg->window = qc->tp.max_udp_payload_size * 2; + cg->window = qc->path->mtu * 2; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic congestion persistent t:%M win:%uz", now, cg->window); @@ -698,8 +698,8 @@ ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f) cg->recovery_start = now; cg->window /= 2; - if (cg->window < qc->tp.max_udp_payload_size * 2) { - cg->window = qc->tp.max_udp_payload_size * 2; + if (cg->window < qc->path->mtu * 2) { + cg->window = qc->path->mtu * 2; } cg->ssthresh = cg->window; diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c index 2d1467e14..ac22b1327 100644 --- a/src/event/quic/ngx_event_quic_migration.c +++ b/src/event/quic/ngx_event_quic_migration.c @@ -182,8 +182,8 @@ valid: ngx_memzero(&qc->congestion, sizeof(ngx_quic_congestion_t)); - qc->congestion.window = ngx_min(10 * qc->tp.max_udp_payload_size, - ngx_max(2 * qc->tp.max_udp_payload_size, + qc->congestion.window = ngx_min(10 * NGX_QUIC_MIN_INITIAL_SIZE, + ngx_max(2 * NGX_QUIC_MIN_INITIAL_SIZE, 14720)); qc->congestion.ssthresh = (size_t) -1; qc->congestion.recovery_start = ngx_current_msec; From noreply at nginx.com Tue Apr 15 15:02:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 15 Apr 2025 15:02:02 +0000 (UTC) Subject: [nginx] QUIC: graph-friendly congestion control logging. Message-ID: <20250415150202.CEB0F48F5F@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/2b8b70068a7f7b800ec23390cd2da01b5b91b25f branches: master commit: 2b8b70068a7f7b800ec23390cd2da01b5b91b25f user: Roman Arutyunyan date: Fri, 3 Jan 2025 14:49:47 +0400 description: QUIC: graph-friendly congestion control logging. Improved logging for simpler data extraction for plotting congestion window graphs. In particular, added current milliseconds number from ngx_current_msec. While here, simplified logging text and removed irrelevant data. --- src/event/quic/ngx_event_quic_ack.c | 44 +++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c index c953b8042..2487ea60d 100644 --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -314,7 +314,7 @@ void ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) { ngx_uint_t blocked; - ngx_msec_t timer; + ngx_msec_t now, timer; ngx_quic_congestion_t *cg; ngx_quic_connection_t *qc; @@ -329,6 +329,8 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) return; } + now = ngx_current_msec; + blocked = (cg->in_flight >= cg->window) ? 1 : 0; cg->in_flight -= f->plen; @@ -337,8 +339,8 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) if ((ngx_msec_int_t) timer <= 0) { ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic congestion ack recovery win:%uz ss:%z if:%uz", - cg->window, cg->ssthresh, cg->in_flight); + "quic congestion ack rec t:%M win:%uz if:%uz", + now, cg->window, cg->in_flight); goto done; } @@ -346,24 +348,24 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) if (cg->window < cg->ssthresh) { cg->window += f->plen; - ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic congestion slow start win:%uz ss:%z if:%uz", - cg->window, cg->ssthresh, cg->in_flight); + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion ack ss t:%M win:%uz ss:%z if:%uz", + now, cg->window, cg->ssthresh, cg->in_flight); } else { cg->window += qc->tp.max_udp_payload_size * f->plen / cg->window; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic congestion avoidance win:%uz ss:%z if:%uz", - cg->window, cg->ssthresh, cg->in_flight); + "quic congestion ack reno t:%M win:%uz if:%uz", + now, cg->window, cg->in_flight); } /* prevent recovery_start from wrapping */ - timer = cg->recovery_start - ngx_current_msec + qc->tp.max_idle_timeout * 2; + timer = cg->recovery_start - now + qc->tp.max_idle_timeout * 2; if ((ngx_msec_int_t) timer < 0) { - cg->recovery_start = ngx_current_msec - qc->tp.max_idle_timeout * 2; + cg->recovery_start = now - qc->tp.max_idle_timeout * 2; } done: @@ -541,17 +543,19 @@ ngx_quic_pcg_duration(ngx_connection_t *c) static void ngx_quic_persistent_congestion(ngx_connection_t *c) { + ngx_msec_t now; ngx_quic_congestion_t *cg; ngx_quic_connection_t *qc; qc = ngx_quic_get_connection(c); cg = &qc->congestion; + now = ngx_current_msec; - cg->recovery_start = ngx_current_msec; + cg->recovery_start = now; cg->window = qc->tp.max_udp_payload_size * 2; - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic persistent congestion win:%uz", cg->window); + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion persistent t:%M win:%uz", now, cg->window); } @@ -659,7 +663,7 @@ static void ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f) { ngx_uint_t blocked; - ngx_msec_t timer; + ngx_msec_t now, timer; ngx_quic_congestion_t *cg; ngx_quic_connection_t *qc; @@ -681,15 +685,17 @@ ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f) timer = f->send_time - cg->recovery_start; + now = ngx_current_msec; + if ((ngx_msec_int_t) timer <= 0) { ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic congestion lost recovery win:%uz ss:%z if:%uz", - cg->window, cg->ssthresh, cg->in_flight); + "quic congestion lost rec t:%M win:%uz if:%uz", + now, cg->window, cg->in_flight); goto done; } - cg->recovery_start = ngx_current_msec; + cg->recovery_start = now; cg->window /= 2; if (cg->window < qc->tp.max_udp_payload_size * 2) { @@ -699,8 +705,8 @@ ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f) cg->ssthresh = cg->window; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic congestion lost win:%uz ss:%z if:%uz", - cg->window, cg->ssthresh, cg->in_flight); + "quic congestion lost t:%M win:%uz if:%uz", + now, cg->window, cg->in_flight); done: From noreply at nginx.com Tue Apr 15 15:02:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 15 Apr 2025 15:02:02 +0000 (UTC) Subject: [nginx] QUIC: ngx_msec_t overflow protection. Message-ID: <20250415150202.E178D48F64@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/1e883a40db98b70e422ff8e4d1d0e87e3f8ccaa5 branches: master commit: 1e883a40db98b70e422ff8e4d1d0e87e3f8ccaa5 user: Roman Arutyunyan date: Mon, 10 Mar 2025 12:19:25 +0400 description: QUIC: ngx_msec_t overflow protection. On some systems the value of ngx_current_msec is derived from monotonic clock, for which the following is defined by POSIX: For this clock, the value returned by clock_gettime() represents the amount of time (in seconds and nanoseconds) since an unspecified point in the past. As as result, overflow protection is needed when comparing two ngx_msec_t. The change adds such protection to the ngx_quic_detect_lost() function. --- src/event/quic/ngx_event_quic_ack.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c index 29c5bfed1..a6f34348b 100644 --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -449,9 +449,10 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st) now = ngx_current_msec; thr = ngx_quic_lost_threshold(qc); - /* send time of lost packets across all send contexts */ - oldest = NGX_TIMER_INFINITE; - newest = NGX_TIMER_INFINITE; +#if (NGX_SUPPRESS_WARN) + oldest = now; + newest = now; +#endif nlost = 0; @@ -484,13 +485,17 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st) break; } - if (start->send_time > qc->first_rtt) { + if ((ngx_msec_int_t) (start->send_time - qc->first_rtt) > 0) { - if (oldest == NGX_TIMER_INFINITE || start->send_time < oldest) { + if (nlost == 0 + || (ngx_msec_int_t) (start->send_time - oldest) < 0) + { oldest = start->send_time; } - if (newest == NGX_TIMER_INFINITE || start->send_time > newest) { + if (nlost == 0 + || (ngx_msec_int_t) (start->send_time - newest) > 0) + { newest = start->send_time; } @@ -511,8 +516,9 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st) * latest ACK frame. */ - if (st && nlost >= 2 && (st->newest < oldest || st->oldest > newest)) { - + if (st && nlost >= 2 && ((ngx_msec_int_t) (st->newest - oldest) < 0 + || (ngx_msec_int_t) (st->oldest - newest) > 0)) + { if (newest - oldest > ngx_quic_pcg_duration(c)) { ngx_quic_persistent_congestion(c); } From noreply at nginx.com Tue Apr 15 15:02:03 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 15 Apr 2025 15:02:03 +0000 (UTC) Subject: [nginx] QUIC: dynamic packet threshold. Message-ID: <20250415150203.1129348FA4@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/aa49a416b8ea762558211de25d6ee70ca73bb373 branches: master commit: aa49a416b8ea762558211de25d6ee70ca73bb373 user: Roman Arutyunyan date: Mon, 14 Apr 2025 17:16:47 +0400 description: QUIC: dynamic packet threshold. RFC 9002, Section 6.1.1 defines packet reordering threshold as 3. Testing shows that such low value leads to spurious packet losses followed by congestion window collapse. The change implements dynamic packet threshold detection based on in-flight packet range. Packet threshold is defined as half the number of in-flight packets, with mininum value of 3. Also, renamed ngx_quic_lost_threshold() to ngx_quic_time_threshold() for better compliance with RFC 9002 terms. --- src/event/quic/ngx_event_quic_ack.c | 48 ++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c index 6b0eef35e..b8b72e943 100644 --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -33,7 +33,8 @@ typedef struct { } ngx_quic_ack_stat_t; -static ngx_inline ngx_msec_t ngx_quic_lost_threshold(ngx_quic_connection_t *qc); +static ngx_inline ngx_msec_t ngx_quic_time_threshold(ngx_quic_connection_t *qc); +static uint64_t ngx_quic_packet_threshold(ngx_quic_send_ctx_t *ctx); static void ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack, enum ssl_encryption_level_t level, ngx_msec_t send_time); static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c, @@ -55,7 +56,7 @@ static void ngx_quic_lost_handler(ngx_event_t *ev); /* RFC 9002, 6.1.2. Time Threshold: kTimeThreshold, kGranularity */ static ngx_inline ngx_msec_t -ngx_quic_lost_threshold(ngx_quic_connection_t *qc) +ngx_quic_time_threshold(ngx_quic_connection_t *qc) { ngx_msec_t thr; @@ -66,6 +67,29 @@ ngx_quic_lost_threshold(ngx_quic_connection_t *qc) } +static uint64_t +ngx_quic_packet_threshold(ngx_quic_send_ctx_t *ctx) +{ + uint64_t pkt_thr; + ngx_queue_t *q; + ngx_quic_frame_t *f; + + if (ngx_queue_empty(&ctx->sent)) { + return NGX_QUIC_PKT_THR; + } + + q = ngx_queue_head(&ctx->sent); + f = ngx_queue_data(q, ngx_quic_frame_t, queue); + pkt_thr = (ctx->pnum - f->pnum) / 2; + + if (pkt_thr <= NGX_QUIC_PKT_THR) { + return NGX_QUIC_PKT_THR; + } + + return pkt_thr; +} + + ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, ngx_quic_frame_t *f) @@ -569,6 +593,7 @@ ngx_quic_drop_ack_ranges(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st) { + uint64_t pkt_thr; ngx_uint_t i, nlost; ngx_msec_t now, wait, thr, oldest, newest; ngx_queue_t *q; @@ -578,7 +603,7 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st) qc = ngx_quic_get_connection(c); now = ngx_current_msec; - thr = ngx_quic_lost_threshold(qc); + thr = ngx_quic_time_threshold(qc); #if (NGX_SUPPRESS_WARN) oldest = now; @@ -595,6 +620,8 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st) continue; } + pkt_thr = ngx_quic_packet_threshold(ctx); + while (!ngx_queue_empty(&ctx->sent)) { q = ngx_queue_head(&ctx->sent); @@ -606,12 +633,12 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st) wait = start->send_time + thr - now; - ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic detect_lost pnum:%uL thr:%M wait:%i level:%d", - start->pnum, thr, (ngx_int_t) wait, start->level); + ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic detect_lost pnum:%uL thr:%M pthr:%uL wait:%i level:%d", + start->pnum, thr, pkt_thr, (ngx_int_t) wait, start->level); if ((ngx_msec_int_t) wait > 0 - && ctx->largest_ack - start->pnum < NGX_QUIC_PKT_THR) + && ctx->largest_ack - start->pnum < pkt_thr) { break; } @@ -952,6 +979,7 @@ ngx_quic_congestion_cubic_time(ngx_connection_t *c) void ngx_quic_set_lost_timer(ngx_connection_t *c) { + uint64_t pkt_thr; ngx_uint_t i; ngx_msec_t now; ngx_queue_t *q; @@ -977,10 +1005,12 @@ ngx_quic_set_lost_timer(ngx_connection_t *c) q = ngx_queue_head(&ctx->sent); f = ngx_queue_data(q, ngx_quic_frame_t, queue); w = (ngx_msec_int_t) - (f->send_time + ngx_quic_lost_threshold(qc) - now); + (f->send_time + ngx_quic_time_threshold(qc) - now); if (f->pnum <= ctx->largest_ack) { - if (w < 0 || ctx->largest_ack - f->pnum >= NGX_QUIC_PKT_THR) { + pkt_thr = ngx_quic_packet_threshold(ctx); + + if (w < 0 || ctx->largest_ack - f->pnum >= pkt_thr) { w = 0; } From noreply at nginx.com Wed Apr 16 12:02:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 16 Apr 2025 12:02:02 +0000 (UTC) Subject: [nginx] nginx-1.27.5-RELEASE Message-ID: <20250416120202.A425247801@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/6ac8b69f06bc10d5503f636da888fa70095b151c branches: master commit: 6ac8b69f06bc10d5503f636da888fa70095b151c user: Sergey Kandaurov date: Mon, 14 Apr 2025 22:35:27 +0400 description: nginx-1.27.5-RELEASE --- docs/xml/nginx/changes.xml | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml index b55177d80..ecb063d57 100644 --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,77 @@ + + + + +контроль перегрузки CUBIC в соединениях QUIC. + + +CUBIC congestion control in QUIC connections. + + + + + +ограничение на максимальный размер кешируемых в разделяемой памяти +SSL-сессий поднято до 8192. + + +the maximum size limit for SSL sessions cached in shared memory +has been raised to 8192. + + + + + +в директивах grpc_ssl_password_file, proxy_ssl_password_file и +uwsgi_ssl_password_file +при загрузке SSL-сертификатов и зашифрованных ключей из переменных; +ошибка появилась в 1.23.1. + + +in the "grpc_ssl_password_file", "proxy_ssl_password_file", and +"uwsgi_ssl_password_file" directives +when loading SSL certificates and encrypted keys from variables; +the bug had appeared in 1.23.1. + + + + + +в переменных $ssl_curve и $ssl_curves +при использовании подключаемых кривых в OpenSSL. + + +in the $ssl_curve and $ssl_curves variables +when using pluggable curves in OpenSSL. + + + + + +nginx не собирался с musl libc.
+Спасибо Piotr Sikora. +
+ +nginx could not be built with musl libc.
+Thanks to Piotr Sikora. +
+
+ + + +Улучшения производительности и исправления в HTTP/3. + + +Performance improvements and bugfixes in HTTP/3. + + + +
+ + From noreply at nginx.com Wed Apr 16 12:05:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 16 Apr 2025 12:05:02 +0000 (UTC) Subject: [nginx] Annotated tag created: release-1.27.5 Message-ID: <20250416120502.A9FB34784E@pubserv1.nginx> details: https://github.com/nginx/nginx/releases/tag/release-1.27.5 branches: commit: 6ac8b69f06bc10d5503f636da888fa70095b151c user: Sergey Kandaurov date: Wed Apr 16 16:03:18 2025 +0400 description: release-1.27.5 tag From noreply at nginx.com Wed Apr 16 14:56:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 16 Apr 2025 14:56:02 +0000 (UTC) Subject: [nginx] Version bump. Message-ID: <20250416145602.723FF489E9@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/0626e60a754895b0d6e8f6f7d3043c465da7b346 branches: master commit: 0626e60a754895b0d6e8f6f7d3043c465da7b346 user: Roman Arutyunyan date: Wed, 16 Apr 2025 18:48:50 +0400 description: Version bump. --- src/core/nginx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/nginx.h b/src/core/nginx.h index 090777853..72664a531 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1027005 -#define NGINX_VERSION "1.27.5" +#define nginx_version 1029000 +#define NGINX_VERSION "1.29.0" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From noreply at nginx.com Thu Apr 17 08:52:01 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Thu, 17 Apr 2025 08:52:01 +0000 (UTC) Subject: [nginx] QUIC: lowered log level for unsupported transport parameters. Message-ID: <20250417085201.F38E948EF7@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/04813dac865d538d160de1d01c7248a22503700b branches: master commit: 04813dac865d538d160de1d01c7248a22503700b user: Roman Arutyunyan date: Tue, 8 Apr 2025 16:54:28 +0400 description: QUIC: lowered log level for unsupported transport parameters. --- src/event/quic/ngx_event_quic_transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/event/quic/ngx_event_quic_transport.c b/src/event/quic/ngx_event_quic_transport.c index bb13447b5..0b3ef4b2e 100644 --- a/src/event/quic/ngx_event_quic_transport.c +++ b/src/event/quic/ngx_event_quic_transport.c @@ -1773,7 +1773,7 @@ ngx_quic_parse_transport_params(u_char *p, u_char *end, ngx_quic_tp_t *tp, } if (rc == NGX_DECLINED) { - ngx_log_error(NGX_LOG_INFO, log, 0, + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0, "quic %s transport param id:0x%xL, skipped", (id % 31 == 27) ? "reserved" : "unknown", id); } From noreply at nginx.com Thu Apr 17 15:13:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Thu, 17 Apr 2025 15:13:02 +0000 (UTC) Subject: [nginx] Fixed -Wunterminated-string-initialization with gcc15. Message-ID: <20250417151302.C008748EF7@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/444954abacef1d77f3dc6e9b1878684c7e6fe5b3 branches: master commit: 444954abacef1d77f3dc6e9b1878684c7e6fe5b3 user: Roman Arutyunyan date: Wed, 16 Apr 2025 16:56:44 +0400 description: Fixed -Wunterminated-string-initialization with gcc15. --- src/event/quic/ngx_event_quic_protection.c | 12 +++++++----- src/http/v2/ngx_http_v2_filter_module.c | 7 ++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/event/quic/ngx_event_quic_protection.c b/src/event/quic/ngx_event_quic_protection.c index 3f249b36a..e5c0df7b4 100644 --- a/src/event/quic/ngx_event_quic_protection.c +++ b/src/event/quic/ngx_event_quic_protection.c @@ -125,9 +125,10 @@ ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys, ngx_str_t *secret, ngx_quic_secret_t *client, *server; ngx_quic_ciphers_t ciphers; - static const uint8_t salt[20] = - "\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17" - "\x9a\xe6\xa4\xc8\x0c\xad\xcc\xbb\x7f\x0a"; + static const uint8_t salt[20] = { + 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, + 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a + }; client = &keys->secrets[ssl_encryption_initial].client; server = &keys->secrets[ssl_encryption_initial].server; @@ -958,8 +959,9 @@ ngx_quic_create_retry_packet(ngx_quic_header_t *pkt, ngx_str_t *res) /* 5.8. Retry Packet Integrity */ static ngx_quic_md_t key = ngx_quic_md( "\xbe\x0c\x69\x0b\x9f\x66\x57\x5a\x1d\x76\x6b\x54\xe3\x68\xc8\x4e"); - static const u_char nonce[NGX_QUIC_IV_LEN] = - "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb"; + static const u_char nonce[NGX_QUIC_IV_LEN] = { + 0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb + }; static ngx_str_t in = ngx_string(""); ad.data = res->data; diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index 1e2cafaf1..b63e343a0 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -115,10 +115,11 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) ngx_http_core_srv_conf_t *cscf; u_char addr[NGX_SOCKADDR_STRLEN]; - static const u_char nginx[5] = "\x84\xaa\x63\x55\xe7"; + static const u_char nginx[5] = { 0x84, 0xaa, 0x63, 0x55, 0xe7 }; #if (NGX_HTTP_GZIP) - static const u_char accept_encoding[12] = - "\x8b\x84\x84\x2d\x69\x5b\x05\x44\x3c\x86\xaa\x6f"; + static const u_char accept_encoding[12] = { + 0x8b, 0x84, 0x84, 0x2d, 0x69, 0x5b, 0x05, 0x44, 0x3c, 0x86, 0xaa, 0x6f + }; #endif static size_t nginx_ver_len = ngx_http_v2_literal_size(NGINX_VER); From noreply at nginx.com Fri Apr 18 11:29:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Fri, 18 Apr 2025 11:29:02 +0000 (UTC) Subject: [nginx] HTTP/3: fixed NGX_HTTP_V3_VARLEN_INT_LEN value. Message-ID: <20250418112902.EA70948F3C@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/0f9f43b79eed64ab1a876be76ff0f49d499784fc branches: master commit: 0f9f43b79eed64ab1a876be76ff0f49d499784fc user: Roman Arutyunyan date: Fri, 18 Apr 2025 11:16:57 +0400 description: HTTP/3: fixed NGX_HTTP_V3_VARLEN_INT_LEN value. After fixing ngx_http_v3_encode_varlen_int() in 400eb1b628, NGX_HTTP_V3_VARLEN_INT_LEN retained the old value of 4, which is insufficient for the values over 1073741823 (1G - 1). The NGX_HTTP_V3_VARLEN_INT_LEN macro is used in ngx_http_v3_uni.c to format stream and frame types. Old buffer size is enough for formatting this data. Also, the macro is used in ngx_http_v3_filter_module.c to format output chunks and trailers. Considering output_buffers and proxy_buffer_size are below 1G in all realistic scenarios, the old buffer size is enough here as well. --- src/http/v3/ngx_http_v3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http/v3/ngx_http_v3.h b/src/http/v3/ngx_http_v3.h index 9dcb5e6a7..8fd212c1f 100644 --- a/src/http/v3/ngx_http_v3.h +++ b/src/http/v3/ngx_http_v3.h @@ -23,7 +23,7 @@ #define NGX_HTTP_V3_HQ_ALPN_PROTO "\x0Ahq-interop" #define NGX_HTTP_V3_HQ_PROTO "hq-interop" -#define NGX_HTTP_V3_VARLEN_INT_LEN 4 +#define NGX_HTTP_V3_VARLEN_INT_LEN 8 #define NGX_HTTP_V3_PREFIX_INT_LEN 11 #define NGX_HTTP_V3_STREAM_CONTROL 0x00 From noreply at nginx.com Fri Apr 18 19:58:03 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Fri, 18 Apr 2025 19:58:03 +0000 (UTC) Subject: [nginx] Core: improved NGX_ALIGNMENT detection on some x86_64 platforms. Message-ID: <20250418195803.378D448F62@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/b9d0ba6677ff7761c85f5556776d6a6c2a7a7051 branches: master commit: b9d0ba6677ff7761c85f5556776d6a6c2a7a7051 user: Aleksei Bavshin date: Tue, 14 Jan 2025 10:32:24 -0800 description: Core: improved NGX_ALIGNMENT detection on some x86_64 platforms. Previously, the default pool alignment used sizeof(unsigned long), with the expectation that this would match to a platform word size. Certain 64-bit platforms prove this assumption wrong by keeping the 32-bit long type, which is fully compliant with the C standard. This introduces a possibility of suboptimal misaligned access to the data allocated with ngx_palloc() on the affected platforms, which is addressed here by changing the default NGX_ALIGNMENT to a pointer size. As we override the detection in auto/os/conf for all the machine types except x86, and Unix-like 64-bit systems prefer the 64-bit long, the impact of the change should be limited to Win64 x64. --- src/core/ngx_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h index 1861be601..707ab216b 100644 --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -94,7 +94,7 @@ typedef intptr_t ngx_flag_t; #ifndef NGX_ALIGNMENT -#define NGX_ALIGNMENT sizeof(unsigned long) /* platform word */ +#define NGX_ALIGNMENT sizeof(uintptr_t) /* platform word */ #endif #define ngx_align(d, a) (((d) + (a - 1)) & ~(a - 1)) From noreply at nginx.com Fri Apr 18 19:58:03 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Fri, 18 Apr 2025 19:58:03 +0000 (UTC) Subject: [nginx] Win32: added detection of ARM64 target. Message-ID: <20250418195803.3A8C448F78@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/020b1db7eb187d4a9a5f1d6154c664a463473b36 branches: master commit: 020b1db7eb187d4a9a5f1d6154c664a463473b36 user: Aleksei Bavshin date: Tue, 14 Jan 2025 11:11:28 -0800 description: Win32: added detection of ARM64 target. This extends the target selection implemented in dad6ec3aa63f to support Windows ARM64 platforms. OpenSSL support for VC-WIN64-ARM target first appeared in 1.1.1 and is present in all currently supported (3.x) branches. As a side effect, ARM64 Windows builds will get 16-byte alignment along with the rest of non-x86 platforms. This is safe, as malloc on 64-bit Windows guarantees the fundamental alignment of allocations, 16 bytes. --- auto/cc/msvc | 4 ++++ auto/lib/openssl/make | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/auto/cc/msvc b/auto/cc/msvc index 567bac7bc..fe7c34e49 100644 --- a/auto/cc/msvc +++ b/auto/cc/msvc @@ -26,6 +26,10 @@ ngx_msvc_ver=`echo $NGX_MSVC_VER | sed -e 's/^\([0-9]*\).*/\1/'` case "$NGX_MSVC_VER" in + *ARM64) + NGX_MACHINE=arm64 + ;; + *x64) NGX_MACHINE=amd64 ;; diff --git a/auto/lib/openssl/make b/auto/lib/openssl/make index a7e9369e7..f8480146d 100644 --- a/auto/lib/openssl/make +++ b/auto/lib/openssl/make @@ -13,6 +13,10 @@ case "$CC" in OPENSSL_TARGET=VC-WIN64A ;; + arm64) + OPENSSL_TARGET=VC-WIN64-ARM + ;; + *) OPENSSL_TARGET=VC-WIN32 ;; From noreply at nginx.com Mon Apr 21 16:48:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Mon, 21 Apr 2025 16:48:02 +0000 (UTC) Subject: [njs] Replaced vm with mp in NJS_CHB_MP_INIT(). Message-ID: <20250421164802.BD90C48FA4@pubserv1.nginx> details: https://github.com/nginx/njs/commit/264b1ced4259db93f928f57dfbddcc5e3f93d68b branches: master commit: 264b1ced4259db93f928f57dfbddcc5e3f93d68b user: Zhidao HONG date: Mon, 21 Apr 2025 23:37:49 +0800 description: Replaced vm with mp in NJS_CHB_MP_INIT(). --- external/njs_query_string_module.c | 6 +++--- external/njs_xml_module.c | 2 +- external/njs_zlib_module.c | 4 ++-- nginx/ngx_http_js_module.c | 4 ++-- nginx/ngx_js_fetch.c | 8 ++++---- src/njs_array.c | 2 +- src/njs_chb.h | 4 ++-- src/njs_error.c | 2 +- src/njs_function.c | 2 +- src/njs_json.c | 4 ++-- src/njs_regexp.c | 2 +- src/njs_string.c | 8 ++++---- src/njs_typed_array.c | 2 +- src/njs_vm.c | 2 +- src/test/njs_benchmark.c | 2 +- src/test/njs_externals_test.c | 2 +- src/test/njs_unit_test.c | 2 +- 17 files changed, 29 insertions(+), 29 deletions(-) diff --git a/external/njs_query_string_module.c b/external/njs_query_string_module.c index f9b7c552..e2f849d2 100644 --- a/external/njs_query_string_module.c +++ b/external/njs_query_string_module.c @@ -152,7 +152,7 @@ njs_query_string_decode(njs_vm_t *vm, njs_value_t *value, const u_char *start, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); njs_utf8_decode_init(&ctx); cp = 0; @@ -749,7 +749,7 @@ njs_query_string_stringify(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, encode = njs_value_function(val); } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); keys = njs_vm_object_keys(vm, object, njs_value_arg(&value)); if (njs_slow_path(keys == NULL)) { @@ -841,7 +841,7 @@ njs_query_string_escape(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_value_string_get(string, &str); - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); ret = njs_query_string_encode(&chain, &str); if (njs_slow_path(ret != NJS_OK)) { diff --git a/external/njs_xml_module.c b/external/njs_xml_module.c index 6bdbb639..e524ba5c 100644 --- a/external/njs_xml_module.c +++ b/external/njs_xml_module.c @@ -1785,7 +1785,7 @@ njs_xml_ext_canonicalization(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); buf = xmlOutputBufferCreateIO(njs_xml_buf_write_cb, NULL, &chain, NULL); if (njs_slow_path(buf == NULL)) { diff --git a/external/njs_zlib_module.c b/external/njs_zlib_module.c index 7945e646..d3a667d8 100644 --- a/external/njs_zlib_module.c +++ b/external/njs_zlib_module.c @@ -320,7 +320,7 @@ njs_zlib_ext_deflate(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); do { stream.next_out = njs_chb_reserve(&chain, chunk_size); @@ -461,7 +461,7 @@ njs_zlib_ext_inflate(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); while (rc != Z_STREAM_END) { stream.next_out = njs_chb_reserve(&chain, chunk_size); diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index 5a131bc9..ce4ce365 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -3121,7 +3121,7 @@ ngx_http_js_header_in_array(njs_vm_t *vm, ngx_http_request_t *r, (*hh)->value.len); } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); for (i = 0; i < n; i++) { njs_chb_append(&chain, hh[i]->value.data, hh[i]->value.len); @@ -4166,7 +4166,7 @@ ngx_http_js_header_generic(njs_vm_t *vm, ngx_http_request_t *r, (*ph)->value.len); } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); sep = flags & NJS_HEADER_SEMICOLON ? ';' : ','; diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index 9539a687..63e7a298 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -732,7 +732,7 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, http->header_only = njs_strstr_eq(&request.method, &njs_str_value("HEAD")); - NJS_CHB_MP_INIT(&http->chain, vm); + NJS_CHB_MP_INIT(&http->chain, njs_vm_memory_pool(vm)); njs_chb_append(&http->chain, request.method.start, request.method.length); njs_chb_append_literal(&http->chain, " "); @@ -1035,7 +1035,7 @@ ngx_js_ext_response_constructor(njs_vm_t *vm, njs_value_t *args, } } - NJS_CHB_MP_INIT(&response->chain, vm); + NJS_CHB_MP_INIT(&response->chain, njs_vm_memory_pool(vm)); body = njs_arg(args, nargs, 1); @@ -2516,7 +2516,7 @@ ngx_js_http_process_headers(ngx_js_http_t *http) njs_chb_destroy(&http->chain); - NJS_CHB_MP_INIT(&http->response.chain, http->vm); + NJS_CHB_MP_INIT(&http->response.chain, njs_vm_memory_pool(http->vm)); http->process = ngx_js_http_process_body; @@ -3296,7 +3296,7 @@ ngx_headers_js_get(njs_vm_t *vm, njs_value_t *value, njs_str_t *name, return NJS_DECLINED; } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); h = ph; diff --git a/src/njs_array.c b/src/njs_array.c index 15a6b6d3..913bc8cf 100644 --- a/src/njs_array.c +++ b/src/njs_array.c @@ -1686,7 +1686,7 @@ njs_array_prototype_join(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, value = &entry; - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); for (i = 0; i < len; i++) { ret = njs_value_property_i64(vm, this, i, value); diff --git a/src/njs_chb.h b/src/njs_chb.h index 3dbe5ac9..4bd1cb3f 100644 --- a/src/njs_chb.h +++ b/src/njs_chb.h @@ -34,8 +34,8 @@ typedef struct { void njs_chb_init(njs_chb_t *chain, void *pool, njs_chb_alloc_t alloc, njs_chb_free_t free); -#define NJS_CHB_MP_INIT(chain, vm) \ - njs_chb_init(chain, njs_vm_memory_pool(vm), (njs_chb_alloc_t) njs_mp_alloc,\ +#define NJS_CHB_MP_INIT(chain, mp) \ + njs_chb_init(chain, mp, (njs_chb_alloc_t) njs_mp_alloc, \ (njs_chb_free_t) njs_mp_free) #define NJS_CHB_CTX_INIT(chain, ctx) \ njs_chb_init(chain, ctx, (njs_chb_alloc_t) js_malloc, \ diff --git a/src/njs_error.c b/src/njs_error.c index 6a14d767..b9da6597 100644 --- a/src/njs_error.c +++ b/src/njs_error.c @@ -1149,7 +1149,7 @@ njs_backtrace_to_string(njs_vm_t *vm, njs_arr_t *backtrace, njs_str_t *dst) return NJS_OK; } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); njs_chb_append_str(&chain, dst); njs_chb_append(&chain, "\n", 1); diff --git a/src/njs_function.c b/src/njs_function.c index c677be57..326549f5 100644 --- a/src/njs_function.c +++ b/src/njs_function.c @@ -1032,7 +1032,7 @@ njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto fail; } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); if (async) { njs_chb_append_literal(&chain, "(async function("); diff --git a/src/njs_json.c b/src/njs_json.c index 85c5d0e8..8ba13314 100644 --- a/src/njs_json.c +++ b/src/njs_json.c @@ -1093,7 +1093,7 @@ njs_json_stringify_iterator(njs_json_stringify_t *stringify, goto memory_error; } - NJS_CHB_MP_INIT(&chain, stringify->vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(stringify->vm)); for ( ;; ) { if (state->index == 0) { @@ -1977,7 +1977,7 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_t *retval, njs_value_t *value, value = &exception; } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); if (!njs_dump_is_recursive(value)) { ret = njs_dump_terminal(stringify, &chain, value, console); diff --git a/src/njs_regexp.c b/src/njs_regexp.c index 1c7cfe87..479f0b75 100644 --- a/src/njs_regexp.c +++ b/src/njs_regexp.c @@ -1373,7 +1373,7 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args, } } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); results.separate = 0; results.pointer = 0; diff --git a/src/njs_string.c b/src/njs_string.c index 9405a8db..6a91cb4c 100644 --- a/src/njs_string.c +++ b/src/njs_string.c @@ -2955,7 +2955,7 @@ njs_string_get_substitution(njs_vm_t *vm, njs_value_t *matched, p = rep.start; end = rep.start + rep.length; - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); while (p < end) { r = njs_strlchr(p, end, '$'); @@ -3244,7 +3244,7 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_OK; } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); start = string.start; @@ -3899,7 +3899,7 @@ njs_string_decode_uri(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, src = string.start; end = string.start + string.size; - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); njs_utf8_decode_init(&ctx); @@ -4173,7 +4173,7 @@ njs_string_atob(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, len = njs_base64_decoded_length(len, pad); - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); dst = njs_chb_reserve(&chain, len * 2); if (njs_slow_path(dst == NULL)) { diff --git a/src/njs_typed_array.c b/src/njs_typed_array.c index 2a485a19..5930dcb0 100644 --- a/src/njs_typed_array.c +++ b/src/njs_typed_array.c @@ -2131,7 +2131,7 @@ njs_typed_array_prototype_join(njs_vm_t *vm, njs_value_t *args, return NJS_ERROR; } - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); njs_typed_array_to_chain(vm, &chain, array, separator); diff --git a/src/njs_vm.c b/src/njs_vm.c index dbeffa51..43b2ccc2 100644 --- a/src/njs_vm.c +++ b/src/njs_vm.c @@ -233,7 +233,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end) } if (njs_slow_path(vm->options.ast)) { - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); ret = njs_parser_serialize_ast(parser.node, &chain); if (njs_slow_path(ret == NJS_ERROR)) { return ret; diff --git a/src/test/njs_benchmark.c b/src/test/njs_benchmark.c index 98c618c8..66c4e84b 100644 --- a/src/test/njs_benchmark.c +++ b/src/test/njs_benchmark.c @@ -745,7 +745,7 @@ njs_benchmark_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } else if (memcmp(mode.start, "chb", 3) == 0) { - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); njs_chb_append_literal(&chain, "abc"); njs_chb_append(&chain, s.start, s.length); diff --git a/src/test/njs_externals_test.c b/src/test/njs_externals_test.c index 7d2e82af..33f0020a 100644 --- a/src/test/njs_externals_test.c +++ b/src/test/njs_externals_test.c @@ -323,7 +323,7 @@ njs_unit_test_r_header(njs_vm_t *vm, njs_object_prop_t *prop, ret = njs_vm_prop_name(vm, prop, &h); if (ret == NJS_OK) { - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); njs_chb_append(&chain, h.start, h.length); njs_chb_append(&chain, (u_char *) "|АБВ", njs_length("|АБВ")); diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 980fd7fa..9c935e5b 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -22399,7 +22399,7 @@ njs_chb_test(njs_vm_t *vm, njs_opts_t *opts, njs_stat_t *stat) static const njs_str_t expected = njs_str("arg: \"XYZ\" -5"); - NJS_CHB_MP_INIT(&chain, vm); + NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); p = njs_chb_reserve(&chain, 513); if (p == NULL) { From noreply at nginx.com Mon Apr 21 21:47:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Mon, 21 Apr 2025 21:47:02 +0000 (UTC) Subject: [njs] Test262: fixed mktemp format on OpenBSD. Message-ID: <20250421214702.B148248FAC@pubserv1.nginx> details: https://github.com/nginx/njs/commit/6a0826429142d3ad509c7dede5ad301d23dffce4 branches: master commit: 6a0826429142d3ad509c7dede5ad301d23dffce4 user: Dmitry Volyntsev date: Mon, 21 Apr 2025 09:41:46 -0700 description: Test262: fixed mktemp format on OpenBSD. mktemp: insufficient number of Xs in template `/tmp/njs_test.XXX' --- test/options | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/options b/test/options index a7b6bd3e..58000703 100644 --- a/test/options +++ b/test/options @@ -3,7 +3,7 @@ # Copyright (C) Dmitry Volyntsev # Copyright (C) NGINX, Inc. -NJS_TEST_DIR=`mktemp -d /tmp/njs_test.XXX` +NJS_TEST_DIR=`mktemp -d /tmp/njs_test.XXXXXX` NJS_TEST_LOG_DEFAULT="$NJS_TEST_DIR/log.log" NJS_TEST_VERBOSE=${NJS_TEST_VERBOSE:-} From noreply at nginx.com Tue Apr 22 16:05:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 22 Apr 2025 16:05:02 +0000 (UTC) Subject: [nginx] Branch created: stable-1.28 Message-ID: <20250422160502.7F93648F92@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/6ac8b69f06bc10d5503f636da888fa70095b151c branches: stable-1.28 commit: 6ac8b69f06bc10d5503f636da888fa70095b151c user: Sergey Kandaurov date: Mon, 14 Apr 2025 22:35:27 +0400 description: nginx-1.27.5-RELEASE --- docs/xml/nginx/changes.xml | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml index b55177d80..ecb063d57 100644 --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,77 @@ + + + + +контроль перегрузки CUBIC в соединениях QUIC. + + +CUBIC congestion control in QUIC connections. + + + + + +ограничение на максимальный размер кешируемых в разделяемой памяти +SSL-сессий поднято до 8192. + + +the maximum size limit for SSL sessions cached in shared memory +has been raised to 8192. + + + + + +в директивах grpc_ssl_password_file, proxy_ssl_password_file и +uwsgi_ssl_password_file +при загрузке SSL-сертификатов и зашифрованных ключей из переменных; +ошибка появилась в 1.23.1. + + +in the "grpc_ssl_password_file", "proxy_ssl_password_file", and +"uwsgi_ssl_password_file" directives +when loading SSL certificates and encrypted keys from variables; +the bug had appeared in 1.23.1. + + + + + +в переменных $ssl_curve и $ssl_curves +при использовании подключаемых кривых в OpenSSL. + + +in the $ssl_curve and $ssl_curves variables +when using pluggable curves in OpenSSL. + + + + + +nginx не собирался с musl libc.
+Спасибо Piotr Sikora. +
+ +nginx could not be built with musl libc.
+Thanks to Piotr Sikora. +
+
+ + + +Улучшения производительности и исправления в HTTP/3. + + +Performance improvements and bugfixes in HTTP/3. + + + +
+ + From noreply at nginx.com Wed Apr 23 07:54:03 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 23 Apr 2025 07:54:03 +0000 (UTC) Subject: [nginx] QUIC: fixed a typo. Message-ID: <20250423075403.1DA5A4783D@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/9785db9bd504ff25c1d84857505e6546fc04ae68 branches: master commit: 9785db9bd504ff25c1d84857505e6546fc04ae68 user: nandsky date: Fri, 18 Apr 2025 11:45:12 +0800 description: QUIC: fixed a typo. --- src/event/quic/ngx_event_quic_ack.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c index b8b72e943..c7fd96c2c 100644 --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -22,7 +22,7 @@ /* CUBIC parameters x10 */ #define NGX_QUIC_CUBIC_BETA 7 -#define MGX_QUIC_CUBIC_C 4 +#define NGX_QUIC_CUBIC_C 4 /* send time of ACK'ed packets */ @@ -483,7 +483,7 @@ ngx_quic_congestion_cubic(ngx_connection_t *c) * w_cubic = C * (t_msec / 1000) ^ 3 * mtu + w_max */ - cc = 10000000000ll / (int64_t) cg->mtu / MGX_QUIC_CUBIC_C; + cc = 10000000000ll / (int64_t) cg->mtu / NGX_QUIC_CUBIC_C; w = t * t * t / cc + (int64_t) cg->w_max; if (w > NGX_MAX_SIZE_T_VALUE) { @@ -945,7 +945,7 @@ ngx_quic_congestion_cubic_time(ngx_connection_t *c) return 0; } - cc = 10000000000ll / (int64_t) cg->mtu / MGX_QUIC_CUBIC_C; + cc = 10000000000ll / (int64_t) cg->mtu / NGX_QUIC_CUBIC_C; v = (int64_t) (cg->w_max - cg->window) * cc; /* From noreply at nginx.com Wed Apr 23 11:49:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 23 Apr 2025 11:49:02 +0000 (UTC) Subject: [nginx] Stable branch. Message-ID: <20250423114902.90D1F4783E@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/f2aa4339a5877bfe8a346a090b1bdef00b20d521 branches: stable-1.28 commit: f2aa4339a5877bfe8a346a090b1bdef00b20d521 user: Sergey Kandaurov date: Tue, 22 Apr 2025 17:29:23 +0400 description: Stable branch. --- src/core/nginx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/nginx.h b/src/core/nginx.h index 090777853..4229012ba 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1027005 -#define NGINX_VERSION "1.27.5" +#define nginx_version 1028000 +#define NGINX_VERSION "1.28.0" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From noreply at nginx.com Wed Apr 23 11:49:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 23 Apr 2025 11:49:02 +0000 (UTC) Subject: [nginx] nginx-1.28.0-RELEASE Message-ID: <20250423114902.A73F747842@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/481d28cb4e04c8096b9b6134856891dc52ecc68f branches: stable-1.28 commit: 481d28cb4e04c8096b9b6134856891dc52ecc68f user: Sergey Kandaurov date: Tue, 22 Apr 2025 18:09:32 +0400 description: nginx-1.28.0-RELEASE --- docs/xml/nginx/changes.xml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml index ecb063d57..2af30d6d6 100644 --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,42 @@ + + + + +Стабильная ветка 1.28.x. + + +1.28.x stable branch. + + + + + +nginx не собирался gcc 15, +если использовались модули ngx_http_v2_module и ngx_http_v3_module. + + +nginx could not be built by gcc 15 +if ngx_http_v2_module or ngx_http_v3_module modules were used. + + + + + +nginx мог не собираться gcc 14 и новее с оптимизацией -O3 -flto, +если использовался модуль ngx_http_v3_module. + + +nginx might not be built by gcc 14 or newer with -O3 -flto optimization +if ngx_http_v3_module was used. + + + + + + From noreply at nginx.com Wed Apr 23 11:49:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 23 Apr 2025 11:49:02 +0000 (UTC) Subject: [nginx] HTTP/3: fixed NGX_HTTP_V3_VARLEN_INT_LEN value. Message-ID: <20250423114902.996F747841@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/55be5536a8fa4dba3ef687db2532ac96bd879b2b branches: stable-1.28 commit: 55be5536a8fa4dba3ef687db2532ac96bd879b2b user: Roman Arutyunyan date: Fri, 18 Apr 2025 11:16:57 +0400 description: HTTP/3: fixed NGX_HTTP_V3_VARLEN_INT_LEN value. After fixing ngx_http_v3_encode_varlen_int() in 400eb1b628, NGX_HTTP_V3_VARLEN_INT_LEN retained the old value of 4, which is insufficient for the values over 1073741823 (1G - 1). The NGX_HTTP_V3_VARLEN_INT_LEN macro is used in ngx_http_v3_uni.c to format stream and frame types. Old buffer size is enough for formatting this data. Also, the macro is used in ngx_http_v3_filter_module.c to format output chunks and trailers. Considering output_buffers and proxy_buffer_size are below 1G in all realistic scenarios, the old buffer size is enough here as well. --- src/http/v3/ngx_http_v3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http/v3/ngx_http_v3.h b/src/http/v3/ngx_http_v3.h index 9dcb5e6a7..8fd212c1f 100644 --- a/src/http/v3/ngx_http_v3.h +++ b/src/http/v3/ngx_http_v3.h @@ -23,7 +23,7 @@ #define NGX_HTTP_V3_HQ_ALPN_PROTO "\x0Ahq-interop" #define NGX_HTTP_V3_HQ_PROTO "hq-interop" -#define NGX_HTTP_V3_VARLEN_INT_LEN 4 +#define NGX_HTTP_V3_VARLEN_INT_LEN 8 #define NGX_HTTP_V3_PREFIX_INT_LEN 11 #define NGX_HTTP_V3_STREAM_CONTROL 0x00 From noreply at nginx.com Wed Apr 23 11:49:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 23 Apr 2025 11:49:02 +0000 (UTC) Subject: [nginx] Fixed -Wunterminated-string-initialization with gcc15. Message-ID: <20250423114902.952724783F@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/3a97c9616cfd7c4dd3a177cb2cb583301e80404c branches: stable-1.28 commit: 3a97c9616cfd7c4dd3a177cb2cb583301e80404c user: Roman Arutyunyan date: Wed, 16 Apr 2025 16:56:44 +0400 description: Fixed -Wunterminated-string-initialization with gcc15. --- src/event/quic/ngx_event_quic_protection.c | 12 +++++++----- src/http/v2/ngx_http_v2_filter_module.c | 7 ++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/event/quic/ngx_event_quic_protection.c b/src/event/quic/ngx_event_quic_protection.c index 3f249b36a..e5c0df7b4 100644 --- a/src/event/quic/ngx_event_quic_protection.c +++ b/src/event/quic/ngx_event_quic_protection.c @@ -125,9 +125,10 @@ ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys, ngx_str_t *secret, ngx_quic_secret_t *client, *server; ngx_quic_ciphers_t ciphers; - static const uint8_t salt[20] = - "\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17" - "\x9a\xe6\xa4\xc8\x0c\xad\xcc\xbb\x7f\x0a"; + static const uint8_t salt[20] = { + 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, + 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a + }; client = &keys->secrets[ssl_encryption_initial].client; server = &keys->secrets[ssl_encryption_initial].server; @@ -958,8 +959,9 @@ ngx_quic_create_retry_packet(ngx_quic_header_t *pkt, ngx_str_t *res) /* 5.8. Retry Packet Integrity */ static ngx_quic_md_t key = ngx_quic_md( "\xbe\x0c\x69\x0b\x9f\x66\x57\x5a\x1d\x76\x6b\x54\xe3\x68\xc8\x4e"); - static const u_char nonce[NGX_QUIC_IV_LEN] = - "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb"; + static const u_char nonce[NGX_QUIC_IV_LEN] = { + 0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb + }; static ngx_str_t in = ngx_string(""); ad.data = res->data; diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index 1e2cafaf1..b63e343a0 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -115,10 +115,11 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) ngx_http_core_srv_conf_t *cscf; u_char addr[NGX_SOCKADDR_STRLEN]; - static const u_char nginx[5] = "\x84\xaa\x63\x55\xe7"; + static const u_char nginx[5] = { 0x84, 0xaa, 0x63, 0x55, 0xe7 }; #if (NGX_HTTP_GZIP) - static const u_char accept_encoding[12] = - "\x8b\x84\x84\x2d\x69\x5b\x05\x44\x3c\x86\xaa\x6f"; + static const u_char accept_encoding[12] = { + 0x8b, 0x84, 0x84, 0x2d, 0x69, 0x5b, 0x05, 0x44, 0x3c, 0x86, 0xaa, 0x6f + }; #endif static size_t nginx_ver_len = ngx_http_v2_literal_size(NGINX_VER); From noreply at nginx.com Wed Apr 23 11:54:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 23 Apr 2025 11:54:02 +0000 (UTC) Subject: [nginx] Annotated tag created: release-1.28.0 Message-ID: <20250423115402.B3EF54783F@pubserv1.nginx> details: https://github.com/nginx/nginx/releases/tag/release-1.28.0 branches: commit: 481d28cb4e04c8096b9b6134856891dc52ecc68f user: Sergey Kandaurov date: Wed Apr 23 15:51:46 2025 +0400 description: release-1.28.0 tag From vl at inspert.ru Fri Apr 25 10:51:18 2025 From: vl at inspert.ru (Vladimir Homutov) Date: Fri, 25 Apr 2025 13:51:18 +0300 Subject: [nginx] QUIC: do not increase underutilized congestion window. In-Reply-To: <20250415150202.EBADF48F77@pubserv1.nginx> References: <20250415150202.EBADF48F77@pubserv1.nginx> Message-ID: On Tue, Apr 15, 2025 at 03:02:02PM +0000, noreply at nginx.com wrote: > details: https://github.com/nginx/nginx/commit/cd5e4fa1446dff86fafc3b6ffcc11afd527a024f > branches: master > commit: cd5e4fa1446dff86fafc3b6ffcc11afd527a024f > user: Roman Arutyunyan > date: Sat, 4 Jan 2025 18:03:46 +0400 > description: > QUIC: do not increase underutilized congestion window. > > As per RFC 9002, Section 7.8, congestion window should not be increased > when it's underutilized. > Hello, it looks like this patch triggers some issues with ack processing (possible previously, but now more probable): see details in suggested patch. I'm also attaching bad.log and good.log. The first one demonstrates that nginx is not sending any ACKs since it is switched into idle mode and the window is not increasing. Since the client code is symmetric, deadlock occurs. From vl at inspert.ru Fri Apr 25 10:55:11 2025 From: vl at inspert.ru (Vladimir Homutov) Date: Fri, 25 Apr 2025 13:55:11 +0300 Subject: [nginx] QUIC: do not increase underutilized congestion window. In-Reply-To: References: <20250415150202.EBADF48F77@pubserv1.nginx> Message-ID: missing attachments -------------- next part -------------- commit 0c7c9d6732a5fe3a3208286c8904db1851ac2cba Author: Vladimir Homutov Date: Fri Apr 25 13:35:00 2025 +0300 QUIC: fixed possible deadlock with ACKs not sent due to congestion. The commit cd5e4fa1446dff86fafc3b6ffcc11afd527a024f (QUIC: do not increase underutilized congestion window) lead to increased possibility of deadlock, caused by the fact that quic does not output any packets in congestion. If both client and server follow the same logic, it is possible that both ends are in the same state: waiting for ACKs to increase window, while being unable to send even ACK to unblock the other side. Since packets that contain ACK frames only are not congestion controlled, we are definitely allowed to send them, since we also need to respect the max_ack_delay. Currently, the max_ack_delay may be triggered and push handler is called, but the output does not send anything, because window is closed, thus nothing is sent. The patch allows to send ACK-only packets in case when the window is closed. Probably, this needs to be attached to the actual trigger of max_ack_delay timer, but it looks like suggested changes is goed enough for practical reasons. Also, RFC 9000 13.2.1 says: Since packets containing only ACK frames are not congestion controlled, an endpoint MUST NOT send more than one such packet in response to receiving an ack-eliciting packet. Probably, this also needs to be accounted. diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c index a92a539f3..4e51518c0 100644 --- a/src/event/quic/ngx_event_quic_output.c +++ b/src/event/quic/ngx_event_quic_output.c @@ -55,7 +55,8 @@ static ssize_t ngx_quic_send_segments(ngx_connection_t *c, u_char *buf, size_t len, struct sockaddr *sockaddr, socklen_t socklen, size_t segment); #endif static ssize_t ngx_quic_output_packet(ngx_connection_t *c, - ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min); + ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min, + ngx_uint_t ack_only); static void ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, ngx_quic_header_t *pkt, ngx_quic_path_t *path); static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); @@ -116,7 +117,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c) ssize_t n; u_char *p; uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST]; - ngx_uint_t i, pad; + ngx_uint_t i, pad, ack_only; ngx_quic_path_t *path; ngx_quic_send_ctx_t *ctx; ngx_quic_congestion_t *cg; @@ -131,7 +132,9 @@ ngx_quic_create_datagrams(ngx_connection_t *c) ngx_memzero(preserved_pnum, sizeof(preserved_pnum)); #endif - while (cg->in_flight < cg->window) { + ack_only = (cg->in_flight >= cg->window); + + while ((cg->in_flight < cg->window) || ack_only) { p = dst; @@ -158,7 +161,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c) return NGX_OK; } - n = ngx_quic_output_packet(c, ctx, p, len, min); + n = ngx_quic_output_packet(c, ctx, p, len, min, ack_only); if (n == NGX_ERROR) { return NGX_ERROR; } @@ -186,6 +189,9 @@ ngx_quic_create_datagrams(ngx_connection_t *c) ngx_quic_commit_send(c); + /* send pure acks just once */ + ack_only = 0; + path->sent += len; } @@ -331,7 +337,7 @@ ngx_quic_create_segments(ngx_connection_t *c) size_t len, segsize; ssize_t n; u_char *p, *end; - ngx_uint_t nseg, level; + ngx_uint_t nseg, level, ack_only; ngx_quic_path_t *path; ngx_quic_send_ctx_t *ctx; ngx_quic_congestion_t *cg; @@ -358,13 +364,15 @@ ngx_quic_create_segments(ngx_connection_t *c) level = ctx - qc->send_ctx; preserved_pnum[level] = ctx->pnum; + ack_only = (cg->in_flight >= cg->window); + for ( ;; ) { len = ngx_min(segsize, (size_t) (end - p)); - if (len && cg->in_flight + (p - dst) < cg->window) { + if (len && ((cg->in_flight + (p - dst) < cg->window) || ack_only)) { - n = ngx_quic_output_packet(c, ctx, p, len, len); + n = ngx_quic_output_packet(c, ctx, p, len, len, ack_only); if (n == NGX_ERROR) { return NGX_ERROR; } @@ -397,6 +405,9 @@ ngx_quic_create_segments(ngx_connection_t *c) ngx_quic_commit_send(c); + /* send pure acks just once */ + ack_only = 0; + path->sent += n; p = dst; @@ -521,7 +532,7 @@ ngx_quic_get_padding_level(ngx_connection_t *c) static ssize_t ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, - u_char *data, size_t max, size_t min) + u_char *data, size_t max, size_t min, ngx_uint_t ack_only) { size_t len, pad, min_payload, max_payload; u_char *p; @@ -589,6 +600,12 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, break; } + if (ack_only + && (f->type != NGX_QUIC_FT_ACK && f->type != NGX_QUIC_FT_ACK_ECN)) + { + continue; + } + if (len + f->len > max_payload) { rc = ngx_quic_split_frame(c, f, max_payload - len); -------------- next part -------------- A non-text attachment was scrubbed... Name: logs_info.tar.gz Type: application/gzip Size: 24054 bytes Desc: not available URL: From noreply at nginx.com Fri Apr 25 10:57:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Fri, 25 Apr 2025 10:57:02 +0000 (UTC) Subject: [nginx] SSL: fixed build with OPENSSL_NO_DEPRECATED. Message-ID: <20250425105702.690DD478D5@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/4f8bc0b282b976eb7d044c81cad06e7e6d64e5ff branches: master commit: 4f8bc0b282b976eb7d044c81cad06e7e6d64e5ff user: Sergey Kandaurov date: Wed, 16 Apr 2025 20:50:29 +0400 description: SSL: fixed build with OPENSSL_NO_DEPRECATED. --- src/event/ngx_event_openssl.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index b7aaaca75..9ba21a810 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -83,6 +83,17 @@ #endif +#ifdef OPENSSL_NO_DEPRECATED_3_4 +#define SSL_SESSION_get_time(s) SSL_SESSION_get_time_ex(s) +#define SSL_SESSION_set_time(s, t) SSL_SESSION_set_time_ex(s, t) +#endif + + +#ifdef OPENSSL_NO_DEPRECATED_3_0 +#define EVP_CIPHER_CTX_cipher(c) EVP_CIPHER_CTX_get0_cipher(c) +#endif + + typedef struct ngx_ssl_ocsp_s ngx_ssl_ocsp_t; From noreply at nginx.com Fri Apr 25 10:57:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Fri, 25 Apr 2025 10:57:02 +0000 (UTC) Subject: [nginx] SSL: fixed build with OPENSSL_NO_DH. Message-ID: <20250425105702.6E2AF478E9@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/adda7041582d8565ee1e5e7dfe740db85398e1ce branches: master commit: adda7041582d8565ee1e5e7dfe740db85398e1ce user: Sergey Kandaurov date: Wed, 16 Apr 2025 20:58:57 +0400 description: SSL: fixed build with OPENSSL_NO_DH. --- src/event/ngx_event_openssl.c | 4 ++++ src/event/ngx_event_openssl.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 6992cc4a4..7eb05209d 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1315,6 +1315,8 @@ ngx_ssl_passwords_cleanup(void *data) ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) { +#ifndef OPENSSL_NO_DH + BIO *bio; if (file->len == 0) { @@ -1385,6 +1387,8 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) BIO_free(bio); +#endif + return NGX_OK; } diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index 9ba21a810..d4a62b82a 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -19,7 +19,9 @@ #include #include #include +#ifndef OPENSSL_NO_DH #include +#endif #ifndef OPENSSL_NO_ENGINE #include #endif From arut at nginx.com Fri Apr 25 11:29:13 2025 From: arut at nginx.com (Roman Arutyunyan) Date: Fri, 25 Apr 2025 15:29:13 +0400 Subject: [nginx] QUIC: do not increase underutilized congestion window. In-Reply-To: References: <20250415150202.EBADF48F77@pubserv1.nginx> Message-ID: <20250425112913.nxpwbtr6mn3olaxg@N00W24XTQX> Hi Vladimir, Thanks for your patch, I will look into this. The issue indeed seems possible and needs to be addressed. The mentiobned change cd5e4fa14 is correct though since without it CWND used to skyrocket while being underutilized. And this certainly consealed other issues. Do you have a reliable way to trigger this? On Fri, Apr 25, 2025 at 01:55:11PM +0300, Vladimir Homutov via nginx-devel wrote: > missing attachments > > commit 0c7c9d6732a5fe3a3208286c8904db1851ac2cba > Author: Vladimir Homutov > Date: Fri Apr 25 13:35:00 2025 +0300 > > QUIC: fixed possible deadlock with ACKs not sent due to congestion. > > The commit cd5e4fa1446dff86fafc3b6ffcc11afd527a024f (QUIC: do not increase > underutilized congestion window) lead to increased possibility of deadlock, > caused by the fact that quic does not output any packets in congestion. > > If both client and server follow the same logic, it is possible that both > ends are in the same state: waiting for ACKs to increase window, while > being unable to send even ACK to unblock the other side. > > Since packets that contain ACK frames only are not congestion controlled, > we are definitely allowed to send them, since we also need to respect > the max_ack_delay. Currently, the max_ack_delay may be triggered and > push handler is called, but the output does not send anything, because > window is closed, thus nothing is sent. > > The patch allows to send ACK-only packets in case when the window is closed. > Probably, this needs to be attached to the actual trigger of max_ack_delay > timer, but it looks like suggested changes is goed enough for practical reasons. > > Also, RFC 9000 13.2.1 says: > Since packets containing only ACK frames are not congestion controlled, > an endpoint MUST NOT send more than one such packet in response to > receiving an ack-eliciting packet. > > Probably, this also needs to be accounted. > > diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c > index a92a539f3..4e51518c0 100644 > --- a/src/event/quic/ngx_event_quic_output.c > +++ b/src/event/quic/ngx_event_quic_output.c > @@ -55,7 +55,8 @@ static ssize_t ngx_quic_send_segments(ngx_connection_t *c, u_char *buf, > size_t len, struct sockaddr *sockaddr, socklen_t socklen, size_t segment); > #endif > static ssize_t ngx_quic_output_packet(ngx_connection_t *c, > - ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min); > + ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min, > + ngx_uint_t ack_only); > static void ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, > ngx_quic_header_t *pkt, ngx_quic_path_t *path); > static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); > @@ -116,7 +117,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c) > ssize_t n; > u_char *p; > uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST]; > - ngx_uint_t i, pad; > + ngx_uint_t i, pad, ack_only; > ngx_quic_path_t *path; > ngx_quic_send_ctx_t *ctx; > ngx_quic_congestion_t *cg; > @@ -131,7 +132,9 @@ ngx_quic_create_datagrams(ngx_connection_t *c) > ngx_memzero(preserved_pnum, sizeof(preserved_pnum)); > #endif > > - while (cg->in_flight < cg->window) { > + ack_only = (cg->in_flight >= cg->window); > + > + while ((cg->in_flight < cg->window) || ack_only) { > > p = dst; > > @@ -158,7 +161,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c) > return NGX_OK; > } > > - n = ngx_quic_output_packet(c, ctx, p, len, min); > + n = ngx_quic_output_packet(c, ctx, p, len, min, ack_only); > if (n == NGX_ERROR) { > return NGX_ERROR; > } > @@ -186,6 +189,9 @@ ngx_quic_create_datagrams(ngx_connection_t *c) > > ngx_quic_commit_send(c); > > + /* send pure acks just once */ > + ack_only = 0; > + > path->sent += len; > } > > @@ -331,7 +337,7 @@ ngx_quic_create_segments(ngx_connection_t *c) > size_t len, segsize; > ssize_t n; > u_char *p, *end; > - ngx_uint_t nseg, level; > + ngx_uint_t nseg, level, ack_only; > ngx_quic_path_t *path; > ngx_quic_send_ctx_t *ctx; > ngx_quic_congestion_t *cg; > @@ -358,13 +364,15 @@ ngx_quic_create_segments(ngx_connection_t *c) > level = ctx - qc->send_ctx; > preserved_pnum[level] = ctx->pnum; > > + ack_only = (cg->in_flight >= cg->window); > + > for ( ;; ) { > > len = ngx_min(segsize, (size_t) (end - p)); > > - if (len && cg->in_flight + (p - dst) < cg->window) { > + if (len && ((cg->in_flight + (p - dst) < cg->window) || ack_only)) { > > - n = ngx_quic_output_packet(c, ctx, p, len, len); > + n = ngx_quic_output_packet(c, ctx, p, len, len, ack_only); > if (n == NGX_ERROR) { > return NGX_ERROR; > } > @@ -397,6 +405,9 @@ ngx_quic_create_segments(ngx_connection_t *c) > > ngx_quic_commit_send(c); > > + /* send pure acks just once */ > + ack_only = 0; > + > path->sent += n; > > p = dst; > @@ -521,7 +532,7 @@ ngx_quic_get_padding_level(ngx_connection_t *c) > > static ssize_t > ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, > - u_char *data, size_t max, size_t min) > + u_char *data, size_t max, size_t min, ngx_uint_t ack_only) > { > size_t len, pad, min_payload, max_payload; > u_char *p; > @@ -589,6 +600,12 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, > break; > } > > + if (ack_only > + && (f->type != NGX_QUIC_FT_ACK && f->type != NGX_QUIC_FT_ACK_ECN)) > + { > + continue; > + } > + > if (len + f->len > max_payload) { > rc = ngx_quic_split_frame(c, f, max_payload - len); > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel -- Roman From vl at inspert.ru Fri Apr 25 12:19:23 2025 From: vl at inspert.ru (Vladimir Homutov) Date: Fri, 25 Apr 2025 15:19:23 +0300 Subject: [nginx] QUIC: do not increase underutilized congestion window. In-Reply-To: <20250425112913.nxpwbtr6mn3olaxg@N00W24XTQX> References: <20250415150202.EBADF48F77@pubserv1.nginx> <20250425112913.nxpwbtr6mn3olaxg@N00W24XTQX> Message-ID: <4fea1847-ab27-4751-9fbd-3b356f638031@inspert.ru> On 4/25/25 2:29 PM, Roman Arutyunyan wrote: > Hi Vladimir, > > Thanks for your patch, I will look into this. The issue indeed seems possible > and needs to be addressed. The mentiobned change cd5e4fa14 is correct though > since without it CWND used to skyrocket while being underutilized. And this > certainly consealed other issues. > > Do you have a reliable way to trigger this? Yes, I'm able to trigger this reliably with angie as a client (with cd5e4fa14 merged both on client and server). > > On Fri, Apr 25, 2025 at 01:55:11PM +0300, Vladimir Homutov via nginx-devel wrote: >> missing attachments >> >> commit 0c7c9d6732a5fe3a3208286c8904db1851ac2cba >> Author: Vladimir Homutov >> Date: Fri Apr 25 13:35:00 2025 +0300 >> >> QUIC: fixed possible deadlock with ACKs not sent due to congestion. >> >> The commit cd5e4fa1446dff86fafc3b6ffcc11afd527a024f (QUIC: do not increase >> underutilized congestion window) lead to increased possibility of deadlock, >> caused by the fact that quic does not output any packets in congestion. >> >> If both client and server follow the same logic, it is possible that both >> ends are in the same state: waiting for ACKs to increase window, while >> being unable to send even ACK to unblock the other side. >> >> Since packets that contain ACK frames only are not congestion controlled, >> we are definitely allowed to send them, since we also need to respect >> the max_ack_delay. Currently, the max_ack_delay may be triggered and >> push handler is called, but the output does not send anything, because >> window is closed, thus nothing is sent. >> >> The patch allows to send ACK-only packets in case when the window is closed. >> Probably, this needs to be attached to the actual trigger of max_ack_delay >> timer, but it looks like suggested changes is goed enough for practical reasons. >> >> Also, RFC 9000 13.2.1 says: >> Since packets containing only ACK frames are not congestion controlled, >> an endpoint MUST NOT send more than one such packet in response to >> receiving an ack-eliciting packet. >> >> Probably, this also needs to be accounted. >> >> diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c >> index a92a539f3..4e51518c0 100644 >> --- a/src/event/quic/ngx_event_quic_output.c >> +++ b/src/event/quic/ngx_event_quic_output.c >> @@ -55,7 +55,8 @@ static ssize_t ngx_quic_send_segments(ngx_connection_t *c, u_char *buf, >> size_t len, struct sockaddr *sockaddr, socklen_t socklen, size_t segment); >> #endif >> static ssize_t ngx_quic_output_packet(ngx_connection_t *c, >> - ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min); >> + ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min, >> + ngx_uint_t ack_only); >> static void ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, >> ngx_quic_header_t *pkt, ngx_quic_path_t *path); >> static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); >> @@ -116,7 +117,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c) >> ssize_t n; >> u_char *p; >> uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST]; >> - ngx_uint_t i, pad; >> + ngx_uint_t i, pad, ack_only; >> ngx_quic_path_t *path; >> ngx_quic_send_ctx_t *ctx; >> ngx_quic_congestion_t *cg; >> @@ -131,7 +132,9 @@ ngx_quic_create_datagrams(ngx_connection_t *c) >> ngx_memzero(preserved_pnum, sizeof(preserved_pnum)); >> #endif >> >> - while (cg->in_flight < cg->window) { >> + ack_only = (cg->in_flight >= cg->window); >> + >> + while ((cg->in_flight < cg->window) || ack_only) { >> >> p = dst; >> >> @@ -158,7 +161,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c) >> return NGX_OK; >> } >> >> - n = ngx_quic_output_packet(c, ctx, p, len, min); >> + n = ngx_quic_output_packet(c, ctx, p, len, min, ack_only); >> if (n == NGX_ERROR) { >> return NGX_ERROR; >> } >> @@ -186,6 +189,9 @@ ngx_quic_create_datagrams(ngx_connection_t *c) >> >> ngx_quic_commit_send(c); >> >> + /* send pure acks just once */ >> + ack_only = 0; >> + >> path->sent += len; >> } >> >> @@ -331,7 +337,7 @@ ngx_quic_create_segments(ngx_connection_t *c) >> size_t len, segsize; >> ssize_t n; >> u_char *p, *end; >> - ngx_uint_t nseg, level; >> + ngx_uint_t nseg, level, ack_only; >> ngx_quic_path_t *path; >> ngx_quic_send_ctx_t *ctx; >> ngx_quic_congestion_t *cg; >> @@ -358,13 +364,15 @@ ngx_quic_create_segments(ngx_connection_t *c) >> level = ctx - qc->send_ctx; >> preserved_pnum[level] = ctx->pnum; >> >> + ack_only = (cg->in_flight >= cg->window); >> + >> for ( ;; ) { >> >> len = ngx_min(segsize, (size_t) (end - p)); >> >> - if (len && cg->in_flight + (p - dst) < cg->window) { >> + if (len && ((cg->in_flight + (p - dst) < cg->window) || ack_only)) { >> >> - n = ngx_quic_output_packet(c, ctx, p, len, len); >> + n = ngx_quic_output_packet(c, ctx, p, len, len, ack_only); >> if (n == NGX_ERROR) { >> return NGX_ERROR; >> } >> @@ -397,6 +405,9 @@ ngx_quic_create_segments(ngx_connection_t *c) >> >> ngx_quic_commit_send(c); >> >> + /* send pure acks just once */ >> + ack_only = 0; >> + >> path->sent += n; >> >> p = dst; >> @@ -521,7 +532,7 @@ ngx_quic_get_padding_level(ngx_connection_t *c) >> >> static ssize_t >> ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, >> - u_char *data, size_t max, size_t min) >> + u_char *data, size_t max, size_t min, ngx_uint_t ack_only) >> { >> size_t len, pad, min_payload, max_payload; >> u_char *p; >> @@ -589,6 +600,12 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, >> break; >> } >> >> + if (ack_only >> + && (f->type != NGX_QUIC_FT_ACK && f->type != NGX_QUIC_FT_ACK_ECN)) >> + { >> + continue; >> + } >> + >> if (len + f->len > max_payload) { >> rc = ngx_quic_split_frame(c, f, max_payload - len); >> > >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> https://mailman.nginx.org/mailman/listinfo/nginx-devel > > -- > Roman -------------- next part -------------- An HTML attachment was scrubbed... URL: From pluknet at nginx.com Fri Apr 25 13:42:59 2025 From: pluknet at nginx.com (Sergey Kandaurov) Date: Fri, 25 Apr 2025 17:42:59 +0400 Subject: [nginx] QUIC: do not increase underutilized congestion window. In-Reply-To: References: <20250415150202.EBADF48F77@pubserv1.nginx> Message-ID: <52BAA7AB-B53F-47BA-831F-7227BBFA8E51@nginx.com> > On 25 Apr 2025, at 14:51, Vladimir Homutov via nginx-devel wrote: > > On Tue, Apr 15, 2025 at 03:02:02PM +0000, noreply at nginx.com wrote: >> details: https://github.com/nginx/nginx/commit/cd5e4fa1446dff86fafc3b6ffcc11afd527a024f >> branches: master >> commit: cd5e4fa1446dff86fafc3b6ffcc11afd527a024f >> user: Roman Arutyunyan >> date: Sat, 4 Jan 2025 18:03:46 +0400 >> description: >> QUIC: do not increase underutilized congestion window. >> >> As per RFC 9002, Section 7.8, congestion window should not be increased >> when it's underutilized. >> > > Hello, > > it looks like this patch triggers some issues with ack processing > (possible previously, but now more probable): see details in suggested > patch. > > I'm also attaching bad.log and good.log. The first one demonstrates that > nginx is not sending any ACKs since it is switched into idle mode and > the window is not increasing. Since the client code is symmetric, deadlock > occurs. cd5e4fa14 is not the only one to blame uncovering this apparently old bug. Few more things to consider: - 53e7e9eb5 initial congestion window reduction made this easier to trigger - a40cc7002 to ignore congestion in MTU probes made this easier to trigger The fix is to teach ngx_quic_output() to send ACKs on congested links. This meets RFC 9002, 7 and B.2 : An endpoint MUST NOT send a packet if it would cause bytes_in_flight : (see Appendix B.2) to be larger than the congestion window : bytes_in_flight: : Packets only containing ACK frames do not count toward : bytes_in_flight to ensure congestion control does not impede : congestion feedback. A simple reproducer attached. -------------- next part -------------- A non-text attachment was scrubbed... Name: h3_congestion_ack.t Type: application/octet-stream Size: 2056 bytes Desc: not available URL: -------------- next part -------------- -- Sergey Kandaurov From pluknet at nginx.com Fri Apr 25 13:50:15 2025 From: pluknet at nginx.com (Sergey Kandaurov) Date: Fri, 25 Apr 2025 17:50:15 +0400 Subject: [nginx] QUIC: do not increase underutilized congestion window. In-Reply-To: <52BAA7AB-B53F-47BA-831F-7227BBFA8E51@nginx.com> References: <20250415150202.EBADF48F77@pubserv1.nginx> <52BAA7AB-B53F-47BA-831F-7227BBFA8E51@nginx.com> Message-ID: On Fri, Apr 25, 2025 at 05:42:59PM +0400, Sergey Kandaurov wrote: > > [...] > > A simple reproducer attached. Forgotten lib changes. diff --git a/lib/Test/Nginx/HTTP3.pm b/lib/Test/Nginx/HTTP3.pm index 5cc8903..de7134f 100644 --- a/lib/Test/Nginx/HTTP3.pm +++ b/lib/Test/Nginx/HTTP3.pm @@ -43,6 +43,7 @@ sub new { $self->{token} = $extra{token} || ''; $self->{psk_list} = $extra{psk_list} || []; $self->{early_data} = $extra{early_data}; + $self->{send_ack} = 1; $self->{sni} = exists $extra{sni} ? $extra{sni} : 'localhost'; $self->{cipher} = 0x1301; @@ -1570,7 +1571,8 @@ sub handle_frames { } } - $self->{socket}->syswrite($self->encrypt_aead(build_ack($ack), $level)); + $self->{socket}->syswrite($self->encrypt_aead(build_ack($ack), $level)) + if $self->{send_ack}; for my $pn (keys %$ack) { $ack->{$pn} = $self->{pn}[0][$level] if $ack->{$pn} == -1; From pluknet at nginx.com Fri Apr 25 18:51:12 2025 From: pluknet at nginx.com (Sergey Kandaurov) Date: Fri, 25 Apr 2025 22:51:12 +0400 Subject: [nginx] QUIC: do not increase underutilized congestion window. In-Reply-To: References: <20250415150202.EBADF48F77@pubserv1.nginx> Message-ID: On Fri, Apr 25, 2025 at 01:55:11PM +0300, Vladimir Homutov via nginx-devel wrote: > missing attachments > Thanks for the provided debug, it is really helpful. Looking into debug, it becomes clear that once we sent something (be it a large response or MTU probe) that temporarily exceeds the congestion window (which is permitted for MTU probes), we can no longer send acknowledgments. This is especially visible if we don't receive ACKs for some reason, such as in your case, to decrease our inflight counter, so the connection becomes stalled. Below is a fix I have made without looking into your version (no offense, it is purely for aesthetic reasons). Although it appears to be quite similar to yours, it's somewhat less intrusive. I tried not to break sending segments for exceeded congestion, as well as to send correct frames in the ack_only mode. diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c index a92a539f3..3fc2091e0 100644 --- a/src/event/quic/ngx_event_quic_output.c +++ b/src/event/quic/ngx_event_quic_output.c @@ -55,7 +55,8 @@ static ssize_t ngx_quic_send_segments(ngx_connection_t *c, u_char *buf, size_t len, struct sockaddr *sockaddr, socklen_t socklen, size_t segment); #endif static ssize_t ngx_quic_output_packet(ngx_connection_t *c, - ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min); + ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min, + ngx_int_t ack_only); static void ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, ngx_quic_header_t *pkt, ngx_quic_path_t *path); static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); @@ -131,8 +132,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c) ngx_memzero(preserved_pnum, sizeof(preserved_pnum)); #endif - while (cg->in_flight < cg->window) { - + do { p = dst; len = ngx_quic_path_limit(c, path, path->mtu); @@ -158,7 +158,8 @@ ngx_quic_create_datagrams(ngx_connection_t *c) return NGX_OK; } - n = ngx_quic_output_packet(c, ctx, p, len, min); + n = ngx_quic_output_packet(c, ctx, p, len, min, + cg->in_flight >= cg->window); if (n == NGX_ERROR) { return NGX_ERROR; } @@ -187,7 +188,8 @@ ngx_quic_create_datagrams(ngx_connection_t *c) ngx_quic_commit_send(c); path->sent += len; - } + + } while (cg->in_flight < cg->window); return NGX_OK; } @@ -315,6 +317,10 @@ ngx_quic_allow_segmentation(ngx_connection_t *c) bytes += f->len; + if (qc->congestion->in_flight + bytes >= qc->congestion->window)) { + return 0; + } + if (bytes > len * 3) { /* require at least ~3 full packets to batch */ return 1; @@ -364,7 +370,7 @@ ngx_quic_create_segments(ngx_connection_t *c) if (len && cg->in_flight + (p - dst) < cg->window) { - n = ngx_quic_output_packet(c, ctx, p, len, len); + n = ngx_quic_output_packet(c, ctx, p, len, len, 0); if (n == NGX_ERROR) { return NGX_ERROR; } @@ -521,7 +527,7 @@ ngx_quic_get_padding_level(ngx_connection_t *c) static ssize_t ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, - u_char *data, size_t max, size_t min) + u_char *data, size_t max, size_t min, ngx_int_t ack_only) { size_t len, pad, min_payload, max_payload; u_char *p; @@ -585,6 +591,10 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, { f = ngx_queue_data(q, ngx_quic_frame_t, queue); + if (ack_only && f->type != NGX_QUIC_FT_ACK) { + continue; + } + if (len >= max_payload) { break; } @@ -651,14 +661,20 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, f->plen = res.len; } - while (nframes--) { + while (nframes) { q = ngx_queue_head(&ctx->frames); f = ngx_queue_data(q, ngx_quic_frame_t, queue); + if (ack_only && f->type != NGX_QUIC_FT_ACK) { + continue; + } + f->pkt_need_ack = pkt.need_ack; ngx_queue_remove(q); ngx_queue_insert_tail(&ctx->sending, q); + + nframes--; } return res.len; From pluknet at nginx.com Sat Apr 26 08:13:31 2025 From: pluknet at nginx.com (Sergey Kandaurov) Date: Sat, 26 Apr 2025 12:13:31 +0400 Subject: [nginx] QUIC: do not increase underutilized congestion window. In-Reply-To: References: <20250415150202.EBADF48F77@pubserv1.nginx> Message-ID: <8D0A5E8C-A438-4033-BF29-A992CF439316@nginx.com> > On 25 Apr 2025, at 22:51, Sergey Kandaurov wrote: > > On Fri, Apr 25, 2025 at 01:55:11PM +0300, Vladimir Homutov via nginx-devel wrote: >> missing attachments >> > [..] A compile tested version is uploaded at https://github.com/nginx/nginx/pull/655 (attached for convenience). Besides, it has fixed generalization to obey the abstraction layer. -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-QUIC-fixed-sending-acknowledgments-with-limited-cong.patch Type: application/octet-stream Size: 5159 bytes Desc: not available URL: -------------- next part -------------- -- Sergey Kandaurov From vl at inspert.ru Mon Apr 28 09:07:40 2025 From: vl at inspert.ru (Vladimir Homutov) Date: Mon, 28 Apr 2025 12:07:40 +0300 Subject: [nginx] QUIC: do not increase underutilized congestion window. In-Reply-To: References: <20250415150202.EBADF48F77@pubserv1.nginx> Message-ID: On Fri, Apr 25, 2025 at 10:51:12PM +0400, Sergey Kandaurov wrote: > On Fri, Apr 25, 2025 at 01:55:11PM +0300, Vladimir Homutov via nginx-devel wrote: > > missing attachments > > > > Thanks for the provided debug, it is really helpful. > > Looking into debug, it becomes clear that once we sent something > (be it a large response or MTU probe) that temporarily exceeds > the congestion window (which is permitted for MTU probes), > we can no longer send acknowledgments. > > This is especially visible if we don't receive ACKs for some reason, > such as in your case, > to decrease our inflight counter, so the connection becomes stalled. > > Below is a fix I have made without looking into your version > (no offense, it is purely for aesthetic reasons). > > Although it appears to be quite similar to yours, it's somewhat less > intrusive. I tried not to break sending segments for exceeded > congestion, as well as to send correct frames in the ack_only mode. indeed, my patch misses the part about queue management, this is required part. I'm agree regarding segmentation - sending pure ACK is definitely not the case for optimizations; otherwise, looks good for me. > > > diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c > index a92a539f3..3fc2091e0 100644 > --- a/src/event/quic/ngx_event_quic_output.c > +++ b/src/event/quic/ngx_event_quic_output.c > @@ -55,7 +55,8 @@ static ssize_t ngx_quic_send_segments(ngx_connection_t *c, u_char *buf, > size_t len, struct sockaddr *sockaddr, socklen_t socklen, size_t segment); > #endif > static ssize_t ngx_quic_output_packet(ngx_connection_t *c, > - ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min); > + ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min, > + ngx_int_t ack_only); > static void ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, > ngx_quic_header_t *pkt, ngx_quic_path_t *path); > static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); > @@ -131,8 +132,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c) > ngx_memzero(preserved_pnum, sizeof(preserved_pnum)); > #endif > > - while (cg->in_flight < cg->window) { > - > + do { > p = dst; > > len = ngx_quic_path_limit(c, path, path->mtu); > @@ -158,7 +158,8 @@ ngx_quic_create_datagrams(ngx_connection_t *c) > return NGX_OK; > } > > - n = ngx_quic_output_packet(c, ctx, p, len, min); > + n = ngx_quic_output_packet(c, ctx, p, len, min, > + cg->in_flight >= cg->window); > if (n == NGX_ERROR) { > return NGX_ERROR; > } > @@ -187,7 +188,8 @@ ngx_quic_create_datagrams(ngx_connection_t *c) > ngx_quic_commit_send(c); > > path->sent += len; > - } > + > + } while (cg->in_flight < cg->window); > > return NGX_OK; > } > @@ -315,6 +317,10 @@ ngx_quic_allow_segmentation(ngx_connection_t *c) > > bytes += f->len; > > + if (qc->congestion->in_flight + bytes >= qc->congestion->window)) { > + return 0; > + } > + > if (bytes > len * 3) { > /* require at least ~3 full packets to batch */ > return 1; > @@ -364,7 +370,7 @@ ngx_quic_create_segments(ngx_connection_t *c) > > if (len && cg->in_flight + (p - dst) < cg->window) { > > - n = ngx_quic_output_packet(c, ctx, p, len, len); > + n = ngx_quic_output_packet(c, ctx, p, len, len, 0); > if (n == NGX_ERROR) { > return NGX_ERROR; > } > @@ -521,7 +527,7 @@ ngx_quic_get_padding_level(ngx_connection_t *c) > > static ssize_t > ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, > - u_char *data, size_t max, size_t min) > + u_char *data, size_t max, size_t min, ngx_int_t ack_only) > { > size_t len, pad, min_payload, max_payload; > u_char *p; > @@ -585,6 +591,10 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, > { > f = ngx_queue_data(q, ngx_quic_frame_t, queue); > > + if (ack_only && f->type != NGX_QUIC_FT_ACK) { > + continue; > + } > + > if (len >= max_payload) { > break; > } > @@ -651,14 +661,20 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, > f->plen = res.len; > } > > - while (nframes--) { > + while (nframes) { > q = ngx_queue_head(&ctx->frames); > f = ngx_queue_data(q, ngx_quic_frame_t, queue); > > + if (ack_only && f->type != NGX_QUIC_FT_ACK) { > + continue; > + } > + > f->pkt_need_ack = pkt.need_ack; > > ngx_queue_remove(q); > ngx_queue_insert_tail(&ctx->sending, q); > + > + nframes--; > } > > return res.len; From noreply at nginx.com Tue Apr 29 15:54:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Tue, 29 Apr 2025 15:54:02 +0000 (UTC) Subject: [nginx] QUIC: do not block ACKs by congestion control. Message-ID: <20250429155402.179DD47E7B@pubserv1.nginx> details: https://github.com/nginx/nginx/commit/f3542500b6d74e3e88fc84b88144afe67882d1fa branches: master commit: f3542500b6d74e3e88fc84b88144afe67882d1fa user: Sergey Kandaurov date: Fri, 25 Apr 2025 23:32:24 +0400 description: QUIC: do not block ACKs by congestion control. Previously, it was not possible to send acknowledgments if the congestion window was limited or temporarily exceeded, such as after sending a large response or MTU probe. If ACKs were not received from the peer for some reason to update the in-flight bytes counter below the congestion window, this might result in a stalled connection. The fix is to send ACKs regardless of congestion control. This meets RFC 9002, Section 7: : Similar to TCP, packets containing only ACK frames do not count : toward bytes in flight and are not congestion controlled. This is a simplified implementation to send ACK frames from the head of the queue. This was made possible after 6f5f17358. Reported in trac ticket #2621 and subsequently by Vladimir Homutov: https://mailman.nginx.org/pipermail/nginx-devel/2025-April/ZKBAWRJVQXSZ2ISG3YJAF3EWMDRDHCMO.html --- src/event/quic/ngx_event_quic_output.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c index a92a539f3..01f1f9113 100644 --- a/src/event/quic/ngx_event_quic_output.c +++ b/src/event/quic/ngx_event_quic_output.c @@ -55,7 +55,8 @@ static ssize_t ngx_quic_send_segments(ngx_connection_t *c, u_char *buf, size_t len, struct sockaddr *sockaddr, socklen_t socklen, size_t segment); #endif static ssize_t ngx_quic_output_packet(ngx_connection_t *c, - ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min); + ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min, + ngx_uint_t ack_only); static void ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, ngx_quic_header_t *pkt, ngx_quic_path_t *path); static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); @@ -131,8 +132,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c) ngx_memzero(preserved_pnum, sizeof(preserved_pnum)); #endif - while (cg->in_flight < cg->window) { - + do { p = dst; len = ngx_quic_path_limit(c, path, path->mtu); @@ -158,7 +158,8 @@ ngx_quic_create_datagrams(ngx_connection_t *c) return NGX_OK; } - n = ngx_quic_output_packet(c, ctx, p, len, min); + n = ngx_quic_output_packet(c, ctx, p, len, min, + cg->in_flight >= cg->window); if (n == NGX_ERROR) { return NGX_ERROR; } @@ -187,7 +188,8 @@ ngx_quic_create_datagrams(ngx_connection_t *c) ngx_quic_commit_send(c); path->sent += len; - } + + } while (cg->in_flight < cg->window); return NGX_OK; } @@ -315,6 +317,10 @@ ngx_quic_allow_segmentation(ngx_connection_t *c) bytes += f->len; + if (qc->congestion.in_flight + bytes >= qc->congestion.window) { + return 0; + } + if (bytes > len * 3) { /* require at least ~3 full packets to batch */ return 1; @@ -364,7 +370,7 @@ ngx_quic_create_segments(ngx_connection_t *c) if (len && cg->in_flight + (p - dst) < cg->window) { - n = ngx_quic_output_packet(c, ctx, p, len, len); + n = ngx_quic_output_packet(c, ctx, p, len, len, 0); if (n == NGX_ERROR) { return NGX_ERROR; } @@ -521,7 +527,7 @@ ngx_quic_get_padding_level(ngx_connection_t *c) static ssize_t ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, - u_char *data, size_t max, size_t min) + u_char *data, size_t max, size_t min, ngx_uint_t ack_only) { size_t len, pad, min_payload, max_payload; u_char *p; @@ -585,6 +591,10 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, { f = ngx_queue_data(q, ngx_quic_frame_t, queue); + if (ack_only && f->type != NGX_QUIC_FT_ACK) { + break; + } + if (len >= max_payload) { break; } From noreply at nginx.com Wed Apr 30 01:50:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 30 Apr 2025 01:50:02 +0000 (UTC) Subject: [njs] Refactored working with built-in strings, symbols and small integers. Message-ID: <20250430015002.9D7FF47E88@pubserv1.nginx> details: https://github.com/nginx/njs/commit/b28e50b1952d8788485e0f6c6126320702add1d3 branches: master commit: b28e50b1952d8788485e0f6c6126320702add1d3 user: Vadim Zhestikov date: Wed, 28 Aug 2024 22:03:14 -0700 description: Refactored working with built-in strings, symbols and small integers. - Implemented atom IDs for strings, symbols and small numbers, enabling equality checks via ID comparison - Optimized string operations for faster property lookups and comparisons - Removed short string inlining from njs_value_t structure Performance improvements (arewefastyet/benchmarks/v8-v7 benchmark): - Richards: +57% (631 → 989) - Crypto: +7% (1445 → 1551) - RayTrace: +37% (562 → 772) - NavierStokes: +20% (2062 → 2465) - Overall score: +29% (1014 → 1307) In collaboration with Dmitry Volyntsev. --- auto/sources | 2 +- external/njs_crypto_module.c | 8 +- external/njs_fs_module.c | 28 +- external/njs_query_string_module.c | 44 +- external/njs_shell.c | 13 +- external/njs_webcrypto_module.c | 44 +- external/njs_xml_module.c | 74 ++-- external/njs_zlib_module.c | 5 +- nginx/ngx_http_js_module.c | 105 ++--- nginx/ngx_js.c | 62 +-- nginx/ngx_js.h | 8 +- nginx/ngx_js_fetch.c | 121 ++++-- nginx/ngx_js_shared_dict.c | 67 +-- nginx/ngx_js_shared_dict.h | 3 +- nginx/ngx_stream_js_module.c | 31 +- src/njs.h | 80 +++- src/njs_array.c | 215 +++++----- src/njs_array_buffer.c | 38 +- src/njs_async.c | 30 +- src/njs_atom.c | 333 +++++++++++++++ src/njs_atom.h | 70 +++ src/njs_atom_defs.h | 502 ++++++++++++++++++++++ src/njs_boolean.c | 54 +-- src/njs_buffer.c | 296 +++++++------ src/njs_buffer.h | 2 +- src/njs_builtin.c | 543 +++++++++++------------- src/njs_date.c | 171 ++++---- src/njs_encoding.c | 99 +++-- src/njs_error.c | 259 ++++++------ src/njs_extern.c | 56 ++- src/njs_flathsh.c | 175 +++++++- src/njs_flathsh.h | 38 +- src/njs_function.c | 160 +++---- src/njs_function.h | 9 +- src/njs_generator.c | 128 ++---- src/njs_iterator.c | 69 ++- src/njs_json.c | 208 +++++---- src/njs_lexer.c | 127 +----- src/njs_lexer.h | 28 +- src/njs_lexer_tables.h | 445 -------------------- src/njs_main.h | 4 +- src/njs_math.c | 131 +++--- src/njs_module.c | 2 +- src/njs_number.c | 107 +++-- src/njs_number.h | 27 +- src/njs_object.c | 607 +++++++++++++------------- src/njs_object.h | 166 ++++---- src/njs_object_hash.h | 842 ------------------------------------- src/njs_object_prop.c | 279 +++++------- src/njs_object_prop_declare.h | 65 ++- src/njs_parser.c | 211 +++++----- src/njs_parser.h | 6 +- src/njs_promise.c | 121 +++--- src/njs_regexp.c | 236 +++++------ src/njs_scope.c | 25 +- src/njs_string.c | 505 +++++++++------------- src/njs_string.h | 27 +- src/njs_symbol.c | 195 ++++----- src/njs_typed_array.c | 461 ++++++++++---------- src/njs_value.c | 318 ++++++-------- src/njs_value.h | 310 +++++++------- src/njs_value_conversion.h | 2 +- src/njs_variable.c | 75 ++-- src/njs_variable.h | 16 +- src/njs_vm.c | 199 ++++----- src/njs_vm.h | 27 +- src/njs_vmcode.c | 200 +++++---- src/test/njs_benchmark.c | 4 +- src/test/njs_externals_test.c | 31 +- src/test/njs_unit_test.c | 13 + 70 files changed, 4704 insertions(+), 5258 deletions(-) diff --git a/auto/sources b/auto/sources index 9b33eead..0e8db2cd 100644 --- a/auto/sources +++ b/auto/sources @@ -19,10 +19,10 @@ NJS_LIB_SRCS=" \ src/njs_utils.c \ src/njs_chb.c \ src/njs_value.c \ + src/njs_atom.c \ src/njs_vm.c \ src/njs_vmcode.c \ src/njs_lexer.c \ - src/njs_lexer_keyword.c \ src/njs_parser.c \ src/njs_variable.c \ src/njs_scope.c \ diff --git a/external/njs_crypto_module.c b/external/njs_crypto_module.c index 2781a485..cdbb4b30 100644 --- a/external/njs_crypto_module.c +++ b/external/njs_crypto_module.c @@ -362,7 +362,7 @@ njs_hash_prototype_update(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - njs_value_string_get(njs_value_arg(&result), &data); + njs_value_string_get(vm, njs_value_arg(&result), &data); } else if (njs_value_is_buffer(value)) { ret = njs_value_buffer_get(vm, value, &data); @@ -526,7 +526,7 @@ njs_crypto_create_hmac(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - njs_value_string_get(njs_value_arg(&result), &key); + njs_value_string_get(vm, njs_value_arg(&result), &key); } else if (njs_value_is_buffer(value)) { ret = njs_value_buffer_get(vm, value, &key); @@ -589,7 +589,7 @@ njs_crypto_algorithm(njs_vm_t *vm, njs_value_t *value) return NULL; } - njs_value_string_get(value, &name); + njs_value_string_get(vm, value, &name); for (e = &njs_hash_algorithms[0]; e->name.length != 0; e++) { if (njs_strstr_eq(&name, &e->name)) { @@ -618,7 +618,7 @@ njs_crypto_encoding(njs_vm_t *vm, njs_value_t *value) return &njs_encodings[0]; } - njs_value_string_get(value, &name); + njs_value_string_get(vm, value, &name); for (e = &njs_encodings[1]; e->name.length != 0; e++) { if (njs_strstr_eq(&name, &e->name)) { diff --git a/external/njs_fs_module.c b/external/njs_fs_module.c index 5f8924ae..c56a685a 100644 --- a/external/njs_fs_module.c +++ b/external/njs_fs_module.c @@ -180,7 +180,8 @@ static njs_int_t njs_fs_write_file(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t calltype, njs_value_t *retval); static njs_int_t njs_fs_constant(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_fs_dirent_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); @@ -190,7 +191,8 @@ static njs_int_t njs_fs_dirent_test(njs_vm_t *vm, njs_value_t *args, static njs_int_t njs_fs_stats_test(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t testtype, njs_value_t *retval); static njs_int_t njs_fs_stats_prop(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_fs_stats_create(njs_vm_t *vm, struct stat *st, njs_value_t *retval); @@ -1966,7 +1968,7 @@ njs_fs_readdir(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, if (njs_value_is_string(njs_value_arg(&encode))) { - njs_value_string_get(njs_value_arg(&encode), &s); + njs_value_string_get(vm, njs_value_arg(&encode), &s); } else { s.length = 0; @@ -2111,7 +2113,7 @@ njs_fs_readlink(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, encoding = NULL; if (njs_value_is_string(njs_value_arg(&encode))) { - njs_value_string_get(njs_value_arg(&encode), &s); + njs_value_string_get(vm, njs_value_arg(&encode), &s); } else { s.length = 0; @@ -2203,7 +2205,7 @@ njs_fs_realpath(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, encoding = NULL; if (njs_value_is_string(njs_value_arg(&encode))) { - njs_value_string_get(njs_value_arg(&encode), &s); + njs_value_string_get(vm, njs_value_arg(&encode), &s); } else { s.length = 0; @@ -2610,7 +2612,7 @@ njs_fs_write(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - njs_value_string_get(njs_value_arg(&result), &data); + njs_value_string_get(vm, njs_value_arg(&result), &data); goto process; } @@ -2790,7 +2792,7 @@ njs_fs_write_file(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - njs_value_string_get(njs_value_arg(&result), &content); + njs_value_string_get(vm, njs_value_arg(&result), &content); } flags = njs_fs_flags(vm, njs_value_arg(&flag), O_CREAT | O_WRONLY); @@ -3213,7 +3215,7 @@ njs_fs_path(njs_vm_t *vm, char storage[NJS_MAX_PATH + 1], njs_value_t *src, njs_int_t ret; if (njs_value_is_string(src)) { - njs_value_string_get(src, &str); + njs_value_string_get(vm, src, &str); } else if (njs_value_is_buffer(src)) { ret = njs_value_buffer_get(vm, src, &str); @@ -3261,7 +3263,7 @@ njs_fs_flags(njs_vm_t *vm, njs_value_t *value, int default_flags) return -1; } - njs_value_string_get(value, &flags); + njs_value_string_get(vm, value, &flags); for (fl = &njs_flags_table[0]; fl->name.length != 0; fl++) { if (njs_strstr_eq(&flags, &fl->name)) { @@ -3651,8 +3653,8 @@ njs_fs_stats_test(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t -njs_fs_stats_prop(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +njs_fs_stats_prop(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { double v; njs_int_t ret; @@ -3870,8 +3872,8 @@ njs_fs_bytes_written_create(njs_vm_t *vm, int bytes, njs_value_t *buffer, njs_int_t -njs_fs_constant(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +njs_fs_constant(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { njs_value_number_set(retval, njs_vm_prop_magic32(prop)); diff --git a/external/njs_query_string_module.c b/external/njs_query_string_module.c index e2f849d2..c5b4d58a 100644 --- a/external/njs_query_string_module.c +++ b/external/njs_query_string_module.c @@ -294,8 +294,8 @@ njs_query_string_append(njs_vm_t *vm, njs_value_t *object, const u_char *key, } } - ret = njs_value_property(vm, object, njs_value_arg(&name), - njs_value_arg(&retval)); + ret = njs_value_property_val(vm, object, njs_value_arg(&name), + njs_value_arg(&retval)); if (ret == NJS_OK) { if (njs_value_is_array(njs_value_arg(&retval))) { @@ -331,8 +331,8 @@ njs_query_string_append(njs_vm_t *vm, njs_value_t *object, const u_char *key, njs_value_assign(&value, &array); } - return njs_value_property_set(vm, object, njs_value_arg(&name), - njs_value_arg(&value)); + return njs_value_property_val_set(vm, object, njs_value_arg(&name), + njs_value_arg(&value)); } @@ -383,7 +383,7 @@ njs_query_string_parse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, string = njs_arg(args, nargs, 1); if (njs_value_is_string(string)) { - njs_value_string_get(string, &str); + njs_value_string_get(vm, string, &str); } else { str = njs_str_value(""); @@ -399,8 +399,8 @@ njs_query_string_parse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - if (njs_string_length(njs_value_arg(&val_sep)) != 0) { - njs_value_string_get(njs_value_arg(&val_sep), &sep); + if (njs_value_string_length(vm, njs_value_arg(&val_sep)) != 0) { + njs_value_string_get(vm, njs_value_arg(&val_sep), &sep); } } @@ -411,8 +411,8 @@ njs_query_string_parse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - if (njs_string_length(njs_value_arg(&val_eq)) != 0) { - njs_value_string_get(njs_value_arg(&val_eq), &eq); + if (njs_value_string_length(vm, njs_value_arg(&val_eq)) != 0) { + njs_value_string_get(vm, njs_value_arg(&val_eq), &eq); } } @@ -614,7 +614,7 @@ njs_query_string_encoder_call(njs_vm_t *vm, njs_chb_t *chain, } if (njs_fast_path(njs_query_string_is_native_encoder(encoder))) { - njs_value_string_get(string, &str); + njs_value_string_get(vm, string, &str); return njs_query_string_encode(chain, &str); } @@ -631,7 +631,7 @@ njs_query_string_encoder_call(njs_vm_t *vm, njs_chb_t *chain, } } - njs_value_string_get(njs_value_arg(&retval), &str); + njs_value_string_get(vm, njs_value_arg(&retval), &str); njs_chb_append_str(chain, &str); @@ -705,8 +705,8 @@ njs_query_string_stringify(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - if (njs_string_length(arg) > 0) { - njs_value_string_get(arg, &sep); + if (njs_value_string_length(vm, arg) > 0) { + njs_value_string_get(vm, arg, &sep); } } @@ -717,8 +717,8 @@ njs_query_string_stringify(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - if (njs_string_length(arg) > 0) { - njs_value_string_get(arg, &eq); + if (njs_value_string_length(vm, arg) > 0) { + njs_value_string_get(vm, arg, &eq); } } @@ -764,8 +764,8 @@ njs_query_string_stringify(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } for (n = 0; n < keys_length; n++, string++) { - ret = njs_value_property(vm, object, njs_value_arg(string), - njs_value_arg(&value)); + ret = njs_value_property_val(vm, object, njs_value_arg(string), + njs_value_arg(&value)); if (njs_slow_path(ret == NJS_ERROR)) { goto failed; } @@ -775,9 +775,9 @@ njs_query_string_stringify(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, for (i = 0; i < len; i++) { njs_value_number_set(njs_value_arg(&key), i); - ret = njs_value_property(vm, njs_value_arg(&value), - njs_value_arg(&key), - njs_value_arg(&result)); + ret = njs_value_property_val(vm, njs_value_arg(&value), + njs_value_arg(&key), + njs_value_arg(&result)); if (njs_slow_path(ret == NJS_ERROR)) { goto failed; } @@ -839,7 +839,7 @@ njs_query_string_escape(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, string = njs_value_arg(&value); } - njs_value_string_get(string, &str); + njs_value_string_get(vm, string, &str); NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); @@ -876,7 +876,7 @@ njs_query_string_unescape(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, string = njs_value_arg(&value); } - njs_value_string_get(string, &str); + njs_value_string_get(vm, string, &str); return njs_query_string_decode(vm, retval, str.start, str.length); } diff --git a/external/njs_shell.c b/external/njs_shell.c index aeab226c..75316339 100644 --- a/external/njs_shell.c +++ b/external/njs_shell.c @@ -1585,8 +1585,9 @@ njs_engine_njs_complete(njs_engine_t *engine, njs_str_t *expression) return NULL; } - ret = njs_value_property(vm, njs_value_arg(&value), njs_value_arg(&key), - njs_value_arg(&retval)); + ret = njs_value_property_val(vm, njs_value_arg(&value), + njs_value_arg(&key), + njs_value_arg(&retval)); if (njs_slow_path(ret != NJS_OK)) { if (ret == NJS_DECLINED && !global) { goto done; @@ -3664,11 +3665,11 @@ njs_ext_console_time(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - njs_value_string_get(value, &name); + njs_value_string_get(vm, value, &name); } } else { - njs_value_string_get(value, &name); + njs_value_string_get(vm, value, &name); } if (njs_console_time(console, &name) != NJS_OK) { @@ -3713,11 +3714,11 @@ njs_ext_console_time_end(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - njs_value_string_get(value, &name); + njs_value_string_get(vm, value, &name); } } else { - njs_value_string_get(value, &name); + njs_value_string_get(vm, value, &name); } njs_console_time_end(console, &name, ns); diff --git a/external/njs_webcrypto_module.c b/external/njs_webcrypto_module.c index 59d02c1d..d2918891 100644 --- a/external/njs_webcrypto_module.c +++ b/external/njs_webcrypto_module.c @@ -129,13 +129,17 @@ static njs_int_t njs_ext_unwrap_key(njs_vm_t *vm, njs_value_t *args, static njs_int_t njs_ext_wrap_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t njs_key_ext_algorithm(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_key_ext_extractable(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_key_ext_type(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_key_ext_usages(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_ext_get_random_values(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); @@ -2767,7 +2771,7 @@ fail0: return NULL; } - njs_value_string_get(val, &alg); + njs_value_string_get(vm, val, &alg); for (w = &njs_webcrypto_alg_hash[0]; w->name.length != 0; w++) { if (njs_strstr_eq(&alg, &w->name)) { @@ -3068,7 +3072,7 @@ fail0: val = njs_vm_object_prop(vm, jwk, &string_crv, &value); if (val != NULL && !njs_value_is_undefined(val)) { - njs_value_string_get(val, &name); + njs_value_string_get(vm, val, &name); for (e = &njs_webcrypto_curve[0]; e->name.length != 0; e++) { if (njs_strstr_eq(&name, &e->name)) { @@ -3194,7 +3198,7 @@ njs_import_jwk_oct(njs_vm_t *vm, njs_value_t *jwk, njs_webcrypto_key_t *key) return NJS_ERROR; } - njs_value_string_get(val, &b64); + njs_value_string_get(vm, val, &b64); (void) njs_decode_base64url_length(&b64, &key->u.s.raw.length); @@ -3213,7 +3217,7 @@ njs_import_jwk_oct(njs_vm_t *vm, njs_value_t *jwk, njs_webcrypto_key_t *key) return NJS_ERROR; } - njs_value_string_get(val, &alg); + njs_value_string_get(vm, val, &alg); size = 16; @@ -4133,8 +4137,8 @@ njs_ext_wrap_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t -njs_key_ext_algorithm(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +njs_key_ext_algorithm(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { u_char *start; njs_int_t ret; @@ -4292,7 +4296,7 @@ njs_key_ext_algorithm(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, static njs_int_t -njs_key_ext_extractable(njs_vm_t *vm, njs_object_prop_t *prop, +njs_key_ext_extractable(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { njs_webcrypto_key_t *key; @@ -4310,8 +4314,8 @@ njs_key_ext_extractable(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -njs_key_ext_type(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +njs_key_ext_type(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { const char *type; njs_webcrypto_key_t *key; @@ -4336,8 +4340,8 @@ njs_key_ext_type(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, static njs_int_t -njs_key_ext_usages(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +njs_key_ext_usages(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { njs_webcrypto_key_t *key; @@ -4436,7 +4440,7 @@ njs_key_format(njs_vm_t *vm, njs_value_t *value) return NJS_KEY_FORMAT_UNKNOWN; } - njs_value_string_get(njs_value_arg(&string), &format); + njs_value_string_get(vm, njs_value_arg(&string), &format); for (e = &njs_webcrypto_format[0]; e->name.length != 0; e++) { if (njs_strstr_eq(&format, &e->name)) { @@ -4482,7 +4486,7 @@ njs_key_usage_array_handler(njs_vm_t *vm, njs_iterator_args_t *args, return NJS_ERROR; } - njs_value_string_get(njs_value_arg(&usage), &u); + njs_value_string_get(vm, njs_value_arg(&usage), &u); for (e = &njs_webcrypto_usage[0]; e->name.length != 0; e++) { if (njs_strstr_eq(&u, &e->name)) { @@ -4585,7 +4589,7 @@ njs_key_algorithm(njs_vm_t *vm, njs_value_t *options) return NULL; } - njs_value_string_get(njs_value_arg(&name), &a); + njs_value_string_get(vm, njs_value_arg(&name), &a); for (e = &njs_webcrypto_alg[0]; e->name.length != 0; e++) { if (njs_strstr_case_eq(&a, &e->name)) { @@ -4647,7 +4651,7 @@ njs_algorithm_hash(njs_vm_t *vm, njs_value_t *options, return NJS_ERROR; } - njs_value_string_get(njs_value_arg(&value), &name); + njs_value_string_get(vm, njs_value_arg(&value), &name); for (e = &njs_webcrypto_hash[0]; e->name.length != 0; e++) { if (njs_strstr_eq(&name, &e->name)) { @@ -4722,7 +4726,7 @@ njs_algorithm_curve(njs_vm_t *vm, njs_value_t *options, int *curve) return NJS_ERROR; } - njs_value_string_get(njs_value_arg(&value), &name); + njs_value_string_get(vm, njs_value_arg(&value), &name); for (e = &njs_webcrypto_curve[0]; e->name.length != 0; e++) { if (njs_strstr_eq(&name, &e->name)) { diff --git a/external/njs_xml_module.c b/external/njs_xml_module.c index e524ba5c..95e5024a 100644 --- a/external/njs_xml_module.c +++ b/external/njs_xml_module.c @@ -43,27 +43,32 @@ static njs_int_t njs_xml_ext_canonicalization(njs_vm_t *vm, njs_value_t *args, static njs_int_t njs_xml_doc_ext_prop_keys(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys); static njs_int_t njs_xml_doc_ext_root(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *unused, njs_value_t *retval); + uint32_t atom_id, njs_value_t *value, njs_value_t *unused, + njs_value_t *retval); static njs_int_t njs_xml_node_ext_prop_keys(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys); static njs_int_t njs_xml_node_ext_prop_handler(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *unused, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, + njs_value_t *unused, njs_value_t *retval); static njs_int_t njs_xml_attr_ext_prop_keys(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys); static njs_int_t njs_xml_attr_ext_prop_handler(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *unused, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, + njs_value_t *unused, njs_value_t *retval); static njs_int_t njs_xml_node_ext_add_child(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t njs_xml_node_ext_attrs(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_xml_node_ext_name(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_xml_node_ext_ns(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_xml_node_ext_parent(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_xml_node_ext_remove_all_attributes(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); @@ -83,9 +88,11 @@ static njs_int_t njs_xml_node_ext_set_text(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t njs_xml_node_ext_tags(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_xml_node_ext_text(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_xml_node_attr_handler(njs_vm_t *vm, xmlNode *current, njs_str_t *name, njs_value_t *setval, njs_value_t *retval); @@ -505,8 +512,8 @@ njs_xml_doc_ext_prop_keys(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys) static njs_int_t -njs_xml_doc_ext_root(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *unused, njs_value_t *retval) +njs_xml_doc_ext_root(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t atom_id, + njs_value_t *value, njs_value_t *unused, njs_value_t *retval) { xmlNode *node; njs_int_t ret; @@ -523,7 +530,7 @@ njs_xml_doc_ext_root(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, any = njs_vm_prop_magic32(prop); if (!any) { - ret = njs_vm_prop_name(vm, prop, &name); + ret = njs_vm_prop_name(vm, atom_id, &name); if (njs_slow_path(ret != NJS_OK)) { njs_value_undefined_set(retval); return NJS_DECLINED; @@ -656,7 +663,8 @@ njs_xml_node_ext_prop_keys(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys) static njs_int_t njs_xml_node_ext_prop_handler(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { xmlNode *current; njs_int_t ret; @@ -675,7 +683,7 @@ njs_xml_node_ext_prop_handler(njs_vm_t *vm, njs_object_prop_t *prop, return NJS_DECLINED; } - ret = njs_vm_prop_name(vm, prop, &name); + ret = njs_vm_prop_name(vm, atom_id, &name); if (njs_slow_path(ret != NJS_OK)) { njs_value_undefined_set(retval); return NJS_DECLINED; @@ -773,7 +781,7 @@ error: static njs_int_t -njs_xml_node_ext_attrs(njs_vm_t *vm, njs_object_prop_t *prop, +njs_xml_node_ext_attrs(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { xmlNode *current; @@ -790,8 +798,8 @@ njs_xml_node_ext_attrs(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -njs_xml_node_ext_name(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +njs_xml_node_ext_name(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { xmlNode *current; @@ -807,7 +815,7 @@ njs_xml_node_ext_name(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, static njs_int_t -njs_xml_node_ext_ns(njs_vm_t *vm, njs_object_prop_t *prop, +njs_xml_node_ext_ns(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { xmlNode *current; @@ -824,7 +832,7 @@ njs_xml_node_ext_ns(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -njs_xml_node_ext_parent(njs_vm_t *vm, njs_object_prop_t *prop, +njs_xml_node_ext_parent(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { xmlNode *current; @@ -853,7 +861,8 @@ njs_xml_node_ext_remove_attribute(njs_vm_t *vm, njs_value_t *args, static njs_int_t njs_xml_node_ext_remove_all_attributes(njs_vm_t *vm, - njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) + njs_value_t *args, njs_uint_t nargs, njs_index_t unused, + njs_value_t *retval) { xmlNode *current; @@ -898,7 +907,7 @@ njs_xml_node_ext_remove_children(njs_vm_t *vm, njs_value_t *args, return NJS_ERROR; } - njs_value_string_get(selector, &name); + njs_value_string_get(vm, selector, &name); return njs_xml_node_tag_remove(vm, current, &name); } @@ -924,7 +933,7 @@ static njs_int_t njs_xml_node_ext_remove_text(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - return njs_xml_node_ext_text(vm, NULL, njs_argument(args, 0), NULL, NULL); + return njs_xml_node_ext_text(vm, NULL, 0, njs_argument(args, 0), NULL, NULL); } @@ -949,7 +958,7 @@ njs_xml_node_ext_set_attribute(njs_vm_t *vm, njs_value_t *args, return NJS_ERROR; } - njs_value_string_get(name, &str); + njs_value_string_get(vm, name, &str); return njs_xml_node_attr_handler(vm, current, &str, njs_arg(args, nargs, 2), !remove ? retval : NULL); @@ -960,14 +969,14 @@ static njs_int_t njs_xml_node_ext_set_text(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - return njs_xml_node_ext_text(vm, NULL, njs_argument(args, 0), + return njs_xml_node_ext_text(vm, NULL, 0, njs_argument(args, 0), njs_arg(args, nargs, 1), retval); } static njs_int_t -njs_xml_node_ext_tags(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +njs_xml_node_ext_tags(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { xmlNode *current; njs_str_t name; @@ -986,7 +995,7 @@ njs_xml_node_ext_tags(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, static njs_int_t -njs_xml_node_ext_text(njs_vm_t *vm, njs_object_prop_t *unused, +njs_xml_node_ext_text(njs_vm_t *vm, njs_object_prop_t *unused, uint32_t unused1, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { u_char *text; @@ -1022,7 +1031,7 @@ njs_xml_node_ext_text(njs_vm_t *vm, njs_object_prop_t *unused, return NJS_ERROR; } - njs_value_string_get(setval, &content); + njs_value_string_get(vm, setval, &content); ret = njs_xml_encode_special_chars(vm, &content, &enc); if (njs_slow_path(ret != NJS_OK)) { @@ -1875,7 +1884,8 @@ njs_xml_attr_ext_prop_keys(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys) static njs_int_t njs_xml_attr_ext_prop_handler(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *unused, njs_value_t *retval) + uint32_t atom_id, njs_value_t *value, njs_value_t *unused, + njs_value_t *retval) { size_t size; xmlAttr *node, *current; @@ -1888,7 +1898,7 @@ njs_xml_attr_ext_prop_handler(njs_vm_t *vm, njs_object_prop_t *prop, return NJS_DECLINED; } - ret = njs_vm_prop_name(vm, prop, &name); + ret = njs_vm_prop_name(vm, atom_id, &name); if (njs_slow_path(ret != NJS_OK)) { njs_value_undefined_set(retval); return NJS_DECLINED; diff --git a/external/njs_zlib_module.c b/external/njs_zlib_module.c index d3a667d8..46202fb9 100644 --- a/external/njs_zlib_module.c +++ b/external/njs_zlib_module.c @@ -15,7 +15,8 @@ static njs_int_t njs_zlib_ext_deflate(njs_vm_t *vm, njs_value_t *args, static njs_int_t njs_zlib_ext_inflate(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); njs_int_t njs_zlib_constant(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t njs_zlib_init(njs_vm_t *vm); static void *njs_zlib_alloc(void *opaque, u_int items, u_int size); static void njs_zlib_free(void *opaque, void *address); @@ -520,7 +521,7 @@ fail: njs_int_t -njs_zlib_constant(njs_vm_t *vm, njs_object_prop_t *prop, +njs_zlib_constant(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { njs_value_number_set(retval, njs_vm_prop_magic32(prop)); diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index ce4ce365..3ac95478 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -129,11 +129,11 @@ static ngx_table_elt_t *ngx_http_js_get_header(ngx_list_part_t *part, u_char *data, size_t len); #endif static njs_int_t ngx_http_js_ext_raw_header(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_http_js_ext_header_out(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); #if defined(nginx_version) && (nginx_version < 1023000) static njs_int_t ngx_http_js_header_single(njs_vm_t *vm, ngx_http_request_t *r, ngx_list_t *headers, njs_str_t *name, @@ -172,7 +172,8 @@ static njs_int_t ngx_http_js_server122(njs_vm_t *vm, ngx_http_request_t *r, static njs_int_t ngx_http_js_ext_keys_header_out(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys); static njs_int_t ngx_http_js_ext_status(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t ngx_http_js_ext_send_header(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t ngx_http_js_ext_send(njs_vm_t *vm, njs_value_t *args, @@ -193,23 +194,23 @@ static njs_int_t ngx_http_js_ext_internal_redirect(njs_vm_t *vm, njs_value_t *retval); static njs_int_t ngx_http_js_ext_get_http_version(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_http_js_ext_internal(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_http_js_ext_get_remote_address(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_http_js_ext_get_args(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_http_js_ext_get_request_body(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_http_js_ext_header_in(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); #if defined(nginx_version) && (nginx_version < 1023000) static njs_int_t ngx_http_js_header_cookie(njs_vm_t *vm, ngx_http_request_t *r, ngx_list_t *headers, njs_str_t *name, @@ -225,21 +226,21 @@ static njs_int_t ngx_http_js_header_in_array(njs_vm_t *vm, static njs_int_t ngx_http_js_ext_keys_header_in(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys); static njs_int_t ngx_http_js_ext_variables(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_http_js_periodic_session_variables(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static ngx_int_t ngx_http_js_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc); static njs_int_t ngx_http_js_ext_get_parent(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_http_js_ext_get_response_body(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); #if defined(nginx_version) && (nginx_version >= 1023000) static njs_int_t ngx_http_js_header_in(njs_vm_t *vm, ngx_http_request_t *r, @@ -1705,7 +1706,7 @@ ngx_http_js_ext_keys_header(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys, start = njs_vm_array_start(vm, keys); for (i = 0; i < length; i++) { - njs_value_string_get(njs_argument(start, i), &hdr); + njs_value_string_get(vm, njs_argument(start, i), &hdr); if (h->key.len == hdr.length && ngx_strncasecmp(h->key.data, hdr.start, hdr.length) == 0) @@ -1772,7 +1773,8 @@ ngx_http_js_get_header(ngx_list_part_t *part, u_char *data, size_t len) static njs_int_t ngx_http_js_ext_raw_header(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_int_t rc; ngx_uint_t i; @@ -1854,7 +1856,8 @@ ngx_http_js_ext_raw_header(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t ngx_http_js_ext_header_out(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_int_t rc; njs_str_t name; @@ -1910,7 +1913,7 @@ ngx_http_js_ext_header_out(njs_vm_t *vm, njs_object_prop_t *prop, return NJS_DECLINED; } - rc = njs_vm_prop_name(vm, prop, &name); + rc = njs_vm_prop_name(vm, atom_id, &name); if (rc != NJS_OK) { if (retval != NULL) { njs_value_undefined_set(retval); @@ -2395,7 +2398,7 @@ ngx_http_js_ext_keys_header_out(njs_vm_t *vm, njs_value_t *value, static njs_int_t -ngx_http_js_ext_status(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_http_js_ext_status(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { ngx_int_t n; @@ -2792,7 +2795,8 @@ ngx_http_js_ext_internal_redirect(njs_vm_t *vm, njs_value_t *args, static njs_int_t ngx_http_js_ext_get_http_version(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_str_t v; ngx_http_request_t *r; @@ -2837,7 +2841,7 @@ ngx_http_js_ext_get_http_version(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -ngx_http_js_ext_internal(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_http_js_ext_internal(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { ngx_http_request_t *r; @@ -2856,7 +2860,8 @@ ngx_http_js_ext_internal(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t ngx_http_js_ext_get_remote_address(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_connection_t *c; ngx_http_request_t *r; @@ -2875,7 +2880,7 @@ ngx_http_js_ext_get_remote_address(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -ngx_http_js_ext_get_args(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_http_js_ext_get_args(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { u_char *data; @@ -2911,7 +2916,8 @@ ngx_http_js_ext_get_args(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t ngx_http_js_ext_get_request_body(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { u_char *p, *body; size_t len; @@ -3021,7 +3027,7 @@ done: #if defined(nginx_version) && (nginx_version < 1023000) static njs_int_t -ngx_http_js_ext_header_in(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_http_js_ext_header_in(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { njs_int_t rc; @@ -3055,7 +3061,7 @@ ngx_http_js_ext_header_in(njs_vm_t *vm, njs_object_prop_t *prop, return NJS_DECLINED; } - rc = njs_vm_prop_name(vm, prop, &name); + rc = njs_vm_prop_name(vm, atom_id, &name); if (rc != NJS_OK) { if (retval != NULL) { njs_value_undefined_set(retval); @@ -3136,7 +3142,7 @@ ngx_http_js_header_in_array(njs_vm_t *vm, ngx_http_request_t *r, } #else static njs_int_t -ngx_http_js_ext_header_in(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_http_js_ext_header_in(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, njs_value_t *unused, njs_value_t *retval) { unsigned flags; @@ -3164,7 +3170,7 @@ ngx_http_js_ext_header_in(njs_vm_t *vm, njs_object_prop_t *prop, return NJS_DECLINED; } - rc = njs_vm_prop_name(vm, prop, &name); + rc = njs_vm_prop_name(vm, atom_id, &name); if (rc != NJS_OK) { if (retval != NULL) { njs_value_undefined_set(retval); @@ -3212,7 +3218,8 @@ ngx_http_js_ext_keys_header_in(njs_vm_t *vm, njs_value_t *value, static njs_int_t ngx_http_js_request_variables(njs_vm_t *vm, njs_object_prop_t *prop, - ngx_http_request_t *r, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, ngx_http_request_t *r, njs_value_t *setval, + njs_value_t *retval) { njs_int_t rc, is_capture, start, length; njs_str_t val, s; @@ -3223,7 +3230,7 @@ ngx_http_js_request_variables(njs_vm_t *vm, njs_object_prop_t *prop, ngx_http_variable_value_t *vv; u_char storage[64]; - rc = njs_vm_prop_name(vm, prop, &val); + rc = njs_vm_prop_name(vm, atom_id, &val); if (rc != NJS_OK) { njs_value_undefined_set(retval); return NJS_DECLINED; @@ -3350,7 +3357,8 @@ ngx_http_js_request_variables(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t ngx_http_js_ext_variables(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_http_request_t *r; @@ -3360,13 +3368,14 @@ ngx_http_js_ext_variables(njs_vm_t *vm, njs_object_prop_t *prop, return NJS_DECLINED; } - return ngx_http_js_request_variables(vm, prop, r, setval, retval); + return ngx_http_js_request_variables(vm, prop, atom_id, r, setval, retval); } static njs_int_t ngx_http_js_periodic_session_variables(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_http_request_t *r; @@ -3376,7 +3385,7 @@ ngx_http_js_periodic_session_variables(njs_vm_t *vm, njs_object_prop_t *prop, return NJS_DECLINED; } - return ngx_http_js_request_variables(vm, prop, r, setval, retval); + return ngx_http_js_request_variables(vm, prop, atom_id, r, setval, retval); } @@ -3708,7 +3717,8 @@ ngx_http_js_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc) static njs_int_t ngx_http_js_ext_get_parent(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_http_js_ctx_t *ctx; ngx_http_request_t *r; @@ -3735,7 +3745,8 @@ ngx_http_js_ext_get_parent(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t ngx_http_js_ext_get_response_body(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { size_t len; u_char *p; diff --git a/nginx/ngx_js.c b/nginx/ngx_js.c index 316a2076..f91fcd99 100644 --- a/nginx/ngx_js.c +++ b/nginx/ngx_js.c @@ -108,21 +108,26 @@ static JSModuleDef *ngx_qjs_core_init(JSContext *cx, const char *name); #endif static njs_int_t ngx_js_ext_build(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -static njs_int_t ngx_js_ext_conf_file_path(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +static njs_int_t ngx_js_ext_conf_file_path(njs_vm_t *vm, + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_js_ext_conf_prefix(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -static njs_int_t ngx_js_ext_error_log_path(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +static njs_int_t ngx_js_ext_error_log_path(njs_vm_t *vm, + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_js_ext_prefix(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t ngx_js_ext_version(njs_vm_t *vm, njs_object_prop_t *prop, + uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_js_ext_worker_id(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t ngx_js_ext_console_time(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t ngx_js_ext_console_time_end(njs_vm_t *vm, njs_value_t *args, @@ -2403,8 +2408,8 @@ ngx_js_core_init(njs_vm_t *vm) njs_int_t -ngx_js_ext_string(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +ngx_js_ext_string(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { char *p; ngx_str_t *field; @@ -2422,8 +2427,8 @@ ngx_js_ext_string(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, njs_int_t -ngx_js_ext_uint(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +ngx_js_ext_uint(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { char *p; ngx_uint_t field; @@ -2443,7 +2448,7 @@ ngx_js_ext_uint(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, njs_int_t -ngx_js_ext_constant(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_js_ext_constant(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { uint32_t magic32; @@ -2466,7 +2471,7 @@ ngx_js_ext_constant(njs_vm_t *vm, njs_object_prop_t *prop, njs_int_t -ngx_js_ext_flags(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_js_ext_flags(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { uintptr_t data; @@ -2491,8 +2496,8 @@ ngx_js_ext_flags(njs_vm_t *vm, njs_object_prop_t *prop, njs_int_t -ngx_js_ext_build(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +ngx_js_ext_build(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { return njs_vm_value_string_create(vm, retval, #ifdef NGX_BUILD @@ -2508,7 +2513,8 @@ ngx_js_ext_build(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, njs_int_t ngx_js_ext_conf_file_path(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { return njs_vm_value_string_create(vm, retval, ngx_cycle->conf_file.data, ngx_cycle->conf_file.len); @@ -2516,7 +2522,7 @@ ngx_js_ext_conf_file_path(njs_vm_t *vm, njs_object_prop_t *prop, njs_int_t -ngx_js_ext_conf_prefix(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_js_ext_conf_prefix(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { return njs_vm_value_string_create(vm, retval, ngx_cycle->conf_prefix.data, @@ -2525,7 +2531,7 @@ ngx_js_ext_conf_prefix(njs_vm_t *vm, njs_object_prop_t *prop, njs_int_t -ngx_js_ext_error_log_path(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_js_ext_error_log_path(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { return njs_vm_value_string_create(vm, retval, ngx_cycle->error_log.data, @@ -2534,7 +2540,7 @@ ngx_js_ext_error_log_path(njs_vm_t *vm, njs_object_prop_t *prop, njs_int_t -ngx_js_ext_prefix(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, +ngx_js_ext_prefix(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { return njs_vm_value_string_create(vm, retval, ngx_cycle->prefix.data, @@ -2543,8 +2549,8 @@ ngx_js_ext_prefix(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, njs_int_t -ngx_js_ext_version(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +ngx_js_ext_version(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { return njs_vm_value_string_create(vm, retval, (u_char *) NGINX_VERSION, njs_strlen(NGINX_VERSION)); @@ -2552,8 +2558,8 @@ ngx_js_ext_version(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, njs_int_t -ngx_js_ext_worker_id(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +ngx_js_ext_worker_id(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { njs_value_number_set(retval, ngx_worker); return NJS_OK; @@ -2640,11 +2646,11 @@ ngx_js_ext_console_time(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - njs_value_string_get(value, &name); + njs_value_string_get(vm, value, &name); } } else { - njs_value_string_get(value, &name); + njs_value_string_get(vm, value, &name); } console = njs_value_external(this); @@ -2733,11 +2739,11 @@ ngx_js_ext_console_time_end(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - njs_value_string_get(value, &name); + njs_value_string_get(vm, value, &name); } } else { - njs_value_string_get(value, &name); + njs_value_string_get(vm, value, &name); } console = njs_value_external(this); diff --git a/nginx/ngx_js.h b/nginx/ngx_js.h index 0a99a696..0e811f44 100644 --- a/nginx/ngx_js.h +++ b/nginx/ngx_js.h @@ -405,13 +405,13 @@ char * ngx_js_merge_conf(ngx_conf_t *cf, void *parent, void *child, char *ngx_js_shared_dict_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf, void *tag); -njs_int_t ngx_js_ext_string(njs_vm_t *vm, njs_object_prop_t *prop, +njs_int_t ngx_js_ext_string(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -njs_int_t ngx_js_ext_uint(njs_vm_t *vm, njs_object_prop_t *prop, +njs_int_t ngx_js_ext_uint(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -njs_int_t ngx_js_ext_constant(njs_vm_t *vm, njs_object_prop_t *prop, +njs_int_t ngx_js_ext_constant(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -njs_int_t ngx_js_ext_flags(njs_vm_t *vm, njs_object_prop_t *prop, +njs_int_t ngx_js_ext_flags(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); ngx_int_t ngx_js_string(njs_vm_t *vm, njs_value_t *value, njs_str_t *str); diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index 63e7a298..4902fe4f 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -210,8 +210,8 @@ static njs_int_t ngx_headers_js_ext_get(njs_vm_t *vm, njs_value_t *args, static njs_int_t ngx_headers_js_ext_has(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t ngx_headers_js_ext_prop(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_headers_js_ext_keys(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys); static njs_int_t ngx_headers_js_ext_set(njs_vm_t *vm, njs_value_t *args, @@ -219,37 +219,38 @@ static njs_int_t ngx_headers_js_ext_set(njs_vm_t *vm, njs_value_t *args, static njs_int_t ngx_request_js_ext_body(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t ngx_request_js_ext_body_used(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_request_js_ext_cache(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_request_js_ext_credentials(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_request_js_ext_headers(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_request_js_ext_mode(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -static njs_int_t ngx_response_js_ext_status(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +static njs_int_t ngx_response_js_ext_status(njs_vm_t *vm, + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_response_js_ext_status_text(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_response_js_ext_ok(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_response_js_ext_body_used(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_response_js_ext_headers(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_response_js_ext_type(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_response_js_ext_body(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); @@ -3523,13 +3524,13 @@ ngx_headers_js_ext_has(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t -ngx_headers_js_ext_prop(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_headers_js_ext_prop(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { njs_int_t ret; njs_str_t name; - ret = njs_vm_prop_name(vm, prop, &name); + ret = njs_vm_prop_name(vm, atom_id, &name); if (ret != NJS_OK) { return NJS_ERROR; } @@ -3539,9 +3540,40 @@ ngx_headers_js_ext_prop(njs_vm_t *vm, njs_object_prop_t *prop, static ngx_int_t -ngx_string_compare(const void *s1, const void *s2) +ngx_string_compare(const void *s1, const void *s2, void *ctx) { - return njs_vm_string_compare(s1, s2); + return njs_vm_string_compare(ctx, s1, s2); +} + + +static void +ngx_js_sort(void *base, size_t n, size_t size, + ngx_int_t (*cmp)(const void *, const void *, void *), void *ctx) +{ + u_char *p1, *p2, *p; + + p = ngx_alloc(size, ngx_cycle->log); + if (p == NULL) { + return; + } + + for (p1 = (u_char *) base + size; + p1 < (u_char *) base + n * size; + p1 += size) + { + ngx_memcpy(p, p1, size); + + for (p2 = p1; + p2 > (u_char *) base && cmp(p2 - size, p, ctx) > 0; + p2 -= size) + { + ngx_memcpy(p2, p2 - size, size); + } + + ngx_memcpy(p2, p, size); + } + + ngx_free(p); } @@ -3591,7 +3623,7 @@ ngx_headers_js_ext_keys(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys) start = njs_vm_array_start(vm, keys); for (k = 0; k < length; k++) { - njs_value_string_get(njs_argument(start, k), &hdr); + njs_value_string_get(vm, njs_argument(start, k), &hdr); if (h[i].key.len == hdr.length && njs_strncasecmp(h[i].key.data, hdr.start, hdr.length) == 0) @@ -3618,8 +3650,8 @@ ngx_headers_js_ext_keys(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys) start = njs_vm_array_start(vm, keys); - ngx_sort(start, (size_t) length, sizeof(njs_opaque_value_t), - ngx_string_compare); + ngx_js_sort(start, (size_t) length, sizeof(njs_opaque_value_t), + ngx_string_compare, vm); return NJS_OK; } @@ -3762,7 +3794,8 @@ ngx_request_js_ext_body(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t ngx_request_js_ext_body_used(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_js_request_t *request; @@ -3779,7 +3812,7 @@ ngx_request_js_ext_body_used(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -ngx_request_js_ext_cache(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_request_js_ext_cache(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { ngx_js_request_t *request; @@ -3797,7 +3830,8 @@ ngx_request_js_ext_cache(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t ngx_request_js_ext_credentials(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_js_request_t *request; @@ -3814,7 +3848,8 @@ ngx_request_js_ext_credentials(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t ngx_request_js_ext_headers(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_int_t ret; ngx_js_request_t *request; @@ -3842,7 +3877,7 @@ ngx_request_js_ext_headers(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -ngx_request_js_ext_mode(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_request_js_ext_mode(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { ngx_js_request_t *request; @@ -3921,7 +3956,8 @@ ngx_response_js_ext_body(njs_vm_t *vm, njs_value_t *args, static njs_int_t ngx_response_js_ext_body_used(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_js_response_t *response; @@ -3939,7 +3975,8 @@ ngx_response_js_ext_body_used(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t ngx_response_js_ext_headers(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_int_t ret; ngx_js_response_t *response; @@ -3967,7 +4004,7 @@ ngx_response_js_ext_headers(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -ngx_response_js_ext_ok(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_response_js_ext_ok(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { ngx_uint_t code; @@ -3989,7 +4026,8 @@ ngx_response_js_ext_ok(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t ngx_response_js_ext_status(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_js_response_t *response; @@ -4007,7 +4045,8 @@ ngx_response_js_ext_status(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t ngx_response_js_ext_status_text(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_js_response_t *response; @@ -4025,7 +4064,7 @@ ngx_response_js_ext_status_text(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -ngx_response_js_ext_type(njs_vm_t *vm, njs_object_prop_t *prop, +ngx_response_js_ext_type(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { ngx_js_response_t *response; diff --git a/nginx/ngx_js_shared_dict.c b/nginx/ngx_js_shared_dict.c index c0928088..ccca530d 100644 --- a/nginx/ngx_js_shared_dict.c +++ b/nginx/ngx_js_shared_dict.c @@ -47,8 +47,8 @@ struct ngx_js_dict_s { static njs_int_t njs_js_ext_shared_dict_capacity(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t njs_js_ext_shared_dict_clear(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t flags, njs_value_t *retval); static njs_int_t njs_js_ext_shared_dict_delete(njs_vm_t *vm, njs_value_t *args, @@ -67,8 +67,8 @@ static njs_int_t njs_js_ext_shared_dict_incr(njs_vm_t *vm, njs_value_t *args, static njs_int_t njs_js_ext_shared_dict_items(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t njs_js_ext_shared_dict_name(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t njs_js_ext_shared_dict_pop(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t njs_js_ext_shared_dict_set(njs_vm_t *vm, njs_value_t *args, @@ -76,8 +76,8 @@ static njs_int_t njs_js_ext_shared_dict_set(njs_vm_t *vm, njs_value_t *args, static njs_int_t njs_js_ext_shared_dict_size(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t njs_js_ext_shared_dict_type(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static ngx_js_dict_node_t *ngx_js_dict_lookup(ngx_js_dict_t *dict, njs_str_t *key); @@ -86,15 +86,16 @@ static ngx_js_dict_node_t *ngx_js_dict_lookup(ngx_js_dict_t *dict, static ngx_int_t ngx_js_dict_set(njs_vm_t *vm, ngx_js_dict_t *dict, njs_str_t *key, njs_value_t *value, ngx_msec_t timeout, unsigned flags); -static ngx_int_t ngx_js_dict_add(ngx_js_dict_t *dict, njs_str_t *key, - njs_value_t *value, ngx_msec_t timeout, ngx_msec_t now); -static ngx_int_t ngx_js_dict_update(ngx_js_dict_t *dict, +static ngx_int_t ngx_js_dict_add(njs_vm_t *vm, ngx_js_dict_t *dict, + njs_str_t *key, njs_value_t *value, ngx_msec_t timeout, ngx_msec_t now); +static ngx_int_t ngx_js_dict_update(njs_vm_t *vm, ngx_js_dict_t *dict, ngx_js_dict_node_t *node, njs_value_t *value, ngx_msec_t timeout, ngx_msec_t now); static ngx_int_t ngx_js_dict_get(njs_vm_t *vm, ngx_js_dict_t *dict, njs_str_t *key, njs_value_t *retval); -static ngx_int_t ngx_js_dict_incr(ngx_js_dict_t *dict, njs_str_t *key, - njs_value_t *delta, njs_value_t *init, double *value, ngx_msec_t timeout); +static ngx_int_t ngx_js_dict_incr(njs_vm_t *vm, ngx_js_dict_t *dict, + njs_str_t *key, njs_value_t *delta, njs_value_t *init, double *value, + ngx_msec_t timeout); static ngx_int_t ngx_js_dict_delete(njs_vm_t *vm, ngx_js_dict_t *dict, njs_str_t *key, njs_value_t *retval); static ngx_int_t ngx_js_dict_copy_value_locked(njs_vm_t *vm, @@ -104,8 +105,8 @@ static void ngx_js_dict_expire(ngx_js_dict_t *dict, ngx_msec_t now); static void ngx_js_dict_evict(ngx_js_dict_t *dict, ngx_int_t count); static njs_int_t ngx_js_dict_shared_error_name(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static ngx_int_t ngx_js_dict_init_zone(ngx_shm_zone_t *shm_zone, void *data); static njs_int_t ngx_js_shared_dict_preinit(njs_vm_t *vm); @@ -480,7 +481,8 @@ qjs_module_t ngx_qjs_ngx_shared_dict_module = { njs_int_t njs_js_ext_global_shared_prop(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_int_t ret; njs_str_t name; @@ -488,7 +490,7 @@ njs_js_ext_global_shared_prop(njs_vm_t *vm, njs_object_prop_t *prop, ngx_shm_zone_t *shm_zone; ngx_js_main_conf_t *conf; - ret = njs_vm_prop_name(vm, prop, &name); + ret = njs_vm_prop_name(vm, atom_id, &name); if (ret != NJS_OK) { return NJS_ERROR; } @@ -559,7 +561,8 @@ njs_js_ext_global_shared_keys(njs_vm_t *vm, njs_value_t *unused, static njs_int_t njs_js_ext_shared_dict_capacity(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_shm_zone_t *shm_zone; @@ -912,7 +915,8 @@ njs_js_ext_shared_dict_incr(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, timeout = dict->timeout; } - rc = ngx_js_dict_incr(shm_zone->data, &key, delta, init, &value, timeout); + rc = ngx_js_dict_incr(vm, shm_zone->data, &key, delta, init, &value, + timeout); if (rc == NGX_ERROR) { njs_vm_error(vm, "failed to increment value in shared dict"); return NJS_ERROR; @@ -1033,7 +1037,8 @@ fail: static njs_int_t njs_js_ext_shared_dict_name(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_shm_zone_t *shm_zone; @@ -1210,7 +1215,8 @@ njs_js_ext_shared_dict_size(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t njs_js_ext_shared_dict_type(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_str_t type; ngx_js_dict_t *dict; @@ -1308,7 +1314,7 @@ ngx_js_dict_set(njs_vm_t *vm, ngx_js_dict_t *dict, njs_str_t *key, return NGX_DECLINED; } - if (ngx_js_dict_add(dict, key, value, timeout, now) != NGX_OK) { + if (ngx_js_dict_add(vm, dict, key, value, timeout, now) != NGX_OK) { goto memory_error; } @@ -1320,7 +1326,7 @@ ngx_js_dict_set(njs_vm_t *vm, ngx_js_dict_t *dict, njs_str_t *key, } } - if (ngx_js_dict_update(dict, node, value, timeout, now) != NGX_OK) { + if (ngx_js_dict_update(vm, dict, node, value, timeout, now) != NGX_OK) { goto memory_error; } } @@ -1340,8 +1346,8 @@ memory_error: static ngx_int_t -ngx_js_dict_add(ngx_js_dict_t *dict, njs_str_t *key, njs_value_t *value, - ngx_msec_t timeout, ngx_msec_t now) +ngx_js_dict_add(njs_vm_t *vm, ngx_js_dict_t *dict, njs_str_t *key, + njs_value_t *value, ngx_msec_t timeout, ngx_msec_t now) { size_t n; uint32_t hash; @@ -1363,7 +1369,7 @@ ngx_js_dict_add(ngx_js_dict_t *dict, njs_str_t *key, njs_value_t *value, node->sn.str.data = (u_char *) node + sizeof(ngx_js_dict_node_t); if (dict->type == NGX_JS_DICT_TYPE_STRING) { - njs_value_string_get(value, &string); + njs_value_string_get(vm, value, &string); node->u.value.data = ngx_js_dict_alloc(dict, string.length); if (node->u.value.data == NULL) { ngx_slab_free_locked(dict->shpool, node); @@ -1394,14 +1400,14 @@ ngx_js_dict_add(ngx_js_dict_t *dict, njs_str_t *key, njs_value_t *value, static ngx_int_t -ngx_js_dict_update(ngx_js_dict_t *dict, ngx_js_dict_node_t *node, +ngx_js_dict_update(njs_vm_t *vm, ngx_js_dict_t *dict, ngx_js_dict_node_t *node, njs_value_t *value, ngx_msec_t timeout, ngx_msec_t now) { u_char *p; njs_str_t string; if (dict->type == NGX_JS_DICT_TYPE_STRING) { - njs_value_string_get(value, &string); + njs_value_string_get(vm, value, &string); p = ngx_js_dict_alloc(dict, string.length); if (p == NULL) { @@ -1476,8 +1482,8 @@ ngx_js_dict_delete(njs_vm_t *vm, ngx_js_dict_t *dict, njs_str_t *key, static ngx_int_t -ngx_js_dict_incr(ngx_js_dict_t *dict, njs_str_t *key, njs_value_t *delta, - njs_value_t *init, double *value, ngx_msec_t timeout) +ngx_js_dict_incr(njs_vm_t *vm, ngx_js_dict_t *dict, njs_str_t *key, + njs_value_t *delta, njs_value_t *init, double *value, ngx_msec_t timeout) { ngx_msec_t now; ngx_time_t *tp; @@ -1493,7 +1499,7 @@ ngx_js_dict_incr(ngx_js_dict_t *dict, njs_str_t *key, njs_value_t *delta, if (node == NULL) { njs_value_number_set(init, njs_value_number(init) + njs_value_number(delta)); - if (ngx_js_dict_add(dict, key, init, timeout, now) != NGX_OK) { + if (ngx_js_dict_add(vm, dict, key, init, timeout, now) != NGX_OK) { ngx_rwlock_unlock(&dict->sh->rwlock); return NGX_ERROR; } @@ -1653,7 +1659,8 @@ ngx_js_dict_evict(ngx_js_dict_t *dict, ngx_int_t count) static njs_int_t ngx_js_dict_shared_error_name(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { return njs_vm_value_string_create(vm, retval, (u_char *) "SharedMemoryError", 17); diff --git a/nginx/ngx_js_shared_dict.h b/nginx/ngx_js_shared_dict.h index ed1f4de7..b9c7f967 100644 --- a/nginx/ngx_js_shared_dict.h +++ b/nginx/ngx_js_shared_dict.h @@ -9,7 +9,8 @@ #define _NGX_JS_SHARED_DICT_H_INCLUDED_ njs_int_t njs_js_ext_global_shared_prop(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t atom_id, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); njs_int_t njs_js_ext_global_shared_keys(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys); diff --git a/nginx/ngx_stream_js_module.c b/nginx/ngx_stream_js_module.c index 7620f2e0..5c837494 100644 --- a/nginx/ngx_stream_js_module.c +++ b/nginx/ngx_stream_js_module.c @@ -120,8 +120,8 @@ static ngx_stream_js_ev_t *ngx_stream_js_event(ngx_stream_session_t *s, njs_str_t *event); static njs_int_t ngx_stream_js_ext_get_remote_address(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_stream_js_ext_done(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); @@ -137,11 +137,11 @@ static njs_int_t ngx_stream_js_ext_set_return_value(njs_vm_t *vm, njs_value_t *retval); static njs_int_t ngx_stream_js_ext_variables(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_stream_js_periodic_variables(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); #if (NJS_HAVE_QUICKJS) @@ -1405,8 +1405,8 @@ ngx_stream_js_event(ngx_stream_session_t *s, njs_str_t *event) static njs_int_t ngx_stream_js_ext_get_remote_address(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval) + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval) { ngx_connection_t *c; ngx_stream_session_t *s; @@ -1708,7 +1708,8 @@ ngx_stream_js_ext_set_return_value(njs_vm_t *vm, njs_value_t *args, static njs_int_t ngx_stream_js_session_variables(njs_vm_t *vm, njs_object_prop_t *prop, - ngx_stream_session_t *s, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, ngx_stream_session_t *s, njs_value_t *setval, + njs_value_t *retval) { njs_int_t rc; njs_str_t val; @@ -1719,7 +1720,7 @@ ngx_stream_js_session_variables(njs_vm_t *vm, njs_object_prop_t *prop, ngx_stream_variable_value_t *vv; u_char storage[64]; - rc = njs_vm_prop_name(vm, prop, &val); + rc = njs_vm_prop_name(vm, atom_id, &val); if (rc != NJS_OK) { njs_value_undefined_set(retval); return NJS_DECLINED; @@ -1818,7 +1819,8 @@ ngx_stream_js_session_variables(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t ngx_stream_js_ext_variables(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_stream_session_t *s; @@ -1828,13 +1830,14 @@ ngx_stream_js_ext_variables(njs_vm_t *vm, njs_object_prop_t *prop, return NJS_DECLINED; } - return ngx_stream_js_session_variables(vm, prop, s, setval, retval); + return ngx_stream_js_session_variables(vm, prop, atom_id, s, setval, retval); } static njs_int_t ngx_stream_js_periodic_variables(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { ngx_stream_session_t *s; @@ -1844,7 +1847,7 @@ ngx_stream_js_periodic_variables(njs_vm_t *vm, njs_object_prop_t *prop, return NJS_DECLINED; } - return ngx_stream_js_session_variables(vm, prop, s, setval, retval); + return ngx_stream_js_session_variables(vm, prop, atom_id, s, setval, retval); } diff --git a/src/njs.h b/src/njs.h index 0e2855d1..0a196321 100644 --- a/src/njs.h +++ b/src/njs.h @@ -34,6 +34,7 @@ typedef struct njs_function_s njs_function_t; typedef struct njs_vm_shared_s njs_vm_shared_t; typedef struct njs_object_init_s njs_object_init_t; typedef struct njs_object_prop_s njs_object_prop_t; +typedef struct njs_object_prop_init_s njs_object_prop_init_t; typedef struct njs_object_type_init_s njs_object_type_init_t; typedef struct njs_external_s njs_external_t; @@ -43,7 +44,7 @@ typedef struct njs_external_s njs_external_t; */ typedef struct { - uint64_t filler[2]; + uint32_t filler[4]; } njs_opaque_value_t; /* sizeof(njs_value_t) is 16 bytes. */ @@ -61,6 +62,11 @@ extern const njs_value_t njs_value_undefined; memcpy(dst, src, sizeof(njs_opaque_value_t)) #define njs_value_arg(val) ((njs_value_t *) val) +#define njs_value_atom(val) (((njs_opaque_value_t *) (val))->filler[0]) + +#define njs_atom_is_number(atom_id) ((atom_id) & 0x80000000) +#define njs_atom_number(atom_id) ((atom_id) & 0x7FFFFFFF) +#define njs_number_atom(n) ((n) | 0x80000000) #define njs_lvalue_arg(lvalue, args, nargs, n) \ ((n < nargs) ? njs_argument(args, n) \ @@ -104,7 +110,8 @@ extern const njs_value_t njs_value_undefined; * the exception value. */ typedef njs_int_t (*njs_prop_handler_t) (njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t atom_id, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); typedef njs_int_t (*njs_exotic_keys_t)(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval); typedef njs_int_t (*njs_function_native_t) (njs_vm_t *vm, njs_value_t *args, @@ -354,23 +361,24 @@ NJS_EXPORT njs_int_t njs_vm_external_create(njs_vm_t *vm, njs_value_t *value, NJS_EXPORT njs_external_ptr_t njs_vm_external(njs_vm_t *vm, njs_int_t proto_id, const njs_value_t *value); NJS_EXPORT njs_int_t njs_external_property(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); +NJS_EXPORT njs_int_t njs_atom_atomize_key(njs_vm_t *vm, njs_value_t *value); NJS_EXPORT njs_int_t njs_value_property(njs_vm_t *vm, njs_value_t *value, - njs_value_t *key, njs_value_t *retval); + uint32_t atom_id, njs_value_t *retval); NJS_EXPORT njs_int_t njs_value_property_set(njs_vm_t *vm, njs_value_t *value, - njs_value_t *key, njs_value_t *setval); + uint32_t atom_id, njs_value_t *setval); NJS_EXPORT uintptr_t njs_vm_meta(njs_vm_t *vm, njs_uint_t index); NJS_EXPORT njs_vm_opt_t *njs_vm_options(njs_vm_t *vm); NJS_EXPORT njs_int_t njs_error_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t type, njs_value_t *retval); NJS_EXPORT njs_int_t njs_object_prototype_create_constructor(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); NJS_EXPORT njs_int_t njs_object_prototype_create(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); NJS_EXPORT njs_function_t *njs_vm_function_alloc(njs_vm_t *vm, njs_function_native_t native, njs_bool_t shared, njs_bool_t ctor); @@ -403,12 +411,13 @@ NJS_EXPORT njs_int_t njs_value_to_integer(njs_vm_t *vm, njs_value_t *value, int64_t *dst); /* Gets string value, no copy. */ -NJS_EXPORT void njs_value_string_get(njs_value_t *value, njs_str_t *dst); +NJS_EXPORT void njs_value_string_get(njs_vm_t *vm, njs_value_t *value, + njs_str_t *dst); NJS_EXPORT njs_int_t njs_vm_value_string_create(njs_vm_t *vm, njs_value_t *value, const u_char *start, uint32_t size); NJS_EXPORT njs_int_t njs_vm_value_string_create_chb(njs_vm_t *vm, njs_value_t *value, njs_chb_t *chain); -NJS_EXPORT njs_int_t njs_vm_string_compare(const njs_value_t *v1, +NJS_EXPORT njs_int_t njs_vm_string_compare(njs_vm_t *vm, const njs_value_t *v1, const njs_value_t *v2); NJS_EXPORT njs_int_t njs_vm_value_array_buffer_set(njs_vm_t *vm, @@ -477,7 +486,7 @@ NJS_EXPORT njs_int_t njs_value_external_tag(const njs_value_t *value); NJS_EXPORT uint16_t njs_vm_prop_magic16(njs_object_prop_t *prop); NJS_EXPORT uint32_t njs_vm_prop_magic32(njs_object_prop_t *prop); -NJS_EXPORT njs_int_t njs_vm_prop_name(njs_vm_t *vm, njs_object_prop_t *prop, +NJS_EXPORT njs_int_t njs_vm_prop_name(njs_vm_t *vm, uint32_t atom_id, njs_str_t *dst); NJS_EXPORT njs_int_t njs_value_is_null(const njs_value_t *value); @@ -536,4 +545,49 @@ NJS_EXPORT njs_int_t njs_vm_promise_create(njs_vm_t *vm, njs_value_t *retval, njs_value_t *callbacks); +njs_inline njs_int_t +njs_value_property_val(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, + njs_value_t *retval) +{ + njs_int_t ret; + + if (njs_value_atom(key) == 0 /* NJS_ATOM_STRING_unknown */) { + ret = njs_atom_atomize_key(vm, key); + if (ret != NJS_OK) { + return ret; + } + } + + return njs_value_property(vm, value, njs_value_atom(key), retval); +} + + +njs_inline njs_int_t +njs_value_property_val_set(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, + njs_value_t *setval) +{ + njs_int_t ret; + + if (njs_value_atom(key) == 0 /* NJS_ATOM_STRING_unknown */) { + ret = njs_atom_atomize_key(vm, key); + if (ret != NJS_OK) { + return ret; + } + } + + return njs_value_property_set(vm, value, njs_value_atom(key), setval); +} + + +njs_inline size_t +njs_value_string_length(njs_vm_t *vm, njs_value_t *value) +{ + njs_str_t str; + + njs_value_string_get(vm, value, &str); + + return str.length; +} + + #endif /* _NJS_H_INCLUDED_ */ diff --git a/src/njs_array.c b/src/njs_array.c index 913bc8cf..e6f8ed83 100644 --- a/src/njs_array.c +++ b/src/njs_array.c @@ -139,7 +139,7 @@ njs_int_t njs_array_convert_to_slow_array(njs_vm_t *vm, njs_array_t *array) { uint32_t i, length; - njs_value_t index, value; + njs_value_t value; njs_object_prop_t *prop; if (njs_slow_path(!array->object.fast_array)) { @@ -153,8 +153,7 @@ njs_array_convert_to_slow_array(njs_vm_t *vm, njs_array_t *array) for (i = 0; i < length; i++) { if (njs_is_valid(&array->start[i])) { - njs_uint32_to_string(&index, i); - prop = njs_object_property_add(vm, &value, &index, 0); + prop = njs_object_property_add(vm, &value, njs_number_atom(i), 0); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -176,15 +175,13 @@ njs_array_length_redefine(njs_vm_t *vm, njs_value_t *value, uint32_t length, { njs_object_prop_t *prop; - static const njs_value_t string_length = njs_string("length"); - if (njs_slow_path(!njs_is_array(value))) { njs_internal_error(vm, "njs_array_length_redefine() " "applied to non-array"); return NJS_ERROR; } - prop = njs_object_property_add(vm, value, njs_value_arg(&string_length), 1); + prop = njs_object_property_add(vm, value, NJS_ATOM_STRING_length, 1); if (njs_slow_path(prop == NULL)) { njs_internal_error(vm, "njs_array_length_redefine() " "cannot redefine \"length\""); @@ -241,7 +238,8 @@ njs_array_length_set(njs_vm_t *vm, njs_value_t *value, do { idx = njs_string_to_index(&keys->start[i]); if (idx >= length) { - ret = njs_value_property_delete(vm, value, &keys->start[i], + ret = njs_value_property_delete(vm, value, + keys->start[i].atom_id, NULL, 1); if (njs_slow_path(ret == NJS_ERROR)) { goto done; @@ -603,19 +601,20 @@ njs_array_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_object_prop_t njs_array_constructor_properties[] = +static const njs_object_prop_init_t njs_array_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("Array"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_NATIVE("from", njs_array_from, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_from, njs_array_from, 1, 0), - NJS_DECLARE_PROP_NATIVE("isArray", njs_array_is_array, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_isArray, njs_array_is_array, 1, 0), - NJS_DECLARE_PROP_NATIVE("of", njs_array_of, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_of, njs_array_of, 0, 0), }; @@ -626,8 +625,8 @@ const njs_object_init_t njs_array_constructor_init = { static njs_int_t -njs_array_length(njs_vm_t *vm,njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +njs_array_length(njs_vm_t *vm,njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { double num; int64_t size; @@ -787,8 +786,8 @@ static njs_int_t njs_array_prototype_slice_copy(njs_vm_t *vm, njs_value_t *this, int64_t start, int64_t length, njs_value_t *retval) { + u_char *c, buf[4]; size_t size; - u_char *dst; uint32_t n; njs_int_t ret; njs_array_t *array, *keys; @@ -819,7 +818,7 @@ njs_array_prototype_slice_copy(njs_vm_t *vm, njs_value_t *this, string_slice.start = start; string_slice.length = length; - string_slice.string_length = njs_string_prop(&string, this); + string_slice.string_length = njs_string_prop(vm, &string, this); njs_string_slice_string_prop(&string, &string, &string_slice); @@ -828,10 +827,14 @@ njs_array_prototype_slice_copy(njs_vm_t *vm, njs_value_t *this, do { value = &array->start[n++]; - dst = njs_string_short_start(value); - dst = njs_utf8_copy(dst, &src, end); - size = dst - njs_string_short_start(value); - njs_string_short_set(value, size, 1); + c = buf; + c = njs_utf8_copy(c, &src, end); + size = c - buf; + + ret = njs_string_new(vm, value, buf, size, 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } length--; } while (length != 0); @@ -896,12 +899,12 @@ njs_array_prototype_slice_copy(njs_vm_t *vm, njs_value_t *this, } for (n = 0; n < keys->length; n++) { - ret = njs_value_property(vm, this, &keys->start[n], &val); + ret = njs_value_property(vm, this, keys->start[n].atom_id, &val); if (njs_slow_path(ret == NJS_ERROR)) { goto done; } - ret = njs_value_property_set(vm, &self, &keys->start[n], &val); + ret = njs_value_property_set(vm, &self, keys->start[n].atom_id, &val); if (njs_slow_path(ret == NJS_ERROR)) { goto done; } @@ -1108,7 +1111,8 @@ njs_array_prototype_unshift(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, from = keys->length; while (from > 0) { - ret = njs_value_property_delete(vm, this, &keys->start[--from], + ret = njs_value_property_delete(vm, this, + keys->start[--from].atom_id, &entry, 1); if (njs_slow_path(ret == NJS_ERROR)) { njs_array_destroy(vm, keys); @@ -1607,14 +1611,13 @@ njs_int_t njs_array_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - njs_int_t ret; - njs_value_t value; - njs_lvlhsh_query_t lhq; - - static const njs_value_t join_string = njs_string("join"); + njs_int_t ret; + njs_value_t value; + njs_flathsh_query_t lhq; if (njs_is_object(njs_argument(args, 0))) { - njs_object_property_init(&lhq, &join_string, NJS_JOIN_HASH); + lhq.proto = &njs_object_hash_proto; + lhq.key_hash = NJS_ATOM_STRING_join; ret = njs_object_property(vm, njs_object(njs_argument(args, 0)), &lhq, &value); @@ -1655,7 +1658,7 @@ njs_array_prototype_join(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, if (njs_slow_path(!njs_is_string(value))) { if (njs_is_undefined(value)) { - value = njs_value_arg(&njs_string_comma); + value = NULL; } else { ret = njs_value_to_string(vm, value, value); @@ -1665,10 +1668,17 @@ njs_array_prototype_join(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - (void) njs_string_prop(&separator, value); + if (value != NULL) { + (void) njs_string_prop(vm, &separator, value); + + } else { + separator.start = (u_char *) ","; + separator.length = 1; + separator.size = 1; + } if (njs_slow_path(!njs_is_object(this))) { - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -1680,7 +1690,7 @@ njs_array_prototype_join(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (njs_slow_path(len == 0)) { - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -1704,7 +1714,7 @@ njs_array_prototype_join(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, length += ret; } else { - (void) njs_string_prop(&string, value); + (void) njs_string_prop(vm, &string, value); length += string.length; njs_chb_append(&chain, string.start, string.size); } @@ -1773,8 +1783,9 @@ njs_array_indices_handler(const void *first, const void *second, void *ctx) return diff != 0; } - njs_string_get(val1, &str1); - njs_string_get(val2, &str2); + /* properties from njs_value_own_enumerate() are always intialized. */ + njs_string_get_unsafe(val1, &str1); + njs_string_get_unsafe(val2, &str2); cmp_res = strncmp((const char *) str1.start, (const char *) str2.start, njs_min(str1.length, str2.length)); @@ -1886,14 +1897,12 @@ njs_is_concat_spreadable(njs_vm_t *vm, njs_value_t *value) njs_int_t ret; njs_value_t retval; - static const njs_value_t key = - njs_wellknown_symbol(NJS_SYMBOL_IS_CONCAT_SPREADABLE); - if (njs_slow_path(!njs_is_object(value))) { return NJS_DECLINED; } - ret = njs_value_property(vm, value, njs_value_arg(&key), &retval); + ret = njs_value_property(vm, value, NJS_ATOM_SYMBOL_isConcatSpreadable, + &retval); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -1980,7 +1989,7 @@ njs_array_prototype_concat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } for (k = 0; k < keys->length; k++) { - ret = njs_value_property(vm, e, &keys->start[k], &value); + ret = njs_value_property_val(vm, e, &keys->start[k], &value); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -2162,7 +2171,7 @@ njs_array_handler_includes(njs_vm_t *vm, njs_iterator_args_t *args, entry = njs_value_arg(&njs_value_undefined); } - if (njs_values_same_zero(njs_value_arg(&args->argument), entry)) { + if (njs_values_same_zero(vm, njs_value_arg(&args->argument), entry)) { njs_set_true(retval); return NJS_DONE; @@ -2176,7 +2185,7 @@ static njs_int_t njs_array_handler_index_of(njs_vm_t *vm, njs_iterator_args_t *args, njs_value_t *entry, int64_t n, njs_value_t *retval) { - if (njs_values_strict_equal(njs_value_arg(&args->argument), entry)) { + if (njs_values_strict_equal(vm, njs_value_arg(&args->argument), entry)) { njs_set_number(retval, n); return NJS_DONE; @@ -2714,7 +2723,7 @@ njs_array_compare(const void *a, const void *b, void *c) } } - ret = njs_string_cmp(aslot->str, bslot->str); + ret = njs_string_cmp(ctx->vm, aslot->str, bslot->str); if (ret != 0) { return ret; @@ -2776,8 +2785,12 @@ njs_sort_indexed_properties(njs_vm_t *vm, njs_value_t *obj, int64_t length, njs_value_assign(&p->value, &start[i]); } else { - njs_uint32_to_string(&key, i); - ret = njs_value_property(vm, obj, &key, &p->value); + ret = njs_uint32_to_string(vm, &key, i); + if (njs_slow_path(ret != NJS_OK)) { + goto exception; + } + + ret = njs_value_property_val(vm, obj, &key, &p->value); if (njs_slow_path(ret == NJS_ERROR)) { goto exception; } @@ -2820,7 +2833,7 @@ njs_sort_indexed_properties(njs_vm_t *vm, njs_value_t *obj, int64_t length, ilength = njs_min(keys->length, length); for (i = 0; i < ilength; i++) { - ret = njs_value_property(vm, obj, &keys->start[i], &p->value); + ret = njs_value_property_val(vm, obj, &keys->start[i], &p->value); if (njs_slow_path(ret == NJS_ERROR)) { goto exception; } @@ -3179,103 +3192,105 @@ njs_array_prototype_iterator_obj(njs_vm_t *vm, njs_value_t *args, } -static const njs_object_prop_t njs_array_prototype_properties[] = +static const njs_object_prop_init_t njs_array_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("length", njs_array_length, 0, 0, + NJS_DECLARE_PROP_HANDLER(STRING_length, njs_array_length, 0, NJS_OBJECT_PROP_VALUE_W), - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_NATIVE("concat", njs_array_prototype_concat, 1, 0), - - NJS_DECLARE_PROP_NATIVE("copyWithin", njs_array_prototype_copy_within, 2, + NJS_DECLARE_PROP_NATIVE(STRING_concat, njs_array_prototype_concat, 1, 0), - NJS_DECLARE_PROP_NATIVE("entries", njs_array_prototype_iterator_obj, 0, - NJS_ENUM_BOTH), + NJS_DECLARE_PROP_NATIVE(STRING_copyWithin, + njs_array_prototype_copy_within, 2, 0), + + NJS_DECLARE_PROP_NATIVE(STRING_entries, + njs_array_prototype_iterator_obj, 0, NJS_ENUM_BOTH), - NJS_DECLARE_PROP_NATIVE("every", njs_array_prototype_iterator, 1, + NJS_DECLARE_PROP_NATIVE(STRING_every, njs_array_prototype_iterator, 1, njs_array_func(NJS_ARRAY_EVERY)), - NJS_DECLARE_PROP_NATIVE("fill", njs_array_prototype_fill, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_fill, njs_array_prototype_fill, 1, 0), - NJS_DECLARE_PROP_NATIVE("filter", njs_array_prototype_iterator, 1, + NJS_DECLARE_PROP_NATIVE(STRING_filter, njs_array_prototype_iterator, 1, njs_array_func(NJS_ARRAY_FILTER)), - NJS_DECLARE_PROP_NATIVE("find", njs_array_prototype_iterator, 1, + NJS_DECLARE_PROP_NATIVE(STRING_find, njs_array_prototype_iterator, 1, njs_array_func(NJS_ARRAY_FIND)), - NJS_DECLARE_PROP_NATIVE("findIndex", njs_array_prototype_iterator, 1, - njs_array_func(NJS_ARRAY_FIND_INDEX)), + NJS_DECLARE_PROP_NATIVE(STRING_findIndex, njs_array_prototype_iterator, + 1, njs_array_func(NJS_ARRAY_FIND_INDEX)), - NJS_DECLARE_PROP_NATIVE("forEach", njs_array_prototype_iterator, 1, - njs_array_func(NJS_ARRAY_FOR_EACH)), + NJS_DECLARE_PROP_NATIVE(STRING_forEach, njs_array_prototype_iterator, + 1, njs_array_func(NJS_ARRAY_FOR_EACH)), - NJS_DECLARE_PROP_NATIVE("includes", njs_array_prototype_iterator, 1, - njs_array_arg(NJS_ARRAY_INCLUDES)), + NJS_DECLARE_PROP_NATIVE(STRING_includes, njs_array_prototype_iterator, + 1, njs_array_arg(NJS_ARRAY_INCLUDES)), - NJS_DECLARE_PROP_NATIVE("indexOf", njs_array_prototype_iterator, 1, + NJS_DECLARE_PROP_NATIVE(STRING_indexOf, njs_array_prototype_iterator, 1, njs_array_arg(NJS_ARRAY_INDEX_OF)), - NJS_DECLARE_PROP_NATIVE("join", njs_array_prototype_join, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_join, njs_array_prototype_join, 1, 0), - NJS_DECLARE_PROP_NATIVE("keys", njs_array_prototype_iterator_obj, 0, - NJS_ENUM_KEYS), + NJS_DECLARE_PROP_NATIVE(STRING_keys, njs_array_prototype_iterator_obj, + 0, NJS_ENUM_KEYS), - NJS_DECLARE_PROP_NATIVE("lastIndexOf", + NJS_DECLARE_PROP_NATIVE(STRING_lastIndexOf, njs_array_prototype_reverse_iterator, 1, NJS_ARRAY_LAST_INDEX_OF), - NJS_DECLARE_PROP_NATIVE("map", njs_array_prototype_iterator, 1, + NJS_DECLARE_PROP_NATIVE(STRING_map, njs_array_prototype_iterator, 1, njs_array_func(NJS_ARRAY_MAP)), - NJS_DECLARE_PROP_NATIVE("pop", njs_array_prototype_pop, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_pop, njs_array_prototype_pop, 0, 0), - NJS_DECLARE_PROP_NATIVE("push", njs_array_prototype_push, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_push, njs_array_prototype_push, 1, 0), - NJS_DECLARE_PROP_NATIVE("reduce", njs_array_prototype_iterator, 1, + NJS_DECLARE_PROP_NATIVE(STRING_reduce, njs_array_prototype_iterator, 1, njs_array_func(NJS_ARRAY_REDUCE)), - NJS_DECLARE_PROP_NATIVE("reduceRight", + NJS_DECLARE_PROP_NATIVE(STRING_reduceRight, njs_array_prototype_reverse_iterator, 1, njs_array_func(NJS_ARRAY_REDUCE_RIGHT)), - NJS_DECLARE_PROP_NATIVE("reverse", njs_array_prototype_reverse, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_reverse, njs_array_prototype_reverse, 0, 0), - NJS_DECLARE_PROP_NATIVE("shift", njs_array_prototype_shift, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_shift, njs_array_prototype_shift, 0, 0), - NJS_DECLARE_PROP_NATIVE("slice", njs_array_prototype_slice, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_slice, njs_array_prototype_slice, 2, 0), - NJS_DECLARE_PROP_NATIVE("some", njs_array_prototype_iterator, 1, + NJS_DECLARE_PROP_NATIVE(STRING_some, njs_array_prototype_iterator, 1, njs_array_func(NJS_ARRAY_SOME)), - NJS_DECLARE_PROP_NATIVE("sort", njs_array_prototype_sort, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_sort, njs_array_prototype_sort, 1, 0), - NJS_DECLARE_PROP_NATIVE("splice", njs_array_prototype_splice, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_splice, njs_array_prototype_splice, 2, + 0), - NJS_DECLARE_PROP_NATIVE("toReversed", njs_array_prototype_to_reversed, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toReversed, + njs_array_prototype_to_reversed, 0, 0), - NJS_DECLARE_PROP_NATIVE("toSorted", njs_array_prototype_to_sorted, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toSorted, njs_array_prototype_to_sorted, + 1, 0), - NJS_DECLARE_PROP_NATIVE("toSpliced", njs_array_prototype_to_spliced, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toSpliced, + njs_array_prototype_to_spliced, 2, 0), - NJS_DECLARE_PROP_NATIVE("toString", njs_array_prototype_to_string, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toString, njs_array_prototype_to_string, + 0, 0), - NJS_DECLARE_PROP_NATIVE("unshift", njs_array_prototype_unshift, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_unshift, njs_array_prototype_unshift, 1, + 0), - NJS_DECLARE_PROP_NATIVE("values", njs_array_prototype_iterator_obj, 0, - NJS_ENUM_VALUES), + NJS_DECLARE_PROP_NATIVE(STRING_values, njs_array_prototype_iterator_obj, + 0, NJS_ENUM_VALUES), - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_ITERATOR), - .u.value = njs_native_function2(njs_array_prototype_iterator_obj, 0, - NJS_ENUM_VALUES), - .writable = 1, - .configurable = 1, - }, + NJS_DECLARE_PROP_NATIVE(SYMBOL_iterator, + njs_array_prototype_iterator_obj, 0, + NJS_ENUM_VALUES), }; @@ -3285,9 +3300,9 @@ const njs_object_init_t njs_array_prototype_init = { }; -const njs_object_prop_t njs_array_instance_properties[] = +const njs_object_prop_init_t njs_array_instance_properties[] = { - NJS_DECLARE_PROP_HANDLER("length", njs_array_length, 0, 0, + NJS_DECLARE_PROP_HANDLER(STRING_length, njs_array_length, 0, NJS_OBJECT_PROP_VALUE_W), }; diff --git a/src/njs_array_buffer.c b/src/njs_array_buffer.c index dece7329..c0e51c9f 100644 --- a/src/njs_array_buffer.c +++ b/src/njs_array_buffer.c @@ -139,23 +139,20 @@ njs_array_buffer_writable(njs_vm_t *vm, njs_array_buffer_t *buffer) } -static const njs_object_prop_t njs_array_buffer_constructor_properties[] = +static const njs_object_prop_init_t njs_array_buffer_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("ArrayBuffer"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - { - .type = NJS_ACCESSOR, - .name = njs_wellknown_symbol(NJS_SYMBOL_SPECIES), - .u.accessor = njs_getter(njs_array_buffer_get_this, 0), - .writable = NJS_ATTRIBUTE_UNSET, - .configurable = 1, - }, + NJS_DECLARE_PROP_GETTER(SYMBOL_species, + njs_array_buffer_get_this, + 0), - NJS_DECLARE_PROP_NATIVE("isView", njs_array_buffer_is_view, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_isView, njs_array_buffer_is_view, 1, 0), }; @@ -265,23 +262,20 @@ njs_array_buffer_detach(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, -static const njs_object_prop_t njs_array_buffer_prototype_properties[] = +static const njs_object_prop_init_t njs_array_buffer_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_GETTER("byteLength", + NJS_DECLARE_PROP_GETTER(STRING_byteLength, njs_array_buffer_prototype_byte_length, 0), - NJS_DECLARE_PROP_NATIVE("slice", njs_array_buffer_prototype_slice, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_slice, njs_array_buffer_prototype_slice, + 2, 0), - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.value = njs_string("ArrayBuffer"), - .configurable = 1, - }, + NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, njs_ascii_strval("ArrayBuffer"), + NJS_OBJECT_PROP_VALUE_C), }; diff --git a/src/njs_async.c b/src/njs_async.c index 77b4605f..c352e86e 100644 --- a/src/njs_async.c +++ b/src/njs_async.c @@ -161,13 +161,14 @@ njs_async_context_free(njs_vm_t *vm, njs_async_ctx_t *ctx) } -static const njs_object_prop_t njs_async_constructor_properties[] = +static const njs_object_prop_init_t njs_async_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("AsyncFunction"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -177,18 +178,15 @@ const njs_object_init_t njs_async_constructor_init = { }; -static const njs_object_prop_t njs_async_prototype_properties[] = +static const njs_object_prop_init_t njs_async_prototype_properties[] = { - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.value = njs_string("AsyncFunction"), - .configurable = 1, - }, - - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, + njs_ascii_strval("AsyncFunction"), + NJS_OBJECT_PROP_VALUE_C), + + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), }; @@ -206,12 +204,12 @@ const njs_object_type_init_t njs_async_function_type_init = { }; -const njs_object_prop_t njs_async_function_instance_properties[] = +const njs_object_prop_init_t njs_async_function_instance_properties[] = { - NJS_DECLARE_PROP_HANDLER("length", njs_function_instance_length, 0, 0, + NJS_DECLARE_PROP_HANDLER(STRING_length, njs_function_instance_length, 0, NJS_OBJECT_PROP_VALUE_C), - NJS_DECLARE_PROP_HANDLER("name", njs_function_instance_name, 0, 0, + NJS_DECLARE_PROP_HANDLER(STRING_name, njs_function_instance_name, 0, NJS_OBJECT_PROP_VALUE_C), }; diff --git a/src/njs_atom.c b/src/njs_atom.c new file mode 100644 index 00000000..24e6dc17 --- /dev/null +++ b/src/njs_atom.c @@ -0,0 +1,333 @@ + +/* + * Copyright (C) Vadim Zhestkov + * Copyright (C) F5, Inc. + */ + + +#include + + +static njs_int_t njs_lexer_hash_test(njs_lvlhsh_query_t *lhq, void *data); +static njs_int_t njs_atom_hash_test(njs_flathsh_query_t *lhq, void *data); + + +const njs_value_t njs_atom[] = { +#define NJS_DEF_SYMBOL(_id, _s) njs_symval(_id, _s), +#define NJS_DEF_STRING(_id, _s, _typ, _tok) (njs_value_t) { \ + .string = { \ + .type = NJS_STRING, \ + .truth = njs_length(_s) ? 1 : 0, \ + .atom_id = NJS_ATOM_STRING_ ## _id, \ + .token_type = _typ, \ + .token_id = _tok, \ + .data = & (njs_string_t) { \ + .start = (u_char *) _s, \ + .length = njs_length(_s), \ + .size = njs_length(_s), \ + }, \ + } \ +}, + + #include +}; + + +const njs_lvlhsh_proto_t njs_lexer_hash_proto + njs_aligned(64) = +{ + NJS_LVLHSH_DEFAULT, + njs_lexer_hash_test, + njs_lvlhsh_alloc, + njs_lvlhsh_free, +}; + + +const njs_flathsh_proto_t njs_atom_hash_proto + njs_aligned(64) = +{ + 0, + njs_atom_hash_test, + njs_lvlhsh_alloc, + njs_lvlhsh_free, +}; + + +static njs_int_t +njs_lexer_hash_test(njs_lvlhsh_query_t *lhq, void *data) +{ + u_char *start; + njs_value_t *name; + + name = data; + + njs_assert(name->type == NJS_STRING); + + if (lhq->key.length != name->string.data->size) { + return NJS_DECLINED; + } + + start = name->string.data->start; + + if (memcmp(start, lhq->key.start, lhq->key.length) == 0) { + return NJS_OK; + } + + return NJS_DECLINED; +} + + +njs_value_t * +njs_atom_find_or_add(njs_vm_t *vm, u_char *key, size_t size, size_t length, + uint32_t hash) +{ + njs_int_t ret; + njs_value_t *entry; + njs_lvlhsh_query_t lhq; + + lhq.key.start = key; + lhq.key.length = size; + lhq.key_hash = hash; + lhq.proto = &njs_lexer_hash_proto; + + ret = njs_lvlhsh_find(vm->atom_hash_current, &lhq); + if (ret == NJS_OK) { + return lhq.value; + } + + ret = njs_lvlhsh_find(&vm->atom_hash_shared, &lhq); + if (ret == NJS_OK) { + return lhq.value; + } + + entry = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t)); + if (njs_slow_path(entry == NULL)) { + return NULL; + } + + ret = njs_string_create(vm, entry, key, size); + if (njs_slow_path(ret != NJS_OK)) { + return NULL; + } + + entry->string.atom_id = vm->atom_id_generator++; + if (njs_atom_is_number(entry->string.atom_id)) { + njs_internal_error(vm, "too many atoms"); + return NULL; + } + + entry->string.token_type = NJS_KEYWORD_TYPE_UNDEF; + + lhq.value = entry; + lhq.pool = vm->mem_pool; + + ret = njs_lvlhsh_insert(vm->atom_hash_current, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + return NULL; + } + + return entry; +} + + +static njs_int_t +njs_atom_hash_test(njs_flathsh_query_t *lhq, void *data) +{ + size_t size; + u_char *start; + njs_value_t *name; + + name = data; + + if (name->type == NJS_STRING + && ((njs_value_t *) lhq->value)->type == NJS_STRING) + { + size = name->string.data->length; + + if (lhq->key.length != size) { + return NJS_DECLINED; + } + + start = (u_char *) name->string.data->start; + + if (memcmp(start, lhq->key.start, lhq->key.length) == 0) { + return NJS_OK; + } + } + + if (name->type == NJS_SYMBOL + && ((njs_value_t *) lhq->value)->type == NJS_SYMBOL) + { + if (lhq->key_hash == name->atom_id) { + return NJS_OK; + } + } + + return NJS_DECLINED; +} + + +uint32_t +njs_atom_hash_init(njs_vm_t *vm) +{ + u_char *start; + size_t len; + njs_int_t ret; + njs_uint_t n; + const njs_value_t *value, *values; + njs_flathsh_query_t lhq; + + values = &njs_atom[0]; + + njs_lvlhsh_init(&vm->atom_hash_shared); + + lhq.replace = 0; + lhq.proto = &njs_atom_hash_proto; + lhq.pool = vm->mem_pool; + + for (n = 0; n < NJS_ATOM_SIZE; n++) { + value = &values[n]; + + if (value->type == NJS_SYMBOL) { + lhq.key_hash = value->string.atom_id; + lhq.value = (void *) value; + + ret = njs_flathsh_insert(&vm->atom_hash_shared, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "flathsh insert/replace failed"); + return 0xffffffff; + } + } + + if (value->type == NJS_STRING) { + start = value->string.data->start; + len = value->string.data->length; + + lhq.key_hash = njs_djb_hash(start, len); + lhq.key.length = len; + lhq.key.start = start; + lhq.value = (void *) value; + + ret = njs_flathsh_insert(&vm->atom_hash_shared, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "flathsh insert/replace failed"); + return 0xffffffff; + } + } + } + + vm->atom_hash_current = &vm->atom_hash_shared; + + return NJS_ATOM_SIZE; +} + + +njs_int_t +njs_atom_atomize_key(njs_vm_t *vm, njs_value_t *value) +{ + double num; + uint32_t hash_id, u32; + njs_int_t ret; + njs_value_t val_str; + const njs_value_t *entry; + + njs_assert(value->atom_id == NJS_ATOM_STRING_unknown); + + switch (value->type) { + case NJS_STRING: + num = njs_key_to_index(value); + u32 = (uint32_t) num; + + if (njs_fast_path(u32 == num && (u32 < 0x80000000) + && !(num == 0 && signbit(num)))) + { + value->atom_id = njs_number_atom(u32); + + } else { + hash_id = njs_djb_hash(value->string.data->start, + value->string.data->size); + + entry = njs_atom_find_or_add(vm, value->string.data->start, + value->string.data->size, + value->string.data->length, + hash_id); + if (njs_slow_path(entry == NULL)) { + return NJS_ERROR; + } + + *value = *entry; + } + + break; + + case NJS_NUMBER: + num = njs_number(value); + u32 = (uint32_t) num; + + if (njs_fast_path(u32 == num && (u32 < 0x80000000))) { + value->atom_id = njs_number_atom(u32); + + } else { + ret = njs_number_to_string(vm, &val_str, value); + if (ret != NJS_OK) { + return ret; + } + + if (val_str.atom_id == NJS_ATOM_STRING_unknown) { + hash_id = njs_djb_hash(val_str.string.data->start, + val_str.string.data->size); + + entry = njs_atom_find_or_add(vm, val_str.string.data->start, + val_str.string.data->size, + val_str.string.data->length, + hash_id); + if (njs_slow_path(entry == NULL)) { + return NJS_ERROR; + } + + value->atom_id = entry->atom_id; + + } else { + value->atom_id = val_str.atom_id; + } + } + + break; + + case NJS_SYMBOL: + default: + /* do nothing. */ + break; + } + + return NJS_OK; +} + + +njs_int_t +njs_atom_symbol_add(njs_vm_t *vm, njs_value_t *value) +{ + njs_int_t ret; + njs_flathsh_query_t lhq; + + njs_assert(value->atom_id == NJS_ATOM_STRING_unknown); + + lhq.replace = 0; + lhq.proto = &njs_lexer_hash_proto; + lhq.pool = vm->mem_pool; + + value->atom_id = vm->atom_id_generator++; + + if (value->type == NJS_SYMBOL) { + lhq.key_hash = value->atom_id; + lhq.value = (void *) value; + + ret = njs_flathsh_insert(vm->atom_hash_current, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "flathsh insert/replace failed"); + return NJS_ERROR; + } + } + + return NJS_OK; +} diff --git a/src/njs_atom.h b/src/njs_atom.h new file mode 100644 index 00000000..12bb0e54 --- /dev/null +++ b/src/njs_atom.h @@ -0,0 +1,70 @@ + +/* + * Copyright (C) Vadim Zhestkov + * Copyright (C) F5, Inc. + */ + + +#ifndef _NJS_ATOM_H_INCLUDED_ +#define _NJS_ATOM_H_INCLUDED_ + + +enum { +#define NJS_DEF_STRING(name, _1, _2, _3) NJS_ATOM_STRING_ ## name, +#define NJS_DEF_SYMBOL(name, str) NJS_ATOM_SYMBOL_ ## name, +#include + NJS_ATOM_SIZE, +#undef NJS_DEF_SYMBOL +#undef NJS_DEF_STRING +}; + + +uint32_t njs_atom_hash_init(njs_vm_t *vm); +njs_int_t njs_atom_symbol_add(njs_vm_t *vm, njs_value_t *value); +njs_value_t *njs_atom_find_or_add(njs_vm_t *vm, u_char *key, size_t size, + size_t length, uint32_t hash); + + +njs_inline njs_int_t +njs_atom_to_value(njs_vm_t *vm, njs_value_t *dst, uint32_t atom_id) +{ + size_t size; + double num; + njs_flathsh_descr_t *h; + u_char buf[128]; + + njs_assert(atom_id != NJS_ATOM_STRING_unknown); + + if (njs_atom_is_number(atom_id)) { + num = njs_atom_number(atom_id); + size = njs_dtoa(num, (char *) buf); + + if (njs_string_new(vm, dst, buf, size, size) != NJS_OK) { + return NJS_ERROR; + } + + dst->atom_id = atom_id; + + return NJS_OK; + } + + if (atom_id < vm->shared_atom_count) { + h = vm->atom_hash_shared.slot; + + njs_assert(atom_id < h->elts_count); + + *dst = *((njs_value_t *) njs_hash_elts(h)[atom_id].value); + + } else { + h = vm->atom_hash_current->slot; + atom_id -= vm->shared_atom_count; + + njs_assert(atom_id < h->elts_count); + + *dst = *((njs_value_t *) njs_hash_elts(h)[atom_id].value); + } + + return NJS_OK; +} + +#endif /* _NJS_ATOM_H_INCLUDED_ */ diff --git a/src/njs_atom_defs.h b/src/njs_atom_defs.h new file mode 100644 index 00000000..f940648a --- /dev/null +++ b/src/njs_atom_defs.h @@ -0,0 +1,502 @@ + +/* + * Copyright (C) Vadim Zhestkov + * Copyright (C) F5, Inc. + */ + + +NJS_DEF_STRING(unknown, "unknown", 0, NJS_TOKEN_ILLEGAL) + +NJS_DEF_SYMBOL(asyncIterator, "Symbol.asyncIterator") +NJS_DEF_SYMBOL(hasInstance, "Symbol.hasInstance") +NJS_DEF_SYMBOL(isConcatSpreadable, "Symbol.isConcatSpreadable") +NJS_DEF_SYMBOL(iterator, "Symbol.iterator") +NJS_DEF_SYMBOL(match, "Symbol.match") +NJS_DEF_SYMBOL(matchAll, "Symbol.matchAll") +NJS_DEF_SYMBOL(replace, "Symbol.replace") +NJS_DEF_SYMBOL(search, "Symbol.search") +NJS_DEF_SYMBOL(species, "Symbol.species") +NJS_DEF_SYMBOL(split, "Symbol.split") +NJS_DEF_SYMBOL(toPrimitive, "Symbol.toPrimitive") +NJS_DEF_SYMBOL(toStringTag, "Symbol.toStringTag") +NJS_DEF_SYMBOL(unscopables, "Symbol.unscopables") + +/* Keywords. */ + +#define NJS_KWD (NJS_KEYWORD_TYPE_KEYWORD) +#define NJS_KWD_RESERVED (NJS_KEYWORD_TYPE_RESERVED | NJS_KEYWORD_TYPE_KEYWORD) + +NJS_DEF_STRING(arguments, "arguments", NJS_KWD, NJS_TOKEN_ARGUMENTS) +NJS_DEF_STRING(async, "async", NJS_KWD, NJS_TOKEN_ASYNC) +NJS_DEF_STRING(await, "await", NJS_KWD_RESERVED, NJS_TOKEN_AWAIT) +NJS_DEF_STRING(break, "break", NJS_KWD_RESERVED, NJS_TOKEN_BREAK) +NJS_DEF_STRING(case, "case", NJS_KWD_RESERVED, NJS_TOKEN_CASE) +NJS_DEF_STRING(catch, "catch", NJS_KWD_RESERVED, NJS_TOKEN_CATCH) +NJS_DEF_STRING(class, "class", NJS_KWD_RESERVED, NJS_TOKEN_CLASS) +NJS_DEF_STRING(const, "const", NJS_KWD_RESERVED, NJS_TOKEN_CONST) +NJS_DEF_STRING(continue, "continue", NJS_KWD_RESERVED, NJS_TOKEN_CONTINUE) +NJS_DEF_STRING(debugger, "debugger", NJS_KWD_RESERVED, NJS_TOKEN_DEBUGGER) +NJS_DEF_STRING(default, "default", NJS_KWD_RESERVED, NJS_TOKEN_DEFAULT) +NJS_DEF_STRING(delete, "delete", NJS_KWD_RESERVED, NJS_TOKEN_DELETE) +NJS_DEF_STRING(do, "do", NJS_KWD_RESERVED, NJS_TOKEN_DO) +NJS_DEF_STRING(else, "else", NJS_KWD_RESERVED, NJS_TOKEN_ELSE) +NJS_DEF_STRING(enum, "enum", NJS_KWD_RESERVED, NJS_TOKEN_ENUM) +NJS_DEF_STRING(eval, "eval", NJS_KWD, NJS_TOKEN_EVAL) +NJS_DEF_STRING(export, "export", NJS_KWD_RESERVED, NJS_TOKEN_EXPORT) +NJS_DEF_STRING(extends, "extends", NJS_KWD_RESERVED, NJS_TOKEN_EXTENDS) +NJS_DEF_STRING(false, "false", NJS_KWD_RESERVED, NJS_TOKEN_FALSE) +NJS_DEF_STRING(finally, "finally", NJS_KWD_RESERVED, NJS_TOKEN_FINALLY) +NJS_DEF_STRING(for, "for", NJS_KWD_RESERVED, NJS_TOKEN_FOR) +NJS_DEF_STRING(from, "from", NJS_KWD, NJS_TOKEN_FROM) +NJS_DEF_STRING(function, "function", NJS_KWD_RESERVED, NJS_TOKEN_FUNCTION) +NJS_DEF_STRING(if, "if", NJS_KWD_RESERVED, NJS_TOKEN_IF) +NJS_DEF_STRING(implements, "implements", NJS_KWD_RESERVED, NJS_TOKEN_IMPLEMENTS) +NJS_DEF_STRING(import, "import", NJS_KWD_RESERVED, NJS_TOKEN_IMPORT) +NJS_DEF_STRING(in, "in", NJS_KWD_RESERVED, NJS_TOKEN_IN) +NJS_DEF_STRING(instanceof, "instanceof", NJS_KWD_RESERVED, NJS_TOKEN_INSTANCEOF) +NJS_DEF_STRING(interface, "interface", NJS_KWD_RESERVED, NJS_TOKEN_INTERFACE) +NJS_DEF_STRING(let, "let", NJS_KWD_RESERVED, NJS_TOKEN_LET) +NJS_DEF_STRING(meta, "meta", NJS_KWD, NJS_TOKEN_META) +NJS_DEF_STRING(new, "new", NJS_KWD_RESERVED, NJS_TOKEN_NEW) +NJS_DEF_STRING(null, "null", NJS_KWD_RESERVED, NJS_TOKEN_NULL) +NJS_DEF_STRING(of, "of", NJS_KWD, NJS_TOKEN_OF) +NJS_DEF_STRING(package, "package", NJS_KWD_RESERVED, NJS_TOKEN_PACKAGE) +NJS_DEF_STRING(private, "private", NJS_KWD_RESERVED, NJS_TOKEN_PRIVATE) +NJS_DEF_STRING(protected, "protected", NJS_KWD_RESERVED, NJS_TOKEN_PROTECTED) +NJS_DEF_STRING(public, "public", NJS_KWD_RESERVED, NJS_TOKEN_PUBLIC) +NJS_DEF_STRING(return, "return", NJS_KWD_RESERVED, NJS_TOKEN_RETURN) +NJS_DEF_STRING(static, "static", NJS_KWD_RESERVED, NJS_TOKEN_STATIC) +NJS_DEF_STRING(super, "super", NJS_KWD_RESERVED, NJS_TOKEN_SUPER) +NJS_DEF_STRING(switch, "switch", NJS_KWD_RESERVED, NJS_TOKEN_SWITCH) +NJS_DEF_STRING(target, "target", NJS_KWD, NJS_TOKEN_TARGET) +NJS_DEF_STRING(this, "this", NJS_KWD_RESERVED, NJS_TOKEN_THIS) +NJS_DEF_STRING(throw, "throw", NJS_KWD_RESERVED, NJS_TOKEN_THROW) +NJS_DEF_STRING(true, "true", NJS_KWD_RESERVED, NJS_TOKEN_TRUE) +NJS_DEF_STRING(try, "try", NJS_KWD_RESERVED, NJS_TOKEN_TRY) +NJS_DEF_STRING(typeof, "typeof", NJS_KWD_RESERVED, NJS_TOKEN_TYPEOF) +NJS_DEF_STRING(undefined, "undefined", NJS_KWD, NJS_TOKEN_UNDEFINED) +NJS_DEF_STRING(var, "var", NJS_KWD_RESERVED, NJS_TOKEN_VAR) +NJS_DEF_STRING(void, "void", NJS_KWD_RESERVED, NJS_TOKEN_VOID) +NJS_DEF_STRING(while, "while", NJS_KWD_RESERVED, NJS_TOKEN_WHILE) +NJS_DEF_STRING(with, "with", NJS_KWD_RESERVED, NJS_TOKEN_WITH) +NJS_DEF_STRING(yield, "yield", NJS_KWD_RESERVED, NJS_TOKEN_YIELD) + +/* Other predefined strings. */ + +NJS_DEF_STRING(spec_EMPTY_REGEXP, "(?:)", 0, 0) + +NJS_DEF_STRING(empty, "", 0, 0) +NJS_DEF_STRING(_262, "$262", 0, 0) +NJS_DEF_STRING(_Infinity, "-Infinity", 0, 0) +NJS_DEF_STRING(AggregateError, "AggregateError", 0, 0) +NJS_DEF_STRING(All_promises_were_rejected, "All promises were rejected", 0, 0) +NJS_DEF_STRING(Array, "Array", 0, 0) +NJS_DEF_STRING(Array_Iterator, "Array Iterator", 0, 0) +NJS_DEF_STRING(ArrayBuffer, "ArrayBuffer", 0, 0) +NJS_DEF_STRING(AsyncFunction, "AsyncFunction", 0, 0) +NJS_DEF_STRING(Boolean, "Boolean", 0, 0) +NJS_DEF_STRING(Buffer, "Buffer", 0, 0) +NJS_DEF_STRING(BYTES_PER_ELEMENT, "BYTES_PER_ELEMENT", 0, 0) +NJS_DEF_STRING(DataView, "DataView", 0, 0) +NJS_DEF_STRING(Date, "Date", 0, 0) +NJS_DEF_STRING(E, "E", 0, 0) +NJS_DEF_STRING(EPSILON, "EPSILON", 0, 0) +NJS_DEF_STRING(Error, "Error", 0, 0) +NJS_DEF_STRING(EvalError, "EvalError", 0, 0) +NJS_DEF_STRING(Float32Array, "Float32Array", 0, 0) +NJS_DEF_STRING(Float64Array, "Float64Array", 0, 0) +NJS_DEF_STRING(Function, "Function", 0, 0) +NJS_DEF_STRING(Infinity, "Infinity", 0, 0) +NJS_DEF_STRING(Int16Array, "Int16Array", 0, 0) +NJS_DEF_STRING(Int32Array, "Int32Array", 0, 0) +NJS_DEF_STRING(Int8Array, "Int8Array", 0, 0) +NJS_DEF_STRING(InternalError, "InternalError", 0, 0) +NJS_DEF_STRING(Invalid_Date, "Invalid Date", 0, 0) +NJS_DEF_STRING(JSON, "JSON", 0, 0) +NJS_DEF_STRING(LN10, "LN10", 0, 0) +NJS_DEF_STRING(LN2, "LN2", 0, 0) +NJS_DEF_STRING(LOG10E, "LOG10E", 0, 0) +NJS_DEF_STRING(LOG2E, "LOG2E", 0, 0) +NJS_DEF_STRING(MAX_LENGTH, "MAX_LENGTH", 0, 0) +NJS_DEF_STRING(MAX_SAFE_INTEGER, "MAX_SAFE_INTEGER", 0, 0) +NJS_DEF_STRING(MAX_STRING_LENGTH, "MAX_STRING_LENGTH", 0, 0) +NJS_DEF_STRING(MAX_VALUE, "MAX_VALUE", 0, 0) +NJS_DEF_STRING(MIN_SAFE_INTEGER, "MIN_SAFE_INTEGER", 0, 0) +NJS_DEF_STRING(MIN_VALUE, "MIN_VALUE", 0, 0) +NJS_DEF_STRING(Math, "Math", 0, 0) +NJS_DEF_STRING(MemoryError, "MemoryError", 0, 0) +NJS_DEF_STRING(NEGATIVE_INFINITY, "NEGATIVE_INFINITY", 0, 0) +NJS_DEF_STRING(NaN, "NaN", 0, 0) +NJS_DEF_STRING(Number, "Number", 0, 0) +NJS_DEF_STRING(Object, "Object", 0, 0) +NJS_DEF_STRING(PI, "PI", 0, 0) +NJS_DEF_STRING(POSITIVE_INFINITY, "POSITIVE_INFINITY", 0, 0) +NJS_DEF_STRING(Promise, "Promise", 0, 0) +NJS_DEF_STRING(RangeError, "RangeError", 0, 0) +NJS_DEF_STRING(ReferenceError, "ReferenceError", 0, 0) +NJS_DEF_STRING(RegExp, "RegExp", 0, 0) +NJS_DEF_STRING(SQRT1_2, "SQRT1_2", 0, 0) +NJS_DEF_STRING(SQRT2, "SQRT2", 0, 0) +NJS_DEF_STRING(String, "String", 0, 0) +NJS_DEF_STRING(Symbol, "Symbol", 0, 0) +NJS_DEF_STRING(SyntaxError, "SyntaxError", 0, 0) +NJS_DEF_STRING(TextDecoder, "TextDecoder", 0, 0) +NJS_DEF_STRING(TextEncoder, "TextEncoder", 0, 0) +NJS_DEF_STRING(TypeError, "TypeError", 0, 0) +NJS_DEF_STRING(TypedArray, "TypedArray", 0, 0) +NJS_DEF_STRING(URIError, "URIError", 0, 0) +NJS_DEF_STRING(UTC, "UTC", 0, 0) +NJS_DEF_STRING(Uint16Array, "Uint16Array", 0, 0) +NJS_DEF_STRING(Uint32Array, "Uint32Array", 0, 0) +NJS_DEF_STRING(Uint8Array, "Uint8Array", 0, 0) +NJS_DEF_STRING(Uint8ClampedArray, "Uint8ClampedArray", 0, 0) +NJS_DEF_STRING(_Getter_, "[Getter]", 0, 0) +NJS_DEF_STRING(_Setter_, "[Setter]", 0, 0) +NJS_DEF_STRING(_Getter_Setter_, "[Getter/Setter]", 0, 0) +NJS_DEF_STRING(_object_Array_, "[object Array]", 0, 0) +NJS_DEF_STRING(_object_Arguments_, "[object Arguments]", 0, 0) +NJS_DEF_STRING(_object_Boolean_, "[object Boolean]", 0, 0) +NJS_DEF_STRING(_object_Date_, "[object Date]", 0, 0) +NJS_DEF_STRING(_object_Error_, "[object Error]", 0, 0) +NJS_DEF_STRING(_object_Function_, "[object Function]", 0, 0) +NJS_DEF_STRING(_object_Null_, "[object Null]", 0, 0) +NJS_DEF_STRING(_object_Number_, "[object Number]", 0, 0) +NJS_DEF_STRING(_object_Object_, "[object Object]", 0, 0) +NJS_DEF_STRING(_object_RegExp_, "[object RegExp]", 0, 0) +NJS_DEF_STRING(_object_String_, "[object String]", 0, 0) +NJS_DEF_STRING(_object_Undefined_, "[object Undefined]", 0, 0) +NJS_DEF_STRING(__proto__, "__proto__", 0, 0) +NJS_DEF_STRING(abs, "abs", 0, 0) +NJS_DEF_STRING(acos, "acos", 0, 0) +NJS_DEF_STRING(acosh, "acosh", 0, 0) +NJS_DEF_STRING(all, "all", 0, 0) +NJS_DEF_STRING(alloc, "alloc", 0, 0) +NJS_DEF_STRING(allocUnsafe, "allocUnsafe", 0, 0) +NJS_DEF_STRING(allocUnsafeSlow, "allocUnsafeSlow", 0, 0) +NJS_DEF_STRING(allSettled, "allSettled", 0, 0) +NJS_DEF_STRING(anonymous, "anonymous", 0, 0) +NJS_DEF_STRING(any, "any", 0, 0) +NJS_DEF_STRING(apply, "apply", 0, 0) +NJS_DEF_STRING(argv, "argv", 0, 0) +NJS_DEF_STRING(asin, "asin", 0, 0) +NJS_DEF_STRING(asinh, "asinh", 0, 0) +NJS_DEF_STRING(assign, "assign", 0, 0) +NJS_DEF_STRING(asyncIterator, "asyncIterator", 0, 0) +NJS_DEF_STRING(atan, "atan", 0, 0) +NJS_DEF_STRING(atan2, "atan2", 0, 0) +NJS_DEF_STRING(atanh, "atanh", 0, 0) +NJS_DEF_STRING(atob, "atob", 0, 0) +NJS_DEF_STRING(bind, "bind", 0, 0) +NJS_DEF_STRING(boolean, "boolean", 0, 0) +NJS_DEF_STRING(btoa, "btoa", 0, 0) +NJS_DEF_STRING(buffer, "buffer", 0, 0) +NJS_DEF_STRING(byteLength, "byteLength", 0, 0) +NJS_DEF_STRING(byteOffset, "byteOffset", 0, 0) +NJS_DEF_STRING(call, "call", 0, 0) +NJS_DEF_STRING(callee, "callee", 0, 0) +NJS_DEF_STRING(caller, "caller", 0, 0) +NJS_DEF_STRING(cbrt, "cbrt", 0, 0) +NJS_DEF_STRING(ceil, "ceil", 0, 0) +NJS_DEF_STRING(charAt, "charAt", 0, 0) +NJS_DEF_STRING(charCodeAt, "charCodeAt", 0, 0) +NJS_DEF_STRING(cluster_size, "cluster_size", 0, 0) +NJS_DEF_STRING(clz32, "clz32", 0, 0) +NJS_DEF_STRING(codePointAt, "codePointAt", 0, 0) +NJS_DEF_STRING(compare, "compare", 0, 0) +NJS_DEF_STRING(concat, "concat", 0, 0) +NJS_DEF_STRING(configurable, "configurable", 0, 0) +NJS_DEF_STRING(constructor, "constructor", 0, 0) +NJS_DEF_STRING(copy, "copy", 0, 0) +NJS_DEF_STRING(copyWithin, "copyWithin", 0, 0) +NJS_DEF_STRING(cos, "cos", 0, 0) +NJS_DEF_STRING(cosh, "cosh", 0, 0) +NJS_DEF_STRING(create, "create", 0, 0) +NJS_DEF_STRING(data, "data", 0, 0) +NJS_DEF_STRING(decode, "decode", 0, 0) +NJS_DEF_STRING(decodeURI, "decodeURI", 0, 0) +NJS_DEF_STRING(decodeURIComponent, "decodeURIComponent", 0, 0) +NJS_DEF_STRING(defineProperty, "defineProperty", 0, 0) +NJS_DEF_STRING(defineProperties, "defineProperties", 0, 0) +NJS_DEF_STRING(description, "description", 0, 0) +NJS_DEF_STRING(done, "done", 0, 0) +NJS_DEF_STRING(dump, "dump", 0, 0) +NJS_DEF_STRING(encode, "encode", 0, 0) +NJS_DEF_STRING(encodeInto, "encodeInto", 0, 0) +NJS_DEF_STRING(encodeURI, "encodeURI", 0, 0) +NJS_DEF_STRING(encodeURIComponent, "encodeURIComponent", 0, 0) +NJS_DEF_STRING(encoding, "encoding", 0, 0) +NJS_DEF_STRING(endsWith, "endsWith", 0, 0) +NJS_DEF_STRING(engine, "engine", 0, 0) +NJS_DEF_STRING(enumerable, "enumerable", 0, 0) +NJS_DEF_STRING(entries, "entries", 0, 0) +NJS_DEF_STRING(env, "env", 0, 0) +NJS_DEF_STRING(equals, "equals", 0, 0) +NJS_DEF_STRING(errors, "errors", 0, 0) +NJS_DEF_STRING(every, "every", 0, 0) +NJS_DEF_STRING(exec, "exec", 0, 0) +NJS_DEF_STRING(exp, "exp", 0, 0) +NJS_DEF_STRING(expm1, "expm1", 0, 0) +NJS_DEF_STRING(external, "external", 0, 0) +NJS_DEF_STRING(fatal, "fatal", 0, 0) +NJS_DEF_STRING(fileName, "fileName", 0, 0) +NJS_DEF_STRING(fill, "fill", 0, 0) +NJS_DEF_STRING(filter, "filter", 0, 0) +NJS_DEF_STRING(find, "find", 0, 0) +NJS_DEF_STRING(findIndex, "findIndex", 0, 0) +NJS_DEF_STRING(flags, "flags", 0, 0) +NJS_DEF_STRING(floor, "floor", 0, 0) +NJS_DEF_STRING(forEach, "forEach", 0, 0) +NJS_DEF_STRING(freeze, "freeze", 0, 0) +NJS_DEF_STRING(fromCharCode, "fromCharCode", 0, 0) +NJS_DEF_STRING(fromCodePoint, "fromCodePoint", 0, 0) +NJS_DEF_STRING(fround, "fround", 0, 0) +NJS_DEF_STRING(fulfilled, "fulfilled", 0, 0) +NJS_DEF_STRING(get, "get", 0, 0) +NJS_DEF_STRING(getDate, "getDate", 0, 0) +NJS_DEF_STRING(getDay, "getDay", 0, 0) +NJS_DEF_STRING(getFloat32, "getFloat32", 0, 0) +NJS_DEF_STRING(getFloat64, "getFloat64", 0, 0) +NJS_DEF_STRING(getFullYear, "getFullYear", 0, 0) +NJS_DEF_STRING(getHours, "getHours", 0, 0) +NJS_DEF_STRING(getInt16, "getInt16", 0, 0) +NJS_DEF_STRING(getInt32, "getInt32", 0, 0) +NJS_DEF_STRING(getInt8, "getInt8", 0, 0) +NJS_DEF_STRING(getMilliseconds, "getMilliseconds", 0, 0) +NJS_DEF_STRING(getMinutes, "getMinutes", 0, 0) +NJS_DEF_STRING(getOwnPropertyDescriptor, "getOwnPropertyDescriptor", 0, 0) +NJS_DEF_STRING(getOwnPropertyDescriptors, "getOwnPropertyDescriptors", 0, 0) +NJS_DEF_STRING(getOwnPropertyNames, "getOwnPropertyNames", 0, 0) +NJS_DEF_STRING(getOwnPropertySymbols, "getOwnPropertySymbols", 0, 0) +NJS_DEF_STRING(getPrototypeOf, "getPrototypeOf", 0, 0) +NJS_DEF_STRING(getSeconds, "getSeconds", 0, 0) +NJS_DEF_STRING(getTime, "getTime", 0, 0) +NJS_DEF_STRING(getTimezoneOffset, "getTimezoneOffset", 0, 0) +NJS_DEF_STRING(getUTCDate, "getUTCDate", 0, 0) +NJS_DEF_STRING(getUTCDay, "getUTCDay", 0, 0) +NJS_DEF_STRING(getUTCFullYear, "getUTCFullYear", 0, 0) +NJS_DEF_STRING(getUTCHours, "getUTCHours", 0, 0) +NJS_DEF_STRING(getUTCMilliseconds, "getUTCMilliseconds", 0, 0) +NJS_DEF_STRING(getUTCMinutes, "getUTCMinutes", 0, 0) +NJS_DEF_STRING(getUTCMonth, "getUTCMonth", 0, 0) +NJS_DEF_STRING(getUTCSeconds, "getUTCSeconds", 0, 0) +NJS_DEF_STRING(getUint16, "getUint16", 0, 0) +NJS_DEF_STRING(getUint32, "getUint32", 0, 0) +NJS_DEF_STRING(getUint8, "getUint8", 0, 0) +NJS_DEF_STRING(getMonth, "getMonth", 0, 0) +NJS_DEF_STRING(global, "global", 0, 0) +NJS_DEF_STRING(globalThis, "globalThis", 0, 0) +NJS_DEF_STRING(groups, "groups", 0, 0) +NJS_DEF_STRING(hasOwnProperty, "hasOwnProperty", 0, 0) +NJS_DEF_STRING(hasInstance, "hasInstance", 0, 0) +NJS_DEF_STRING(hypot, "hypot", 0, 0) +NJS_DEF_STRING(ignoreBOM, "ignoreBOM", 0, 0) +NJS_DEF_STRING(ignoreCase, "ignoreCase", 0, 0) +NJS_DEF_STRING(imul, "imul", 0, 0) +NJS_DEF_STRING(includes, "includes", 0, 0) +NJS_DEF_STRING(index, "index", 0, 0) +NJS_DEF_STRING(indexOf, "indexOf", 0, 0) +NJS_DEF_STRING(input, "input", 0, 0) +NJS_DEF_STRING(is, "is", 0, 0) +NJS_DEF_STRING(isArray, "isArray", 0, 0) +NJS_DEF_STRING(isBuffer, "isBuffer", 0, 0) +NJS_DEF_STRING(isConcatSpreadable, "isConcatSpreadable", 0, 0) +NJS_DEF_STRING(isEncoding, "isEncoding", 0, 0) +NJS_DEF_STRING(isExtensible, "isExtensible", 0, 0) +NJS_DEF_STRING(isFinite, "isFinite", 0, 0) +NJS_DEF_STRING(isFrozen, "isFrozen", 0, 0) +NJS_DEF_STRING(isInteger, "isInteger", 0, 0) +NJS_DEF_STRING(isNaN, "isNaN", 0, 0) +NJS_DEF_STRING(isPrototypeOf, "isPrototypeOf", 0, 0) +NJS_DEF_STRING(isSafeInteger, "isSafeInteger", 0, 0) +NJS_DEF_STRING(isSealed, "isSealed", 0, 0) +NJS_DEF_STRING(isView, "isView", 0, 0) +NJS_DEF_STRING(iterator, "iterator", 0, 0) +NJS_DEF_STRING(join, "join", 0, 0) +NJS_DEF_STRING(keyFor, "keyFor", 0, 0) +NJS_DEF_STRING(keys, "keys", 0, 0) +NJS_DEF_STRING(kill, "kill", 0, 0) +NJS_DEF_STRING(lastIndex, "lastIndex", 0, 0) +NJS_DEF_STRING(lastIndexOf, "lastIndexOf", 0, 0) +NJS_DEF_STRING(length, "length", 0, 0) +NJS_DEF_STRING(lineNumber, "lineNumber", 0, 0) +NJS_DEF_STRING(log, "log", 0, 0) +NJS_DEF_STRING(log10, "log10", 0, 0) +NJS_DEF_STRING(log1p, "log1p", 0, 0) +NJS_DEF_STRING(log2, "log2", 0, 0) +NJS_DEF_STRING(map, "map", 0, 0) +NJS_DEF_STRING(matchAll, "matchAll", 0, 0) +NJS_DEF_STRING(match, "match", 0, 0) +NJS_DEF_STRING(max, "max", 0, 0) +NJS_DEF_STRING(min, "min", 0, 0) +NJS_DEF_STRING(memoryStats, "memoryStats", 0, 0) +NJS_DEF_STRING(message, "message", 0, 0) +NJS_DEF_STRING(multiline, "multiline", 0, 0) +NJS_DEF_STRING(name, "name", 0, 0) +NJS_DEF_STRING(nblocks, "nblocks", 0, 0) +NJS_DEF_STRING(next, "next", 0, 0) +NJS_DEF_STRING(njs, "njs", 0, 0) +NJS_DEF_STRING(now, "now", 0, 0) +NJS_DEF_STRING(number, "number", 0, 0) +NJS_DEF_STRING(object, "object", 0, 0) +NJS_DEF_STRING(on, "on", 0, 0) +NJS_DEF_STRING(padEnd, "padEnd", 0, 0) +NJS_DEF_STRING(padStart, "padStart", 0, 0) +NJS_DEF_STRING(page_size, "page_size", 0, 0) +NJS_DEF_STRING(parse, "parse", 0, 0) +NJS_DEF_STRING(parseFloat, "parseFloat", 0, 0) +NJS_DEF_STRING(parseInt, "parseInt", 0, 0) +NJS_DEF_STRING(pid, "pid", 0, 0) +NJS_DEF_STRING(pop, "pop", 0, 0) +NJS_DEF_STRING(pow, "pow", 0, 0) +NJS_DEF_STRING(ppid, "ppid", 0, 0) +NJS_DEF_STRING(preventExtensions, "preventExtensions", 0, 0) +NJS_DEF_STRING(process, "process", 0, 0) +NJS_DEF_STRING(propertyIsEnumerable, "propertyIsEnumerable", 0, 0) +NJS_DEF_STRING(prototype, "prototype", 0, 0) +NJS_DEF_STRING(push, "push", 0, 0) +NJS_DEF_STRING(race, "race", 0, 0) +NJS_DEF_STRING(random, "random", 0, 0) +NJS_DEF_STRING(read, "read", 0, 0) +NJS_DEF_STRING(readDoubleBE, "readDoubleBE", 0, 0) +NJS_DEF_STRING(readDoubleLE, "readDoubleLE", 0, 0) +NJS_DEF_STRING(readFloatBE, "readFloatBE", 0, 0) +NJS_DEF_STRING(readFloatLE, "readFloatLE", 0, 0) +NJS_DEF_STRING(readInt16BE, "readInt16BE", 0, 0) +NJS_DEF_STRING(readInt16LE, "readInt16LE", 0, 0) +NJS_DEF_STRING(readInt32BE, "readInt32BE", 0, 0) +NJS_DEF_STRING(readInt32LE, "readInt32LE", 0, 0) +NJS_DEF_STRING(readInt8, "readInt8", 0, 0) +NJS_DEF_STRING(readIntBE, "readIntBE", 0, 0) +NJS_DEF_STRING(readIntLE, "readIntLE", 0, 0) +NJS_DEF_STRING(readUInt16BE, "readUInt16BE", 0, 0) +NJS_DEF_STRING(readUInt16LE, "readUInt16LE", 0, 0) +NJS_DEF_STRING(readUInt32BE, "readUInt32BE", 0, 0) +NJS_DEF_STRING(readUInt32LE, "readUInt32LE", 0, 0) +NJS_DEF_STRING(readUInt8, "readUInt8", 0, 0) +NJS_DEF_STRING(readUIntBE, "readUIntBE", 0, 0) +NJS_DEF_STRING(readUIntLE, "readUIntLE", 0, 0) +NJS_DEF_STRING(reason, "reason", 0, 0) +NJS_DEF_STRING(reduce, "reduce", 0, 0) +NJS_DEF_STRING(reduceRight, "reduceRight", 0, 0) +NJS_DEF_STRING(reject, "reject", 0, 0) +NJS_DEF_STRING(rejected, "rejected", 0, 0) +NJS_DEF_STRING(repeat, "repeat", 0, 0) +NJS_DEF_STRING(replace, "replace", 0, 0) +NJS_DEF_STRING(replaceAll, "replaceAll", 0, 0) +NJS_DEF_STRING(require, "require", 0, 0) +NJS_DEF_STRING(resolve, "resolve", 0, 0) +NJS_DEF_STRING(reverse, "reverse", 0, 0) +NJS_DEF_STRING(round, "round", 0, 0) +NJS_DEF_STRING(seal, "seal", 0, 0) +NJS_DEF_STRING(search, "search", 0, 0) +NJS_DEF_STRING(set, "set", 0, 0) +NJS_DEF_STRING(setDate, "setDate", 0, 0) +NJS_DEF_STRING(setFloat32, "setFloat32", 0, 0) +NJS_DEF_STRING(setFloat64, "setFloat64", 0, 0) +NJS_DEF_STRING(setFullYear, "setFullYear", 0, 0) +NJS_DEF_STRING(setHours, "setHours", 0, 0) +NJS_DEF_STRING(setInt16, "setInt16", 0, 0) +NJS_DEF_STRING(setInt32, "setInt32", 0, 0) +NJS_DEF_STRING(setInt8, "setInt8", 0, 0) +NJS_DEF_STRING(setMilliseconds, "setMilliseconds", 0, 0) +NJS_DEF_STRING(setMinutes, "setMinutes", 0, 0) +NJS_DEF_STRING(setMonth, "setMonth", 0, 0) +NJS_DEF_STRING(setPrototypeOf, "setPrototypeOf", 0, 0) +NJS_DEF_STRING(setSeconds, "setSeconds", 0, 0) +NJS_DEF_STRING(setTime, "setTime", 0, 0) +NJS_DEF_STRING(setUint16, "setUint16", 0, 0) +NJS_DEF_STRING(setUint32, "setUint32", 0, 0) +NJS_DEF_STRING(setUint8, "setUint8", 0, 0) +NJS_DEF_STRING(setUTCDate, "setUTCDate", 0, 0) +NJS_DEF_STRING(setUTCFullYear, "setUTCFullYear", 0, 0) +NJS_DEF_STRING(setUTCHours, "setUTCHours", 0, 0) +NJS_DEF_STRING(setUTCMilliseconds, "setUTCMilliseconds", 0, 0) +NJS_DEF_STRING(setUTCMinutes, "setUTCMinutes", 0, 0) +NJS_DEF_STRING(setUTCMonth, "setUTCMonth", 0, 0) +NJS_DEF_STRING(setUTCSeconds, "setUTCSeconds", 0, 0) +NJS_DEF_STRING(shift, "shift", 0, 0) +NJS_DEF_STRING(sign, "sign", 0, 0) +NJS_DEF_STRING(sin, "sin", 0, 0) +NJS_DEF_STRING(sinh, "sinh", 0, 0) +NJS_DEF_STRING(size, "size", 0, 0) +NJS_DEF_STRING(slice, "slice", 0, 0) +NJS_DEF_STRING(some, "some", 0, 0) +NJS_DEF_STRING(sort, "sort", 0, 0) +NJS_DEF_STRING(source, "source", 0, 0) +NJS_DEF_STRING(species, "species", 0, 0) +NJS_DEF_STRING(splice, "splice", 0, 0) +NJS_DEF_STRING(split, "split", 0, 0) +NJS_DEF_STRING(sqrt, "sqrt", 0, 0) +NJS_DEF_STRING(stack, "stack", 0, 0) +NJS_DEF_STRING(startsWith, "startsWith", 0, 0) +NJS_DEF_STRING(status, "status", 0, 0) +NJS_DEF_STRING(sticky, "sticky", 0, 0) +NJS_DEF_STRING(stream, "stream", 0, 0) +NJS_DEF_STRING(string, "string", 0, 0) +NJS_DEF_STRING(stringify, "stringify", 0, 0) +NJS_DEF_STRING(subarray, "subarray", 0, 0) +NJS_DEF_STRING(substr, "substr", 0, 0) +NJS_DEF_STRING(substring, "substring", 0, 0) +NJS_DEF_STRING(symbol, "symbol", 0, 0) +NJS_DEF_STRING(swap16, "swap16", 0, 0) +NJS_DEF_STRING(swap32, "swap32", 0, 0) +NJS_DEF_STRING(swap64, "swap64", 0, 0) +NJS_DEF_STRING(tan, "tan", 0, 0) +NJS_DEF_STRING(tanh, "tanh", 0, 0) +NJS_DEF_STRING(test, "test", 0, 0) +NJS_DEF_STRING(then, "then", 0, 0) +NJS_DEF_STRING(times, "times", 0, 0) +NJS_DEF_STRING(toDateString, "toDateString", 0, 0) +NJS_DEF_STRING(toExponential, "toExponential", 0, 0) +NJS_DEF_STRING(toFixed, "toFixed", 0, 0) +NJS_DEF_STRING(toISOString, "toISOString", 0, 0) +NJS_DEF_STRING(toJSON, "toJSON", 0, 0) +NJS_DEF_STRING(toLocaleDateString, "toLocaleDateString", 0, 0) +NJS_DEF_STRING(toLocaleString, "toLocaleString", 0, 0) +NJS_DEF_STRING(toLocaleTimeString, "toLocaleTimeString", 0, 0) +NJS_DEF_STRING(toLowerCase, "toLowerCase", 0, 0) +NJS_DEF_STRING(toPrimitive, "toPrimitive", 0, 0) +NJS_DEF_STRING(toPrecision, "toPrecision", 0, 0) +NJS_DEF_STRING(toReversed, "toReversed", 0, 0) +NJS_DEF_STRING(toSorted, "toSorted", 0, 0) +NJS_DEF_STRING(toSpliced, "toSpliced", 0, 0) +NJS_DEF_STRING(toStringTag, "toStringTag", 0, 0) +NJS_DEF_STRING(toString, "toString", 0, 0) +NJS_DEF_STRING(toTimeString, "toTimeString", 0, 0) +NJS_DEF_STRING(toUpperCase, "toUpperCase", 0, 0) +NJS_DEF_STRING(toUTCString, "toUTCString", 0, 0) +NJS_DEF_STRING(trimEnd, "trimEnd", 0, 0) +NJS_DEF_STRING(trimStart, "trimStart", 0, 0) +NJS_DEF_STRING(trim, "trim", 0, 0) +NJS_DEF_STRING(trunc, "trunc", 0, 0) +NJS_DEF_STRING(type, "type", 0, 0) +NJS_DEF_STRING(usec, "usec", 0, 0) +NJS_DEF_STRING(unscopables, "unscopables", 0, 0) +NJS_DEF_STRING(unshift, "unshift", 0, 0) +NJS_DEF_STRING(utf_8, "utf-8", 0, 0) +NJS_DEF_STRING(value, "value", 0, 0) +NJS_DEF_STRING(valueOf, "valueOf", 0, 0) +NJS_DEF_STRING(values, "values", 0, 0) +NJS_DEF_STRING(version, "version", 0, 0) +NJS_DEF_STRING(version_number, "version_number", 0, 0) +NJS_DEF_STRING(write, "write", 0, 0) +NJS_DEF_STRING(writable, "writable", 0, 0) +NJS_DEF_STRING(writeDoubleBE, "writeDoubleBE", 0, 0) +NJS_DEF_STRING(writeDoubleLE, "writeDoubleLE", 0, 0) +NJS_DEF_STRING(writeFloatBE, "writeFloatBE", 0, 0) +NJS_DEF_STRING(writeFloatLE, "writeFloatLE", 0, 0) +NJS_DEF_STRING(writeIntBE, "writeIntBE", 0, 0) +NJS_DEF_STRING(writeIntLE, "writeIntLE", 0, 0) +NJS_DEF_STRING(writeInt16BE, "writeInt16BE", 0, 0) +NJS_DEF_STRING(writeInt16LE, "writeInt16LE", 0, 0) +NJS_DEF_STRING(writeInt32BE, "writeInt32BE", 0, 0) +NJS_DEF_STRING(writeInt32LE, "writeInt32LE", 0, 0) +NJS_DEF_STRING(writeInt8, "writeInt8", 0, 0) +NJS_DEF_STRING(writeUIntBE, "writeUIntBE", 0, 0) +NJS_DEF_STRING(writeUIntLE, "writeUIntLE", 0, 0) +NJS_DEF_STRING(writeUInt16BE, "writeUInt16BE", 0, 0) +NJS_DEF_STRING(writeUInt16LE, "writeUInt16LE", 0, 0) +NJS_DEF_STRING(writeUInt32BE, "writeUInt32BE", 0, 0) +NJS_DEF_STRING(writeUInt32LE, "writeUInt32LE", 0, 0) +NJS_DEF_STRING(writeUInt8, "writeUInt8", 0, 0) +NJS_DEF_STRING(written, "written", 0, 0) diff --git a/src/njs_boolean.c b/src/njs_boolean.c index ba26f751..39119060 100644 --- a/src/njs_boolean.c +++ b/src/njs_boolean.c @@ -38,23 +38,16 @@ njs_boolean_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_object_prop_t njs_boolean_constructor_properties[] = +static const njs_object_prop_init_t njs_boolean_constructor_properties[] = { - { - .type = NJS_PROPERTY, - .name = njs_string("name"), - .u.value = njs_string("Boolean"), - .configurable = 1, - }, - - { - .type = NJS_PROPERTY, - .name = njs_string("length"), - .u.value = njs_value(NJS_NUMBER, 1, 1.0), - .configurable = 1, - }, - - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval("Boolean"), + NJS_OBJECT_PROP_VALUE_C), + + NJS_DECLARE_PROP_VALUE(STRING_length, njs_value(NJS_NUMBER, 1, 1.0), + NJS_OBJECT_PROP_VALUE_C), + + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -110,29 +103,36 @@ njs_boolean_prototype_to_string(njs_vm_t *vm, njs_value_t *args, } } - njs_value_assign(retval, njs_is_true(value) ? &njs_string_true - : &njs_string_false); + if (njs_is_true(value)) { + njs_atom_to_value(vm, retval, NJS_ATOM_STRING_true); + + } else { + njs_atom_to_value(vm, retval, NJS_ATOM_STRING_false); + } return NJS_OK; } -static const njs_object_prop_t njs_boolean_prototype_properties[] = +static const njs_object_prop_init_t njs_boolean_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("__proto__", njs_primitive_prototype_get_proto, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING___proto__, + njs_primitive_prototype_get_proto, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_NATIVE("valueOf", njs_boolean_prototype_value_of, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_valueOf, njs_boolean_prototype_value_of, + 0, 0), - NJS_DECLARE_PROP_NATIVE("toString", njs_boolean_prototype_to_string, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toString, + njs_boolean_prototype_to_string, 0, 0), }; -const njs_object_init_t njs_boolean_prototype_init = { +static const njs_object_init_t njs_boolean_prototype_init = { njs_boolean_prototype_properties, njs_nitems(njs_boolean_prototype_properties), }; diff --git a/src/njs_buffer.c b/src/njs_buffer.c index 3ce1b90a..3f0469e7 100644 --- a/src/njs_buffer.c +++ b/src/njs_buffer.c @@ -76,7 +76,7 @@ static njs_int_t njs_buffer_write_string(njs_vm_t *vm, njs_value_t *value, njs_typed_array_t *array, const njs_buffer_encoding_t *encoding, uint64_t offset, uint64_t length, njs_value_t *retval); static njs_int_t njs_buffer_fill(njs_vm_t *vm, njs_typed_array_t *array, - const njs_value_t *fill, const njs_value_t *encoding, uint64_t offset, + const njs_value_t *fill, njs_value_t *encoding, uint64_t offset, uint64_t end); static njs_int_t njs_buffer_fill_string(njs_vm_t *vm, const njs_value_t *value, njs_typed_array_t *array, const njs_buffer_encoding_t *encoding, @@ -86,14 +86,14 @@ static njs_int_t njs_buffer_fill_typed_array(njs_vm_t *vm, uint8_t *end); static njs_int_t njs_buffer(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t njs_buffer_constants(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t njs_buffer_constant(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t njs_buffer_init(njs_vm_t *vm); @@ -349,20 +349,17 @@ njs_buffer_from_object(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval) njs_value_t val, data, length; njs_typed_array_t *buffer; - static const njs_value_t string_length = njs_string("length"); static const njs_str_t str_buffer = njs_str("Buffer"); next: - ret = njs_value_property(vm, value, njs_value_arg(&string_length), - &length); + ret = njs_value_property(vm, value, NJS_ATOM_STRING_length, &length); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } if (ret == NJS_DECLINED) { - ret = njs_value_property(vm, value, njs_value_arg(&njs_string_type), - &val); + ret = njs_value_property(vm, value, NJS_ATOM_STRING_type, &val); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -372,14 +369,13 @@ next: return ret; } - njs_string_get(&val, &str); + njs_string_get(vm, &val, &str); if (!njs_strstr_eq(&str, &str_buffer)) { return NJS_DECLINED; } - ret = njs_value_property(vm, value, njs_value_arg(&njs_string_data), - &val); + ret = njs_value_property(vm, value, NJS_ATOM_STRING_data, &val); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -527,7 +523,7 @@ njs_buffer_from_string(njs_vm_t *vm, njs_value_t *value, return NJS_ERROR; } - njs_string_get(&dst, &str); + njs_string_get(vm, &dst, &str); buffer = njs_buffer_alloc(vm, str.length, 0); if (njs_slow_path(buffer == NULL)) { @@ -543,14 +539,14 @@ njs_buffer_from_string(njs_vm_t *vm, njs_value_t *value, static size_t -njs_buffer_decode_string_length(njs_value_t *value, +njs_buffer_decode_string_length(njs_vm_t *vm, njs_value_t *value, const njs_buffer_encoding_t *encoding) { size_t size; njs_str_t str; njs_string_prop_t string; - (void) njs_string_prop(&string, value); + (void) njs_string_prop(vm, &string, value); str.start = string.start; str.length = string.size; @@ -595,7 +591,7 @@ njs_buffer_byte_length(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - size = njs_buffer_decode_string_length(value, encoding); + size = njs_buffer_decode_string_length(vm, value, encoding); njs_set_number(retval, size); @@ -965,7 +961,7 @@ static njs_int_t njs_buffer_is_encoding(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - const njs_value_t *value; + njs_value_t *value; value = njs_arg(args, nargs, 1); njs_set_boolean(retval, njs_is_defined(value) @@ -977,7 +973,8 @@ njs_buffer_is_encoding(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t njs_buffer_prototype_length(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_typed_array_t *array; @@ -1703,7 +1700,7 @@ njs_buffer_write_string(njs_vm_t *vm, njs_value_t *value, return NJS_ERROR; } - njs_string_get(&dst, &str); + njs_string_get(vm, &dst, &str); start = &buffer->u.u8[array->offset + offset]; @@ -1812,7 +1809,7 @@ done: static njs_int_t njs_buffer_fill(njs_vm_t *vm, njs_typed_array_t *array, const njs_value_t *fill, - const njs_value_t *encode, uint64_t offset, uint64_t end) + njs_value_t *encode, uint64_t offset, uint64_t end) { double num; uint8_t *start, *stop; @@ -1887,7 +1884,7 @@ njs_buffer_fill_string(njs_vm_t *vm, const njs_value_t *value, return NJS_ERROR; } - njs_string_get(&dst, &str); + njs_string_get(vm, &dst, &str); if (str.length == 0) { memset(start, 0, end - start); @@ -1992,7 +1989,7 @@ njs_buffer_prototype_to_string(njs_vm_t *vm, njs_value_t *args, str.length = end - start; if (njs_slow_path(str.length == 0)) { - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -2173,7 +2170,7 @@ encoding: return ret; } - njs_string_get(&dst, &str); + njs_string_get(vm, &dst, &str); } else { src = njs_typed_array(value); @@ -2347,15 +2344,13 @@ njs_buffer_prototype_to_json(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, { u_char *p, *end; njs_int_t ret; - njs_value_t *value; + njs_value_t *value, setval; njs_value_t object, array; njs_array_t *arr; njs_object_t *obj; njs_typed_array_t *ta; njs_array_buffer_t *buffer; - static const njs_value_t string_buffer = njs_string("Buffer"); - ta = njs_buffer_slot(vm, njs_argument(args, 0), "this"); if (njs_slow_path(ta == NULL)) { return NJS_ERROR; @@ -2367,9 +2362,9 @@ njs_buffer_prototype_to_json(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } njs_set_object(&object, obj); + njs_atom_to_value(vm, &setval, NJS_ATOM_STRING_Buffer); - ret = njs_value_property_set(vm, &object, njs_value_arg(&njs_string_type), - njs_value_arg(&string_buffer)); + ret = njs_value_property_set(vm, &object, NJS_ATOM_STRING_type, &setval); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -2395,8 +2390,7 @@ njs_buffer_prototype_to_json(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_set_array(&array, arr); - ret = njs_value_property_set(vm, &object, njs_value_arg(&njs_string_data), - &array); + ret = njs_value_property_set(vm, &object, NJS_ATOM_STRING_data, &array); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -2408,10 +2402,10 @@ njs_buffer_prototype_to_json(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, const njs_buffer_encoding_t * -njs_buffer_encoding(njs_vm_t *vm, const njs_value_t *value, njs_bool_t throw) +njs_buffer_encoding(njs_vm_t *vm, njs_value_t *value, njs_bool_t throw) { - njs_str_t name; - njs_buffer_encoding_t *encoding; + njs_str_t name; + const njs_buffer_encoding_t *encoding; if (njs_slow_path(!njs_is_string(value))) { if (njs_is_defined(value)) { @@ -2422,7 +2416,7 @@ njs_buffer_encoding(njs_vm_t *vm, const njs_value_t *value, njs_bool_t throw) return &njs_buffer_encodings[0]; } - njs_string_get(value, &name); + njs_string_get(vm, value, &name); for (encoding = &njs_buffer_encodings[0]; encoding->name.length != 0; @@ -2449,7 +2443,7 @@ njs_buffer_decode_string(njs_vm_t *vm, const njs_value_t *value, njs_str_t str; njs_string_prop_t string; - (void) njs_string_prop(&string, value); + (void) njs_string_prop(vm, &string, value); str.start = string.start; str.length = string.size; @@ -2469,159 +2463,197 @@ njs_buffer_decode_string(njs_vm_t *vm, const njs_value_t *value, } -static const njs_object_prop_t njs_buffer_prototype_properties[] = +static const njs_object_prop_init_t njs_buffer_prototype_properties[] = { - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.value = njs_string("Buffer"), - .configurable = 1, - }, + NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, njs_ascii_strval("Buffer"), + NJS_OBJECT_PROP_VALUE_C), - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("length", njs_buffer_prototype_length, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_length, njs_buffer_prototype_length, 0, + 0), - NJS_DECLARE_PROP_NATIVE("readInt8", njs_buffer_prototype_read_int, 1, - njs_buffer_magic(1, 1, 1)), + NJS_DECLARE_PROP_NATIVE(STRING_readInt8, njs_buffer_prototype_read_int, + 1, njs_buffer_magic(1, 1, 1)), - NJS_DECLARE_PROP_NATIVE("readUInt8", njs_buffer_prototype_read_int, 1, - njs_buffer_magic(1, 0, 1)), + NJS_DECLARE_PROP_NATIVE(STRING_readUInt8, njs_buffer_prototype_read_int, + 1, njs_buffer_magic(1, 0, 1)), - NJS_DECLARE_PROP_NATIVE("readInt16LE", njs_buffer_prototype_read_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_readInt16LE, + njs_buffer_prototype_read_int, 1, njs_buffer_magic(2, 1, 1)), - NJS_DECLARE_PROP_NATIVE("readUInt16LE", njs_buffer_prototype_read_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_readUInt16LE, + njs_buffer_prototype_read_int, 1, njs_buffer_magic(2, 0, 1)), - NJS_DECLARE_PROP_NATIVE("readInt16BE", njs_buffer_prototype_read_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_readInt16BE, + njs_buffer_prototype_read_int, 1, njs_buffer_magic(2, 1, 0)), - NJS_DECLARE_PROP_NATIVE("readUInt16BE", njs_buffer_prototype_read_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_readUInt16BE, + njs_buffer_prototype_read_int, 1, njs_buffer_magic(2, 0, 0)), - NJS_DECLARE_PROP_NATIVE("readInt32LE", njs_buffer_prototype_read_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_readInt32LE, + njs_buffer_prototype_read_int, 1, njs_buffer_magic(4, 1, 1)), - NJS_DECLARE_PROP_NATIVE("readUInt32LE", njs_buffer_prototype_read_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_readUInt32LE, + njs_buffer_prototype_read_int, 1, njs_buffer_magic(4, 0, 1)), - NJS_DECLARE_PROP_NATIVE("readInt32BE", njs_buffer_prototype_read_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_readInt32BE, + njs_buffer_prototype_read_int, 1, njs_buffer_magic(4, 1, 0)), - NJS_DECLARE_PROP_NATIVE("readUInt32BE", njs_buffer_prototype_read_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_readUInt32BE, + njs_buffer_prototype_read_int, 1, njs_buffer_magic(4, 0, 0)), - NJS_DECLARE_PROP_NATIVE("readIntLE", njs_buffer_prototype_read_int, 2, + NJS_DECLARE_PROP_NATIVE(STRING_readIntLE, + njs_buffer_prototype_read_int, 2, njs_buffer_magic(0, 1, 1)), - NJS_DECLARE_PROP_NATIVE("readUIntLE", njs_buffer_prototype_read_int, 2, + NJS_DECLARE_PROP_NATIVE(STRING_readUIntLE, + njs_buffer_prototype_read_int, 2, njs_buffer_magic(0, 0, 1)), - NJS_DECLARE_PROP_NATIVE("readIntBE", njs_buffer_prototype_read_int, 2, + NJS_DECLARE_PROP_NATIVE(STRING_readIntBE, + njs_buffer_prototype_read_int, 2, njs_buffer_magic(0, 1, 0)), - NJS_DECLARE_PROP_NATIVE("readUIntBE", njs_buffer_prototype_read_int, 2, + NJS_DECLARE_PROP_NATIVE(STRING_readUIntBE, + njs_buffer_prototype_read_int, 2, njs_buffer_magic(0, 0, 0)), - NJS_DECLARE_PROP_NATIVE("readFloatLE", njs_buffer_prototype_read_float, 1, + NJS_DECLARE_PROP_NATIVE(STRING_readFloatLE, + njs_buffer_prototype_read_float, 1, njs_buffer_magic(4, 0, 1)), - NJS_DECLARE_PROP_NATIVE("readFloatBE", njs_buffer_prototype_read_float, 1, + NJS_DECLARE_PROP_NATIVE(STRING_readFloatBE, + njs_buffer_prototype_read_float, 1, njs_buffer_magic(4, 0, 0)), - NJS_DECLARE_PROP_NATIVE("readDoubleLE", njs_buffer_prototype_read_float, 1, + NJS_DECLARE_PROP_NATIVE(STRING_readDoubleLE, + njs_buffer_prototype_read_float, 1, njs_buffer_magic(8, 0, 1)), - NJS_DECLARE_PROP_NATIVE("readDoubleBE", njs_buffer_prototype_read_float, 1, + NJS_DECLARE_PROP_NATIVE(STRING_readDoubleBE, + njs_buffer_prototype_read_float, 1, njs_buffer_magic(8, 0, 0)), - NJS_DECLARE_PROP_NATIVE("writeInt8", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeInt8, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(1, 1, 0)), - NJS_DECLARE_PROP_NATIVE("writeUInt8", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeUInt8, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(1, 0, 0)), - NJS_DECLARE_PROP_NATIVE("writeInt16LE", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeInt16LE, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(2, 1, 1)), - NJS_DECLARE_PROP_NATIVE("writeUInt16LE", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeUInt16LE, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(2, 0, 1)), - NJS_DECLARE_PROP_NATIVE("writeInt16BE", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeInt16BE, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(2, 1, 0)), - NJS_DECLARE_PROP_NATIVE("writeUInt16BE", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeUInt16BE, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(2, 0, 0)), - NJS_DECLARE_PROP_NATIVE("writeInt32LE", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeInt32LE, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(4, 1, 1)), - NJS_DECLARE_PROP_NATIVE("writeUInt32LE", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeUInt32LE, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(4, 0, 1)), - NJS_DECLARE_PROP_NATIVE("writeInt32BE", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeInt32BE, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(4, 1, 0)), - NJS_DECLARE_PROP_NATIVE("writeUInt32BE", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeUInt32BE, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(4, 0, 0)), - NJS_DECLARE_PROP_NATIVE("writeIntLE", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeIntLE, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(0, 1, 1)), - NJS_DECLARE_PROP_NATIVE("writeUIntLE", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeUIntLE, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(0, 0, 1)), - NJS_DECLARE_PROP_NATIVE("writeIntBE", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeIntBE, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(0, 1, 0)), - NJS_DECLARE_PROP_NATIVE("writeUIntBE", njs_buffer_prototype_write_int, 1, + NJS_DECLARE_PROP_NATIVE(STRING_writeUIntBE, + njs_buffer_prototype_write_int, 1, njs_buffer_magic(0, 0, 0)), - NJS_DECLARE_PROP_NATIVE("writeFloatLE", njs_buffer_prototype_write_float, + NJS_DECLARE_PROP_NATIVE(STRING_writeFloatLE, + njs_buffer_prototype_write_float, 1, njs_buffer_magic(4, 0, 1)), - NJS_DECLARE_PROP_NATIVE("writeFloatBE", njs_buffer_prototype_write_float, + NJS_DECLARE_PROP_NATIVE(STRING_writeFloatBE, + njs_buffer_prototype_write_float, 1, njs_buffer_magic(4, 0, 0)), - NJS_DECLARE_PROP_NATIVE("writeDoubleLE", njs_buffer_prototype_write_float, + NJS_DECLARE_PROP_NATIVE(STRING_writeDoubleLE, + njs_buffer_prototype_write_float, 1, njs_buffer_magic(8, 0, 1)), - NJS_DECLARE_PROP_NATIVE("writeDoubleBE", njs_buffer_prototype_write_float, + NJS_DECLARE_PROP_NATIVE(STRING_writeDoubleBE, + njs_buffer_prototype_write_float, 1, njs_buffer_magic(8, 0, 0)), - NJS_DECLARE_PROP_NATIVE("write", njs_buffer_prototype_write, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_write, njs_buffer_prototype_write, 1, 0), - NJS_DECLARE_PROP_NATIVE("fill", njs_buffer_prototype_fill, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_fill, njs_buffer_prototype_fill, 1, 0), - NJS_DECLARE_PROP_NATIVE("toString", njs_buffer_prototype_to_string, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toString, njs_buffer_prototype_to_string, + 0, 0), - NJS_DECLARE_PROP_NATIVE("compare", njs_buffer_prototype_compare, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_compare, njs_buffer_prototype_compare, 1, + 0), - NJS_DECLARE_PROP_NATIVE("copy", njs_buffer_prototype_copy, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_copy, njs_buffer_prototype_copy, 1, 0), - NJS_DECLARE_PROP_NATIVE("equals", njs_buffer_prototype_equals, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_equals, njs_buffer_prototype_equals, 1, + 0), - NJS_DECLARE_PROP_NATIVE("indexOf", njs_buffer_prototype_index_of, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_indexOf, njs_buffer_prototype_index_of, + 1, 0), - NJS_DECLARE_PROP_NATIVE("lastIndexOf", njs_buffer_prototype_index_of, 1, - 1), + NJS_DECLARE_PROP_NATIVE(STRING_lastIndexOf, + njs_buffer_prototype_index_of, 1, 1), - NJS_DECLARE_PROP_NATIVE("includes", njs_buffer_prototype_includes, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_includes, njs_buffer_prototype_includes, 1, + 0), - NJS_DECLARE_PROP_NATIVE("subarray", njs_buffer_prototype_slice, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_subarray, njs_buffer_prototype_slice, 2, + 0), - NJS_DECLARE_PROP_NATIVE("slice", njs_buffer_prototype_slice, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_slice, njs_buffer_prototype_slice, 2, 0), - NJS_DECLARE_PROP_NATIVE("swap16", njs_buffer_prototype_swap, 0, 2), + NJS_DECLARE_PROP_NATIVE(STRING_swap16, njs_buffer_prototype_swap, 0, 2), - NJS_DECLARE_PROP_NATIVE("swap32", njs_buffer_prototype_swap, 0, 4), + NJS_DECLARE_PROP_NATIVE(STRING_swap32, njs_buffer_prototype_swap, 0, 4), - NJS_DECLARE_PROP_NATIVE("swap64", njs_buffer_prototype_swap, 0, 8), + NJS_DECLARE_PROP_NATIVE(STRING_swap64, njs_buffer_prototype_swap, 0, 8), - NJS_DECLARE_PROP_NATIVE("toJSON", njs_buffer_prototype_to_json, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toJSON, njs_buffer_prototype_to_json, 0, + 0), }; @@ -2631,31 +2663,36 @@ const njs_object_init_t njs_buffer_prototype_init = { }; -static const njs_object_prop_t njs_buffer_constructor_properties[] = +static const njs_object_prop_init_t njs_buffer_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(0), NJS_DECLARE_PROP_NAME("Buffer"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_NATIVE("alloc", njs_buffer_alloc_safe, 0, 1), + NJS_DECLARE_PROP_NATIVE(STRING_alloc, njs_buffer_alloc_safe, 0, 1), - NJS_DECLARE_PROP_NATIVE("allocUnsafe", njs_buffer_alloc_safe, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_allocUnsafe, njs_buffer_alloc_safe, 0, + 0), - NJS_DECLARE_PROP_LNATIVE("allocUnsafeSlow", njs_buffer_alloc_safe, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_allocUnsafeSlow, njs_buffer_alloc_safe, + 1, 0), - NJS_DECLARE_PROP_NATIVE("byteLength", njs_buffer_byte_length, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_byteLength, njs_buffer_byte_length, 1, + 0), - NJS_DECLARE_PROP_NATIVE("compare", njs_buffer_compare, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_compare, njs_buffer_compare, 2, 0), - NJS_DECLARE_PROP_NATIVE("concat", njs_buffer_concat, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_concat, njs_buffer_concat, 1, 0), - NJS_DECLARE_PROP_NATIVE("from", njs_buffer_from, 3, 0), + NJS_DECLARE_PROP_NATIVE(STRING_from, njs_buffer_from, 3, 0), - NJS_DECLARE_PROP_NATIVE("isBuffer", njs_buffer_is_buffer, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_isBuffer, njs_buffer_is_buffer, 1, 0), - NJS_DECLARE_PROP_NATIVE("isEncoding", njs_buffer_is_encoding, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_isEncoding, njs_buffer_is_encoding, 1, + 0), }; @@ -2673,14 +2710,15 @@ const njs_object_type_init_t njs_buffer_type_init = { }; -static const njs_object_prop_t njs_buffer_constants_properties[] = +static const njs_object_prop_init_t njs_buffer_constants_properties[] = { - NJS_DECLARE_PROP_VALUE("MAX_LENGTH", njs_value(NJS_NUMBER, 1, INT32_MAX), + NJS_DECLARE_PROP_VALUE(STRING_MAX_LENGTH, + njs_value(NJS_NUMBER, 1, INT32_MAX), NJS_OBJECT_PROP_VALUE_E), - NJS_DECLARE_PROP_LVALUE("MAX_STRING_LENGTH", - njs_value(NJS_NUMBER, 1, NJS_STRING_MAX_LENGTH), - NJS_OBJECT_PROP_VALUE_E), + NJS_DECLARE_PROP_VALUE(STRING_MAX_STRING_LENGTH, + njs_value(NJS_NUMBER, 1, NJS_STRING_MAX_LENGTH), + NJS_OBJECT_PROP_VALUE_E), }; @@ -2691,26 +2729,26 @@ static const njs_object_init_t njs_buffer_constants_init = { static njs_int_t -njs_buffer(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *unused, njs_value_t *retval) +njs_buffer(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t atom_id, + njs_value_t *value, njs_value_t *unused, njs_value_t *retval) { - return njs_object_prop_init(vm, &njs_buffer_constructor_init, prop, value, - retval); + return njs_object_prop_init(vm, &njs_buffer_constructor_init, prop, atom_id, + value, retval); } static njs_int_t -njs_buffer_constants(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *unused, njs_value_t *retval) +njs_buffer_constants(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t atom_id, + njs_value_t *value, njs_value_t *unused, njs_value_t *retval) { - return njs_object_prop_init(vm, &njs_buffer_constants_init, prop, value, - retval); + return njs_object_prop_init(vm, &njs_buffer_constants_init, prop, atom_id, + value, retval); } static njs_int_t -njs_buffer_constant(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *unused, njs_value_t *retval) +njs_buffer_constant(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t not_used, + njs_value_t *value, njs_value_t *unused, njs_value_t *retval) { njs_value_number_set(retval, njs_vm_prop_magic32(prop)); diff --git a/src/njs_buffer.h b/src/njs_buffer.h index 696653c2..0ac4db79 100644 --- a/src/njs_buffer.h +++ b/src/njs_buffer.h @@ -27,7 +27,7 @@ njs_int_t njs_buffer_new(njs_vm_t *vm, njs_value_t *value, const u_char *start, uint32_t size); const njs_buffer_encoding_t *njs_buffer_encoding(njs_vm_t *vm, - const njs_value_t *value, njs_bool_t thrw); + njs_value_t *value, njs_bool_t thrw); njs_int_t njs_buffer_decode_string(njs_vm_t *vm, const njs_value_t *value, njs_value_t *dst, const njs_buffer_encoding_t *encoding); diff --git a/src/njs_builtin.c b/src/njs_builtin.c index 279c2158..230b4c1c 100644 --- a/src/njs_builtin.c +++ b/src/njs_builtin.c @@ -18,7 +18,7 @@ typedef struct { njs_function_t *func; - njs_lvlhsh_t keys; + njs_flathsh_t keys; njs_str_t match; } njs_builtin_traverse_t; @@ -30,10 +30,10 @@ typedef struct { static njs_int_t njs_global_this_prop_handler(njs_vm_t *vm, - njs_object_prop_t *self, njs_value_t *global, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *self, uint32_t atom_id, njs_value_t *global, + njs_value_t *setval, njs_value_t *retval); -static njs_int_t njs_env_hash_init(njs_vm_t *vm, njs_lvlhsh_t *hash, +static njs_int_t njs_env_hash_init(njs_vm_t *vm, njs_flathsh_t *hash, char **environment); @@ -132,7 +132,7 @@ static njs_signal_entry_t njs_signals_table[] = { njs_inline njs_int_t -njs_object_hash_init(njs_vm_t *vm, njs_lvlhsh_t *hash, +njs_object_hash_init(njs_vm_t *vm, njs_flathsh_t *hash, const njs_object_init_t *init) { return njs_object_hash_create(vm, hash, init->properties, init->items); @@ -158,9 +158,13 @@ njs_builtin_objects_create(njs_vm_t *vm) vm->shared = shared; - njs_lvlhsh_init(&shared->keywords_hash); njs_lvlhsh_init(&shared->values_hash); + vm->atom_id_generator = njs_atom_hash_init(vm); + if (njs_slow_path(vm->atom_id_generator == 0xffffffff)) { + return NJS_ERROR; + } + pattern = njs_regexp_pattern_create(vm, (u_char *) "(?:)", njs_length("(?:)"), 0); if (njs_slow_path(pattern == NULL)) { @@ -245,6 +249,16 @@ njs_builtin_objects_create(njs_vm_t *vm) prototype = njs_shared_prototype(shared, i); *prototype = njs_object_type_init[i]->prototype_value; + if (njs_object_type_init[i] == &njs_boolean_type_init) { + prototype->object_value.value = njs_value(NJS_BOOLEAN, 0, 0.0); + + } else if (njs_object_type_init[i] == &njs_number_type_init) { + prototype->object_value.value = njs_value(NJS_NUMBER, 0, 0.0); + + } else if (njs_object_type_init[i] == &njs_string_type_init) { + njs_set_empty_string(vm, &prototype->object_value.value); + } + ret = njs_object_hash_init(vm, &prototype->object.shared_hash, njs_object_type_init[i]->prototype_props); if (njs_slow_path(ret != NJS_OK)) { @@ -306,10 +320,10 @@ njs_builtin_traverse(njs_vm_t *vm, njs_traverse_t *traverse, void *data) njs_int_t ret, n; njs_str_t name; njs_bool_t symbol; - njs_value_t key, *value; + njs_value_t key, *value, prop_name; njs_function_t *func, *target; njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + njs_flathsh_query_t lhq; njs_builtin_traverse_t *ctx; njs_traverse_t *path[NJS_TRAVERSE_MAX_DEPTH]; u_char buf[256]; @@ -356,13 +370,17 @@ njs_builtin_traverse(njs_vm_t *vm, njs_traverse_t *traverse, void *data) do { symbol = 0; - key = path[n]->prop->name; + + ret = njs_atom_to_value(vm, &key, path[n]->atom_id); + if (ret != NJS_OK) { + return NJS_ERROR; + } if (njs_slow_path(njs_is_symbol(&key))) { symbol = 1; key = *njs_symbol_description(&key); if (njs_is_undefined(&key)) { - key = njs_string_empty; + njs_set_empty_string(vm, &key); } } @@ -371,7 +389,7 @@ njs_builtin_traverse(njs_vm_t *vm, njs_traverse_t *traverse, void *data) return NJS_OK; } - njs_string_get(&key, &name); + njs_string_get(vm, &key, &name); if (njs_slow_path((p + name.length + 3) > end)) { njs_type_error(vm, "njs_builtin_traverse() key is too long"); @@ -415,24 +433,23 @@ njs_builtin_traverse(njs_vm_t *vm, njs_traverse_t *traverse, void *data) /* NJS_BUILTIN_TRAVERSE_KEYS. */ - prop = njs_object_prop_alloc(vm, &njs_value_undefined, &njs_value_null, 0); + prop = njs_object_prop_alloc(vm, &njs_value_null, 0); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } - ret = njs_string_create(vm, &prop->name, buf, p - buf); + ret = njs_atom_string_create(vm, &prop_name, buf, p - buf); if (njs_slow_path(ret != NJS_OK)) { return ret; } lhq.value = prop; - njs_string_get(&prop->name, &lhq.key); - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); + lhq.key_hash = prop_name.atom_id; lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(&ctx->keys, &lhq); + ret = njs_flathsh_unique_insert(&ctx->keys, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert/replace failed"); return NJS_ERROR; @@ -503,11 +520,9 @@ njs_builtin_match_native_function(njs_vm_t *vm, njs_function_t *function, for (i = NJS_OBJ_TYPE_HIDDEN_MIN; i < NJS_OBJ_TYPE_HIDDEN_MAX; i++) { njs_set_object(&value, &njs_vm_ctor(vm, i).object); - ret = njs_value_property(vm, &value, njs_value_arg(&njs_string_name), - &tag); - + ret = njs_value_property(vm, &value, NJS_ATOM_STRING_name, &tag); if (ret == NJS_OK && njs_is_string(&tag)) { - njs_string_get(&tag, &ctx.match); + njs_string_get(vm, &tag, &ctx.match); } ret = njs_object_traverse(vm, njs_object(&value), &ctx, @@ -560,7 +575,7 @@ njs_builtin_match_native_function(njs_vm_t *vm, njs_function_t *function, ret = njs_object_string_tag(vm, &value, &tag); if (ret == NJS_OK && njs_is_string(&tag)) { - njs_string_get(&tag, &ctx.match); + njs_string_get(vm, &tag, &ctx.match); } ret = njs_object_traverse(vm, njs_object(&value), &ctx, @@ -651,7 +666,7 @@ njs_ext_on(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - njs_string_get(value, &type); + njs_string_get(vm, value, &type); i = 0; n = sizeof(hooks) / sizeof(hooks[0]); @@ -683,19 +698,14 @@ njs_ext_on(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t -njs_ext_memory_stats(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *unused, njs_value_t *unused2, njs_value_t *retval) +njs_ext_memory_stats(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *unused2, njs_value_t *unused3, njs_value_t *retval) { njs_int_t ret; njs_value_t object, value; njs_object_t *stat; njs_mp_stat_t mp_stat; - static const njs_value_t size_string = njs_string("size"); - static const njs_value_t nblocks_string = njs_string("nblocks"); - static const njs_value_t page_string = njs_string("page_size"); - static const njs_value_t cluster_string = njs_string("cluster_size"); - stat = njs_object_alloc(vm); if (njs_slow_path(stat == NULL)) { return NJS_ERROR; @@ -707,23 +717,21 @@ njs_ext_memory_stats(njs_vm_t *vm, njs_object_prop_t *prop, njs_set_number(&value, mp_stat.size); - ret = njs_value_property_set(vm, &object, njs_value_arg(&size_string), - &value); + ret = njs_value_property_set(vm, &object, NJS_ATOM_STRING_size, &value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } njs_set_number(&value, mp_stat.nblocks); - ret = njs_value_property_set(vm, &object, njs_value_arg(&nblocks_string), - &value); + ret = njs_value_property_set(vm, &object, NJS_ATOM_STRING_nblocks, &value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } njs_set_number(&value, mp_stat.cluster_size); - ret = njs_value_property_set(vm, &object, njs_value_arg(&cluster_string), + ret = njs_value_property_set(vm, &object, NJS_ATOM_STRING_cluster_size, &value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; @@ -731,8 +739,7 @@ njs_ext_memory_stats(njs_vm_t *vm, njs_object_prop_t *prop, njs_set_number(&value, mp_stat.page_size); - ret = njs_value_property_set(vm, &object, njs_value_arg(&page_string), - &value); + ret = njs_value_property_set(vm, &object, NJS_ATOM_STRING_page_size, &value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -747,32 +754,25 @@ njs_ext_memory_stats(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t njs_global_this_prop_handler(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *global, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, njs_value_t *global, njs_value_t *setval, + njs_value_t *retval) { - njs_int_t ret; njs_value_t *value; njs_variable_t *var; njs_function_t *function; njs_rbtree_node_t *rb_node; - njs_lvlhsh_query_t lhq; njs_variable_node_t *node, var_node; if (retval == NULL) { return NJS_DECLINED; } - njs_string_get(&prop->name, &lhq.key); - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); - lhq.proto = &njs_lexer_hash_proto; + var_node.key = atom_id; - ret = njs_lvlhsh_find(&vm->shared->keywords_hash, &lhq); - - if (njs_slow_path(ret != NJS_OK || lhq.value == NULL)) { + if (njs_slow_path(vm->global_scope == NULL)) { return NJS_DECLINED; } - var_node.key = (uintptr_t) lhq.value; - rb_node = njs_rbtree_find(&vm->global_scope->variables, &var_node.node); if (rb_node == NULL) { return NJS_DECLINED; @@ -808,12 +808,12 @@ njs_global_this_prop_handler(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -njs_global_this_object(njs_vm_t *vm, njs_object_prop_t *self, +njs_global_this_object(njs_vm_t *vm, njs_object_prop_t *self, uint32_t atom_id, njs_value_t *global, njs_value_t *setval, njs_value_t *retval) { - njs_int_t ret; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; if (retval == NULL) { return NJS_DECLINED; @@ -825,7 +825,7 @@ njs_global_this_object(njs_vm_t *vm, njs_object_prop_t *self, njs_value_assign(retval, setval); } - prop = njs_object_prop_alloc(vm, &self->name, retval, 1); + prop = njs_object_prop_alloc(vm, retval, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -834,13 +834,12 @@ njs_global_this_object(njs_vm_t *vm, njs_object_prop_t *self, prop->enumerable = self->enumerable; lhq.value = prop; - njs_string_get(&self->name, &lhq.key); - lhq.key_hash = njs_prop_magic32(self); + lhq.key_hash = atom_id; lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(njs_object_hash(global), &lhq); + ret = njs_flathsh_unique_insert(njs_object_hash(global), &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert/replace failed"); return NJS_ERROR; @@ -851,13 +850,13 @@ njs_global_this_object(njs_vm_t *vm, njs_object_prop_t *self, static njs_int_t -njs_top_level_object(njs_vm_t *vm, njs_object_prop_t *self, +njs_top_level_object(njs_vm_t *vm, njs_object_prop_t *self, uint32_t atom_id, njs_value_t *global, njs_value_t *setval, njs_value_t *retval) { - njs_int_t ret; - njs_object_t *object; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_object_t *object; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; if (njs_slow_path(setval != NULL)) { njs_value_assign(retval, setval); @@ -877,7 +876,7 @@ njs_top_level_object(njs_vm_t *vm, njs_object_prop_t *self, object->__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_OBJECT); } - prop = njs_object_prop_alloc(vm, &self->name, retval, 1); + prop = njs_object_prop_alloc(vm, retval, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -886,13 +885,12 @@ njs_top_level_object(njs_vm_t *vm, njs_object_prop_t *self, prop->enumerable = self->enumerable; lhq.value = prop; - njs_string_get(&self->name, &lhq.key); - lhq.key_hash = njs_prop_magic32(self); + lhq.key_hash = atom_id; lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(njs_object_hash(global), &lhq); + ret = njs_flathsh_unique_insert(njs_object_hash(global), &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert/replace failed"); return NJS_ERROR; @@ -904,12 +902,13 @@ njs_top_level_object(njs_vm_t *vm, njs_object_prop_t *self, static njs_int_t njs_top_level_constructor(njs_vm_t *vm, njs_object_prop_t *self, - njs_value_t *global, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, njs_value_t *global, njs_value_t *setval, + njs_value_t *retval) { - njs_int_t ret; - njs_function_t *ctor; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_function_t *ctor; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; if (njs_slow_path(setval != NULL)) { njs_value_assign(retval, setval); @@ -926,7 +925,7 @@ njs_top_level_constructor(njs_vm_t *vm, njs_object_prop_t *self, return NJS_OK; } - prop = njs_object_prop_alloc(vm, &self->name, retval, 1); + prop = njs_object_prop_alloc(vm, retval, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -935,13 +934,12 @@ njs_top_level_constructor(njs_vm_t *vm, njs_object_prop_t *self, prop->enumerable = 0; lhq.value = prop; - njs_string_get(&self->name, &lhq.key); - lhq.key_hash = njs_prop_magic32(self); + lhq.key_hash = atom_id; lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(njs_object_hash(global), &lhq); + ret = njs_flathsh_unique_insert(njs_object_hash(global), &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert/replace failed"); return NJS_ERROR; @@ -951,227 +949,205 @@ njs_top_level_constructor(njs_vm_t *vm, njs_object_prop_t *self, } -static const njs_object_prop_t njs_global_this_object_properties[] = +static const njs_object_prop_init_t njs_global_this_object_properties[] = { - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.value = njs_string("global"), - .configurable = 1, - }, + NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, njs_ascii_strval("global"), + NJS_OBJECT_PROP_VALUE_C), /* Global aliases. */ - NJS_DECLARE_PROP_HANDLER("global", njs_global_this_object, 0, - NJS_GLOBAL_HASH, NJS_OBJECT_PROP_VALUE_ECW), + NJS_DECLARE_PROP_HANDLER(STRING_global, njs_global_this_object, 0, + NJS_OBJECT_PROP_VALUE_ECW), - NJS_DECLARE_PROP_HANDLER("globalThis", njs_global_this_object, 0, - NJS_GLOBAL_THIS_HASH, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_globalThis, njs_global_this_object, 0, + NJS_OBJECT_PROP_VALUE_CW), /* Global constants. */ - NJS_DECLARE_PROP_VALUE("NaN", njs_value(NJS_NUMBER, 0, NAN), 0), + NJS_DECLARE_PROP_VALUE(STRING_NaN, njs_value(NJS_NUMBER, 0, NAN), 0), - NJS_DECLARE_PROP_VALUE("Infinity", njs_value(NJS_NUMBER, 1, INFINITY), 0), + NJS_DECLARE_PROP_VALUE(STRING_Infinity, + njs_value(NJS_NUMBER, 1, INFINITY), 0), - NJS_DECLARE_PROP_VALUE("undefined", njs_value(NJS_UNDEFINED, 0, NAN), 0), + NJS_DECLARE_PROP_VALUE(STRING_undefined, + njs_value(NJS_UNDEFINED, 0, NAN), 0), /* Global functions. */ - NJS_DECLARE_PROP_NATIVE("isFinite", njs_number_global_is_finite, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_isFinite, njs_number_global_is_finite, 1, + 0), - NJS_DECLARE_PROP_NATIVE("isNaN", njs_number_global_is_nan, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_isNaN, njs_number_global_is_nan, 1, 0), - NJS_DECLARE_PROP_NATIVE("parseFloat", njs_number_parse_float, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_parseFloat, njs_number_parse_float, 1, + 0), - NJS_DECLARE_PROP_NATIVE("parseInt", njs_number_parse_int, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_parseInt, njs_number_parse_int, 2, 0), - NJS_DECLARE_PROP_NATIVE("toString", njs_object_prototype_to_string, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toString, njs_object_prototype_to_string, + 0, 0), - NJS_DECLARE_PROP_NATIVE("encodeURI", njs_string_encode_uri, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_encodeURI, njs_string_encode_uri, 1, 0), - NJS_DECLARE_PROP_LNATIVE("encodeURIComponent", njs_string_encode_uri, 1, 1), + NJS_DECLARE_PROP_NATIVE(STRING_encodeURIComponent, + njs_string_encode_uri, 1, 1), - NJS_DECLARE_PROP_NATIVE("decodeURI", njs_string_decode_uri, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_decodeURI, njs_string_decode_uri, 1, 0), - NJS_DECLARE_PROP_LNATIVE("decodeURIComponent", njs_string_decode_uri, 1, 1), + NJS_DECLARE_PROP_NATIVE(STRING_decodeURIComponent, + njs_string_decode_uri, 1, 1), - NJS_DECLARE_PROP_NATIVE("atob", njs_string_atob, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_atob, njs_string_atob, 1, 0), - NJS_DECLARE_PROP_NATIVE("btoa", njs_string_btoa, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_btoa, njs_string_btoa, 1, 0), - NJS_DECLARE_PROP_NATIVE("eval", njs_eval_function, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_eval, njs_eval_function, 1, 0), - NJS_DECLARE_PROP_NATIVE("require", njs_module_require, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_require, njs_module_require, 1, 0), /* Global objects. */ - NJS_DECLARE_PROP_HANDLER("njs", njs_top_level_object, NJS_OBJECT_NJS, - NJS_NJS_HASH, NJS_OBJECT_PROP_VALUE_ECW), + NJS_DECLARE_PROP_HANDLER(STRING_njs, njs_top_level_object, + NJS_OBJECT_NJS, NJS_OBJECT_PROP_VALUE_ECW), - NJS_DECLARE_PROP_HANDLER("process", njs_top_level_object, - NJS_OBJECT_PROCESS, NJS_PROCESS_HASH, - NJS_OBJECT_PROP_VALUE_ECW), + NJS_DECLARE_PROP_HANDLER(STRING_process, njs_top_level_object, + NJS_OBJECT_PROCESS, NJS_OBJECT_PROP_VALUE_ECW), - NJS_DECLARE_PROP_HANDLER("Math", njs_top_level_object, - NJS_OBJECT_MATH, NJS_MATH_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_Math, njs_top_level_object, + NJS_OBJECT_MATH, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("JSON", njs_top_level_object, - NJS_OBJECT_JSON, NJS_JSON_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_JSON, njs_top_level_object, + NJS_OBJECT_JSON, NJS_OBJECT_PROP_VALUE_CW), #ifdef NJS_TEST262 - NJS_DECLARE_PROP_HANDLER("$262", njs_top_level_object, - NJS_OBJECT_262, NJS_262_HASH, - NJS_OBJECT_PROP_VALUE_ECW), + NJS_DECLARE_PROP_HANDLER(STRING__262, njs_top_level_object, + NJS_OBJECT_262, NJS_OBJECT_PROP_VALUE_ECW), #endif /* Global constructors. */ - NJS_DECLARE_PROP_HANDLER("Object", njs_top_level_constructor, - NJS_OBJ_TYPE_OBJECT, NJS_OBJECT_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_Object, njs_top_level_constructor, + NJS_OBJ_TYPE_OBJECT, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Array", njs_top_level_constructor, - NJS_OBJ_TYPE_ARRAY, NJS_ARRAY_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_Array, njs_top_level_constructor, + NJS_OBJ_TYPE_ARRAY, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("ArrayBuffer", njs_top_level_constructor, - NJS_OBJ_TYPE_ARRAY_BUFFER, NJS_ARRAY_BUFFER_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_ArrayBuffer, njs_top_level_constructor, + NJS_OBJ_TYPE_ARRAY_BUFFER, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("DataView", njs_top_level_constructor, - NJS_OBJ_TYPE_DATA_VIEW, NJS_DATA_VIEW_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_DataView, njs_top_level_constructor, + NJS_OBJ_TYPE_DATA_VIEW, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("TextDecoder", njs_top_level_constructor, - NJS_OBJ_TYPE_TEXT_DECODER, NJS_TEXT_DECODER_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_TextDecoder, njs_top_level_constructor, + NJS_OBJ_TYPE_TEXT_DECODER, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("TextEncoder", njs_top_level_constructor, - NJS_OBJ_TYPE_TEXT_ENCODER, NJS_TEXT_ENCODER_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_TextEncoder, njs_top_level_constructor, + NJS_OBJ_TYPE_TEXT_ENCODER, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Buffer", njs_top_level_constructor, - NJS_OBJ_TYPE_BUFFER, NJS_BUFFER_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_Buffer, njs_top_level_constructor, + NJS_OBJ_TYPE_BUFFER, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Uint8Array", njs_top_level_constructor, - NJS_OBJ_TYPE_UINT8_ARRAY, NJS_UINT8ARRAY_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_Uint8Array, njs_top_level_constructor, + NJS_OBJ_TYPE_UINT8_ARRAY, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Uint16Array", njs_top_level_constructor, - NJS_OBJ_TYPE_UINT16_ARRAY, NJS_UINT16ARRAY_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_Uint16Array, njs_top_level_constructor, + NJS_OBJ_TYPE_UINT16_ARRAY, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Uint32Array", njs_top_level_constructor, - NJS_OBJ_TYPE_UINT32_ARRAY, NJS_UINT32ARRAY_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_Uint32Array, njs_top_level_constructor, + NJS_OBJ_TYPE_UINT32_ARRAY, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Int8Array", njs_top_level_constructor, - NJS_OBJ_TYPE_INT8_ARRAY, NJS_INT8ARRAY_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_Int8Array, njs_top_level_constructor, + NJS_OBJ_TYPE_INT8_ARRAY, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Int16Array", njs_top_level_constructor, - NJS_OBJ_TYPE_INT16_ARRAY, NJS_INT16ARRAY_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_Int16Array, njs_top_level_constructor, + NJS_OBJ_TYPE_INT16_ARRAY, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Int32Array", njs_top_level_constructor, - NJS_OBJ_TYPE_INT32_ARRAY, NJS_INT32ARRAY_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_Int32Array, njs_top_level_constructor, + NJS_OBJ_TYPE_INT32_ARRAY, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Float32Array", njs_top_level_constructor, - NJS_OBJ_TYPE_FLOAT32_ARRAY, NJS_FLOAT32ARRAY_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_Float32Array, njs_top_level_constructor, + NJS_OBJ_TYPE_FLOAT32_ARRAY, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Float64Array", njs_top_level_constructor, - NJS_OBJ_TYPE_FLOAT64_ARRAY, NJS_FLOAT64ARRAY_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_Float64Array, njs_top_level_constructor, + NJS_OBJ_TYPE_FLOAT64_ARRAY, NJS_OBJECT_PROP_VALUE_CW), - { - .type = NJS_PROPERTY_HANDLER, - .name = njs_long_string("Uint8ClampedArray"), - .u.value = njs_prop_handler2(njs_top_level_constructor, - NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY, - NJS_UINT8CLAMPEDARRAY_HASH), - .writable = 1, - .configurable = 1, - }, - - NJS_DECLARE_PROP_HANDLER("Boolean", njs_top_level_constructor, - NJS_OBJ_TYPE_BOOLEAN, NJS_BOOLEAN_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_Uint8ClampedArray, + njs_top_level_constructor, + NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Number", njs_top_level_constructor, - NJS_OBJ_TYPE_NUMBER, NJS_NUMBER_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_Boolean, njs_top_level_constructor, + NJS_OBJ_TYPE_BOOLEAN, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Symbol", njs_top_level_constructor, - NJS_OBJ_TYPE_SYMBOL, NJS_SYMBOL_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_Number, njs_top_level_constructor, + NJS_OBJ_TYPE_NUMBER, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("String", njs_top_level_constructor, - NJS_OBJ_TYPE_STRING, NJS_STRING_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_Symbol, njs_top_level_constructor, + NJS_OBJ_TYPE_SYMBOL, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Function", njs_top_level_constructor, - NJS_OBJ_TYPE_FUNCTION, NJS_FUNCTION_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_String, njs_top_level_constructor, + NJS_OBJ_TYPE_STRING, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("RegExp", njs_top_level_constructor, - NJS_OBJ_TYPE_REGEXP, NJS_REGEXP_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_Function, njs_top_level_constructor, + NJS_OBJ_TYPE_FUNCTION, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Date", njs_top_level_constructor, - NJS_OBJ_TYPE_DATE, NJS_DATE_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_RegExp, njs_top_level_constructor, + NJS_OBJ_TYPE_REGEXP, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Promise", njs_top_level_constructor, - NJS_OBJ_TYPE_PROMISE, NJS_PROMISE_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_Date, njs_top_level_constructor, + NJS_OBJ_TYPE_DATE, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("Error", njs_top_level_constructor, - NJS_OBJ_TYPE_ERROR, NJS_ERROR_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_Promise, njs_top_level_constructor, + NJS_OBJ_TYPE_PROMISE, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("EvalError", njs_top_level_constructor, - NJS_OBJ_TYPE_EVAL_ERROR, NJS_EVAL_ERROR_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_Error, njs_top_level_constructor, + NJS_OBJ_TYPE_ERROR, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("InternalError", njs_top_level_constructor, + NJS_DECLARE_PROP_HANDLER(STRING_EvalError, njs_top_level_constructor, + NJS_OBJ_TYPE_EVAL_ERROR, NJS_OBJECT_PROP_VALUE_CW), + + NJS_DECLARE_PROP_HANDLER(STRING_InternalError, + njs_top_level_constructor, NJS_OBJ_TYPE_INTERNAL_ERROR, - NJS_INTERNAL_ERROR_HASH, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("RangeError", njs_top_level_constructor, - NJS_OBJ_TYPE_RANGE_ERROR, NJS_RANGE_ERROR_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_RangeError, njs_top_level_constructor, + NJS_OBJ_TYPE_RANGE_ERROR, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("ReferenceError", njs_top_level_constructor, - NJS_OBJ_TYPE_REF_ERROR, NJS_REF_ERROR_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_ReferenceError, + njs_top_level_constructor, + NJS_OBJ_TYPE_REF_ERROR, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("SyntaxError", njs_top_level_constructor, - NJS_OBJ_TYPE_SYNTAX_ERROR, NJS_SYNTAX_ERROR_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_SyntaxError, njs_top_level_constructor, + NJS_OBJ_TYPE_SYNTAX_ERROR, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("TypeError", njs_top_level_constructor, - NJS_OBJ_TYPE_TYPE_ERROR, NJS_TYPE_ERROR_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_TypeError, njs_top_level_constructor, + NJS_OBJ_TYPE_TYPE_ERROR, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("URIError", njs_top_level_constructor, - NJS_OBJ_TYPE_URI_ERROR, NJS_URI_ERROR_HASH, - NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_URIError, njs_top_level_constructor, + NJS_OBJ_TYPE_URI_ERROR, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("MemoryError", njs_top_level_constructor, - NJS_OBJ_TYPE_MEMORY_ERROR, NJS_MEMORY_ERROR_HASH, + NJS_DECLARE_PROP_HANDLER(STRING_MemoryError, njs_top_level_constructor, + NJS_OBJ_TYPE_MEMORY_ERROR, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("AggregateError", njs_top_level_constructor, + NJS_DECLARE_PROP_HANDLER(STRING_AggregateError, njs_top_level_constructor, NJS_OBJ_TYPE_AGGREGATE_ERROR, - NJS_AGGREGATE_ERROR_HASH, NJS_OBJECT_PROP_VALUE_CW), }; @@ -1182,30 +1158,26 @@ static const njs_object_init_t njs_global_this_init = { }; -static const njs_object_prop_t njs_njs_object_properties[] = +static const njs_object_prop_init_t njs_njs_object_properties[] = { - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.value = njs_string("njs"), - .configurable = 1, - }, - - NJS_DECLARE_PROP_VALUE("engine", njs_string("njs"), + NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, njs_ascii_strval("njs"), + NJS_OBJECT_PROP_VALUE_C), + + NJS_DECLARE_PROP_VALUE(STRING_engine, njs_ascii_strval("njs"), NJS_OBJECT_PROP_VALUE_EC), - NJS_DECLARE_PROP_VALUE("version", njs_string(NJS_VERSION), + NJS_DECLARE_PROP_VALUE(STRING_version, njs_ascii_strval(NJS_VERSION), NJS_OBJECT_PROP_VALUE_EC), - NJS_DECLARE_PROP_VALUE("version_number", + NJS_DECLARE_PROP_VALUE(STRING_version_number, njs_value(NJS_NUMBER, 1, NJS_VERSION_NUMBER), NJS_OBJECT_PROP_VALUE_EC), - NJS_DECLARE_PROP_NATIVE("dump", njs_ext_dump, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_dump, njs_ext_dump, 0, 0), - NJS_DECLARE_PROP_NATIVE("on", njs_ext_on, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_on, njs_ext_on, 0, 0), - NJS_DECLARE_PROP_HANDLER("memoryStats", njs_ext_memory_stats, 0, 0, + NJS_DECLARE_PROP_HANDLER(STRING_memoryStats, njs_ext_memory_stats, 0, NJS_OBJECT_PROP_VALUE_EC), }; @@ -1218,17 +1190,15 @@ static const njs_object_init_t njs_njs_object_init = { static njs_int_t -njs_process_object_argv(njs_vm_t *vm, njs_object_prop_t *pr, - njs_value_t *process, njs_value_t *unused, njs_value_t *retval) +njs_process_object_argv(njs_vm_t *vm, njs_object_prop_t *pr, uint32_t unused, + njs_value_t *process, njs_value_t *unused2, njs_value_t *retval) { - char **arg; - njs_int_t ret; - njs_uint_t i; - njs_array_t *argv; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; - - static const njs_value_t argv_string = njs_string("argv"); + char **arg; + njs_int_t ret; + njs_uint_t i; + njs_array_t *argv; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; argv = njs_array_alloc(vm, 1, vm->options.argc, 0); if (njs_slow_path(argv == NULL)) { @@ -1238,11 +1208,14 @@ njs_process_object_argv(njs_vm_t *vm, njs_object_prop_t *pr, i = 0; for (arg = vm->options.argv; i < vm->options.argc; arg++) { - njs_string_create(vm, &argv->start[i++], (u_char *) *arg, - njs_strlen(*arg)); + ret = njs_string_create(vm, &argv->start[i++], (u_char *) *arg, + njs_strlen(*arg)); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } - prop = njs_object_prop_alloc(vm, &argv_string, &njs_value_undefined, 1); + prop = njs_object_prop_alloc(vm, &njs_value_undefined, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -1250,14 +1223,12 @@ njs_process_object_argv(njs_vm_t *vm, njs_object_prop_t *pr, njs_set_array(njs_prop_value(prop), argv); lhq.value = prop; - lhq.key_hash = NJS_ARGV_HASH; - lhq.key = njs_str_value("argv"); + lhq.key_hash = NJS_ATOM_STRING_argv; lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(njs_object_hash(process), &lhq); - + ret = njs_flathsh_unique_insert(njs_object_hash(process), &lhq); if (njs_fast_path(ret == NJS_OK)) { njs_value_assign(retval, njs_prop_value(prop)); return NJS_OK; @@ -1270,17 +1241,18 @@ njs_process_object_argv(njs_vm_t *vm, njs_object_prop_t *pr, static njs_int_t -njs_env_hash_init(njs_vm_t *vm, njs_lvlhsh_t *hash, char **environment) +njs_env_hash_init(njs_vm_t *vm, njs_flathsh_t *hash, char **environment) { - char **ep; - u_char *dst; - ssize_t length; - uint32_t cp; - njs_int_t ret; - const u_char *val, *entry, *s, *end; - njs_object_prop_t *prop; - njs_string_prop_t string; - njs_lvlhsh_query_t lhq; + char **ep; + u_char *dst; + ssize_t length; + uint32_t cp; + njs_int_t ret; + njs_value_t prop_name; + const u_char *val, *entry, *s, *end; + njs_object_prop_t *prop; + njs_string_prop_t string; + njs_flathsh_query_t lhq; lhq.replace = 0; lhq.pool = vm->mem_pool; @@ -1289,8 +1261,7 @@ njs_env_hash_init(njs_vm_t *vm, njs_lvlhsh_t *hash, char **environment) ep = environment; while (*ep != NULL) { - prop = njs_object_prop_alloc(vm, &njs_value_undefined, - &njs_value_undefined, 1); + prop = njs_object_prop_alloc(vm, &njs_value_undefined, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -1302,12 +1273,12 @@ njs_env_hash_init(njs_vm_t *vm, njs_lvlhsh_t *hash, char **environment) continue; } - ret = njs_string_create(vm, &prop->name, entry, val - entry); + ret = njs_string_create(vm, &prop_name, entry, val - entry); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - (void) njs_string_prop(&string, &prop->name); + (void) njs_string_prop(vm, &string, &prop_name); length = string.length; s = string.start; @@ -1327,11 +1298,15 @@ njs_env_hash_init(njs_vm_t *vm, njs_lvlhsh_t *hash, char **environment) return NJS_ERROR; } + ret = njs_atom_atomize_key(vm, &prop_name); + if (ret != NJS_OK) { + return ret; + } + lhq.value = prop; - njs_string_get(&prop->name, &lhq.key); - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); + lhq.key_hash = prop_name.atom_id; - ret = njs_lvlhsh_insert(hash, &lhq); + ret = njs_flathsh_unique_insert(hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { if (ret == NJS_ERROR) { njs_internal_error(vm, "lvlhsh insert failed"); @@ -1352,15 +1327,13 @@ njs_env_hash_init(njs_vm_t *vm, njs_lvlhsh_t *hash, char **environment) static njs_int_t -njs_process_object_env(njs_vm_t *vm, njs_object_prop_t *pr, - njs_value_t *process, njs_value_t *unused, njs_value_t *retval) +njs_process_object_env(njs_vm_t *vm, njs_object_prop_t *pr, uint32_t unused, + njs_value_t *process, njs_value_t *unused2, njs_value_t *retval) { - njs_int_t ret; - njs_object_t *env; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; - - static const njs_value_t env_string = njs_string("env"); + njs_int_t ret; + njs_object_t *env; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; env = njs_object_alloc(vm); if (njs_slow_path(env == NULL)) { @@ -1369,7 +1342,7 @@ njs_process_object_env(njs_vm_t *vm, njs_object_prop_t *pr, env->shared_hash = vm->shared->env_hash; - prop = njs_object_prop_alloc(vm, &env_string, &njs_value_undefined, 1); + prop = njs_object_prop_alloc(vm, &njs_value_undefined, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -1380,11 +1353,9 @@ njs_process_object_env(njs_vm_t *vm, njs_object_prop_t *pr, lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; lhq.value = prop; - lhq.key = njs_str_value("env"); - lhq.key_hash = NJS_ENV_HASH; - - ret = njs_lvlhsh_insert(njs_object_hash(process), &lhq); + lhq.key_hash = NJS_ATOM_STRING_env; + ret = njs_flathsh_unique_insert(njs_object_hash(process), &lhq); if (njs_fast_path(ret == NJS_OK)) { njs_value_assign(retval, njs_prop_value(prop)); return NJS_OK; @@ -1397,8 +1368,8 @@ njs_process_object_env(njs_vm_t *vm, njs_object_prop_t *pr, static njs_int_t -njs_process_object_pid(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *unused, njs_value_t *unused2, njs_value_t *retval) +njs_process_object_pid(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *unused2, njs_value_t *unused3, njs_value_t *retval) { njs_set_number(retval, getpid()); @@ -1407,8 +1378,8 @@ njs_process_object_pid(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -njs_process_object_ppid(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *unused, njs_value_t *unused2, njs_value_t *retval) +njs_process_object_ppid(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *unused2, njs_value_t *unused3, njs_value_t *retval) { njs_set_number(retval, getppid()); @@ -1420,11 +1391,11 @@ static njs_int_t njs_ext_process_kill(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t magic, njs_value_t *retval) { - int signal; - njs_str_t str; - njs_uint_t pid; - njs_value_t *arg; - njs_signal_entry_t *s; + int signal; + njs_str_t str; + njs_uint_t pid; + njs_value_t *arg; + const njs_signal_entry_t *s; arg = njs_arg(args, nargs, 1); if (!njs_value_is_number(arg)) { @@ -1440,7 +1411,7 @@ njs_ext_process_kill(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, signal = njs_value_number(arg); } else if (njs_value_is_string(arg)) { - njs_value_string_get(arg, &str); + njs_string_get(vm, arg, &str); if (str.length < 3 || memcmp(str.start, "SIG", 3) != 0) { njs_vm_type_error(vm, "\"signal\" unknown value: \"%V\"", &str); @@ -1477,24 +1448,20 @@ njs_ext_process_kill(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_object_prop_t njs_process_object_properties[] = +static const njs_object_prop_init_t njs_process_object_properties[] = { - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.value = njs_string("process"), - .configurable = 1, - }, + NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, njs_ascii_strval("process"), + NJS_OBJECT_PROP_VALUE_C), - NJS_DECLARE_PROP_HANDLER("argv", njs_process_object_argv, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_argv, njs_process_object_argv, 0, 0), - NJS_DECLARE_PROP_HANDLER("env", njs_process_object_env, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_env, njs_process_object_env, 0, 0), - NJS_DECLARE_PROP_HANDLER("pid", njs_process_object_pid, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_pid, njs_process_object_pid, 0, 0), - NJS_DECLARE_PROP_HANDLER("ppid", njs_process_object_ppid, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_ppid, njs_process_object_ppid, 0, 0), - NJS_DECLARE_PROP_NATIVE("kill", njs_ext_process_kill, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_kill, njs_ext_process_kill, 2, 0), }; diff --git a/src/njs_date.c b/src/njs_date.c index cd10abd5..2832abbd 100644 --- a/src/njs_date.c +++ b/src/njs_date.c @@ -52,7 +52,7 @@ typedef enum { } njs_date_fmt_t; -static double njs_date_string_parse(njs_value_t *date); +static double njs_date_string_parse(njs_vm_t *vm, njs_value_t *date); static double njs_date_rfc2822_string_parse(int64_t tm[], const u_char *p, const u_char *end); static double njs_date_js_string_parse(int64_t tm[], const u_char *p, @@ -69,9 +69,6 @@ static njs_int_t njs_date_string(njs_vm_t *vm, njs_value_t *retval, njs_date_fmt_t fmt, double time); -static const njs_value_t njs_string_invalid_date = njs_string("Invalid Date"); - - njs_inline int64_t njs_mod(int64_t a, int64_t b) { @@ -425,7 +422,7 @@ njs_date_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, time = njs_date(&args[1])->time; } else if (njs_is_string(&args[1])) { - time = njs_date_string_parse(&args[1]); + time = njs_date_string_parse(vm, &args[1]); } else { time = njs_timeclip(njs_number(&args[1])); @@ -502,7 +499,7 @@ njs_date_parse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - time = njs_date_string_parse(&args[1]); + time = njs_date_string_parse(vm, &args[1]); } else { time = NAN; @@ -548,7 +545,7 @@ njs_date_utc_offset_parse(const u_char *start, const u_char *end) } static double -njs_date_string_parse(njs_value_t *date) +njs_date_string_parse(njs_vm_t *vm, njs_value_t *date) { size_t ms_length; int64_t ext, utc_off; @@ -557,7 +554,7 @@ njs_date_string_parse(njs_value_t *date) const u_char *p, *next, *end; int64_t tm[NJS_DATE_MAX_FIELDS]; - njs_string_get(date, &string); + njs_string_get(vm, date, &string); p = string.start; end = p + string.length; @@ -1127,19 +1124,20 @@ njs_date_number_parse(int64_t *value, const u_char *p, const u_char *end, } -static const njs_object_prop_t njs_date_constructor_properties[] = +static const njs_object_prop_init_t njs_date_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(7), NJS_DECLARE_PROP_NAME("Date"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_NATIVE("UTC", njs_date_utc, 7, 0), + NJS_DECLARE_PROP_NATIVE(STRING_UTC, njs_date_utc, 7, 0), - NJS_DECLARE_PROP_NATIVE("now", njs_date_now, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_now, njs_date_now, 0, 0), - NJS_DECLARE_PROP_NATIVE("parse", njs_date_parse, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_parse, njs_date_parse, 1, 0), }; @@ -1206,7 +1204,7 @@ njs_date_string(njs_vm_t *vm, njs_value_t *retval, njs_date_fmt_t fmt, "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; if (njs_slow_path(isnan(time))) { - *retval = njs_string_invalid_date; + njs_atom_to_value(vm, retval, NJS_ATOM_STRING_Invalid_Date); return NJS_OK; } @@ -1443,14 +1441,13 @@ static njs_int_t njs_date_prototype_to_json(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - njs_int_t ret; - njs_value_t value; - njs_lvlhsh_query_t lhq; - - static const njs_value_t to_iso_string = njs_string("toISOString"); + njs_int_t ret; + njs_value_t value; + njs_flathsh_query_t lhq; if (njs_is_object(njs_argument(args, 0))) { - njs_object_property_init(&lhq, &to_iso_string, NJS_TO_ISO_STRING_HASH); + lhq.proto = &njs_object_hash_proto; + lhq.key_hash = NJS_ATOM_STRING_toISOString; ret = njs_object_property(vm, njs_object(njs_argument(args, 0)), &lhq, &value); @@ -1471,171 +1468,179 @@ njs_date_prototype_to_json(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_object_prop_t njs_date_prototype_properties[] = +static const njs_object_prop_init_t njs_date_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("__proto__", njs_primitive_prototype_get_proto, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING___proto__, + njs_primitive_prototype_get_proto, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_NATIVE("valueOf", njs_date_prototype_value_of, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_valueOf, njs_date_prototype_value_of, 0, + 0), - NJS_DECLARE_PROP_NATIVE("toString", njs_date_prototype_to_string, 0, - NJS_DATE_FMT_TO_STRING), + NJS_DECLARE_PROP_NATIVE(STRING_toString, njs_date_prototype_to_string, + 0, NJS_DATE_FMT_TO_STRING), - NJS_DECLARE_PROP_NATIVE("toDateString", njs_date_prototype_to_string, 0, + NJS_DECLARE_PROP_NATIVE(STRING_toDateString, + njs_date_prototype_to_string, 0, NJS_DATE_FMT_TO_DATE_STRING), - NJS_DECLARE_PROP_NATIVE("toTimeString", njs_date_prototype_to_string, 0, + NJS_DECLARE_PROP_NATIVE(STRING_toTimeString, + njs_date_prototype_to_string, 0, NJS_DATE_FMT_TO_TIME_STRING), - NJS_DECLARE_PROP_NATIVE("toLocaleString", njs_date_prototype_to_string, 0, + NJS_DECLARE_PROP_NATIVE(STRING_toLocaleString, + njs_date_prototype_to_string, 0, NJS_DATE_FMT_TO_STRING), - NJS_DECLARE_PROP_LNATIVE("toLocaleDateString", - njs_date_prototype_to_string, 0, - NJS_DATE_FMT_TO_DATE_STRING), + NJS_DECLARE_PROP_NATIVE(STRING_toLocaleDateString, + njs_date_prototype_to_string, 0, + NJS_DATE_FMT_TO_DATE_STRING), - NJS_DECLARE_PROP_LNATIVE("toLocaleTimeString", - njs_date_prototype_to_string, 0, - NJS_DATE_FMT_TO_TIME_STRING), + NJS_DECLARE_PROP_NATIVE(STRING_toLocaleTimeString, + njs_date_prototype_to_string, 0, + NJS_DATE_FMT_TO_TIME_STRING), - NJS_DECLARE_PROP_NATIVE("toUTCString", + NJS_DECLARE_PROP_NATIVE(STRING_toUTCString, njs_date_prototype_to_string, 0, NJS_DATE_FMT_TO_UTC_STRING), - NJS_DECLARE_PROP_NATIVE("toISOString", + NJS_DECLARE_PROP_NATIVE(STRING_toISOString, njs_date_prototype_to_string, 0, NJS_DATE_FMT_TO_ISO_STRING), - NJS_DECLARE_PROP_NATIVE("toJSON", njs_date_prototype_to_json, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toJSON, njs_date_prototype_to_json, 1, + 0), - NJS_DECLARE_PROP_NATIVE("getTime", njs_date_prototype_value_of, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_getTime, njs_date_prototype_value_of, 0, + 0), - NJS_DECLARE_PROP_NATIVE("getFullYear", + NJS_DECLARE_PROP_NATIVE(STRING_getFullYear, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_YR, 1)), - NJS_DECLARE_PROP_NATIVE("getUTCFullYear", + NJS_DECLARE_PROP_NATIVE(STRING_getUTCFullYear, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_YR, 0)), - NJS_DECLARE_PROP_NATIVE("getMonth", + NJS_DECLARE_PROP_NATIVE(STRING_getMonth, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_MON, 1)), - NJS_DECLARE_PROP_NATIVE("getUTCMonth", + NJS_DECLARE_PROP_NATIVE(STRING_getUTCMonth, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_MON, 0)), - NJS_DECLARE_PROP_NATIVE("getDate", + NJS_DECLARE_PROP_NATIVE(STRING_getDate, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_DAY, 1)), - NJS_DECLARE_PROP_NATIVE("getUTCDate", + NJS_DECLARE_PROP_NATIVE(STRING_getUTCDate, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_DAY, 0)), - NJS_DECLARE_PROP_NATIVE("getDay", + NJS_DECLARE_PROP_NATIVE(STRING_getDay, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_WDAY, 1)), - NJS_DECLARE_PROP_NATIVE("getUTCDay", + NJS_DECLARE_PROP_NATIVE(STRING_getUTCDay, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_WDAY, 0)), - NJS_DECLARE_PROP_NATIVE("getHours", + NJS_DECLARE_PROP_NATIVE(STRING_getHours, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_HR, 1)), - NJS_DECLARE_PROP_NATIVE("getUTCHours", + NJS_DECLARE_PROP_NATIVE(STRING_getUTCHours, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_HR, 0)), - NJS_DECLARE_PROP_NATIVE("getMinutes", + NJS_DECLARE_PROP_NATIVE(STRING_getMinutes, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_MIN, 1)), - NJS_DECLARE_PROP_NATIVE("getUTCMinutes", + NJS_DECLARE_PROP_NATIVE(STRING_getUTCMinutes, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_MIN, 0)), - NJS_DECLARE_PROP_NATIVE("getSeconds", + NJS_DECLARE_PROP_NATIVE(STRING_getSeconds, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_SEC, 1)), - NJS_DECLARE_PROP_NATIVE("getUTCSeconds", + NJS_DECLARE_PROP_NATIVE(STRING_getUTCSeconds, njs_date_prototype_get_field, 0, njs_date_magic(NJS_DATE_SEC, 0)), - NJS_DECLARE_PROP_LNATIVE("getMilliseconds", - njs_date_prototype_get_field, 0, - njs_date_magic(NJS_DATE_MSEC, 1)), + NJS_DECLARE_PROP_NATIVE(STRING_getMilliseconds, + njs_date_prototype_get_field, 0, + njs_date_magic(NJS_DATE_MSEC, 1)), - NJS_DECLARE_PROP_LNATIVE("getUTCMilliseconds", - njs_date_prototype_get_field, 0, - njs_date_magic(NJS_DATE_MSEC, 0)), + NJS_DECLARE_PROP_NATIVE(STRING_getUTCMilliseconds, + njs_date_prototype_get_field, 0, + njs_date_magic(NJS_DATE_MSEC, 0)), - NJS_DECLARE_PROP_LNATIVE("getTimezoneOffset", - njs_date_prototype_get_timezone_offset, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_getTimezoneOffset, + njs_date_prototype_get_timezone_offset, 0, 0), - NJS_DECLARE_PROP_NATIVE("setTime", njs_date_prototype_set_time, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_setTime, njs_date_prototype_set_time, 1, + 0), - NJS_DECLARE_PROP_LNATIVE("setMilliseconds", - njs_date_prototype_set_fields, 1, - njs_date_magic2(NJS_DATE_MSEC, 1, 1)), + NJS_DECLARE_PROP_NATIVE(STRING_setMilliseconds, + njs_date_prototype_set_fields, 1, + njs_date_magic2(NJS_DATE_MSEC, 1, 1)), - NJS_DECLARE_PROP_LNATIVE("setUTCMilliseconds", - njs_date_prototype_set_fields, 1, - njs_date_magic2(NJS_DATE_MSEC, 1, 0)), + NJS_DECLARE_PROP_NATIVE(STRING_setUTCMilliseconds, + njs_date_prototype_set_fields, 1, + njs_date_magic2(NJS_DATE_MSEC, 1, 0)), - NJS_DECLARE_PROP_NATIVE("setSeconds", + NJS_DECLARE_PROP_NATIVE(STRING_setSeconds, njs_date_prototype_set_fields, 2, njs_date_magic2(NJS_DATE_SEC, 2, 1)), - NJS_DECLARE_PROP_NATIVE("setUTCSeconds", + NJS_DECLARE_PROP_NATIVE(STRING_setUTCSeconds, njs_date_prototype_set_fields, 2, njs_date_magic2(NJS_DATE_SEC, 2, 0)), - NJS_DECLARE_PROP_NATIVE("setMinutes", + NJS_DECLARE_PROP_NATIVE(STRING_setMinutes, njs_date_prototype_set_fields, 3, njs_date_magic2(NJS_DATE_MIN, 3, 1)), - NJS_DECLARE_PROP_NATIVE("setUTCMinutes", + NJS_DECLARE_PROP_NATIVE(STRING_setUTCMinutes, njs_date_prototype_set_fields, 3, njs_date_magic2(NJS_DATE_MIN, 3, 0)), - NJS_DECLARE_PROP_NATIVE("setHours", + NJS_DECLARE_PROP_NATIVE(STRING_setHours, njs_date_prototype_set_fields, 4, njs_date_magic2(NJS_DATE_HR, 4, 1)), - NJS_DECLARE_PROP_NATIVE("setUTCHours", + NJS_DECLARE_PROP_NATIVE(STRING_setUTCHours, njs_date_prototype_set_fields, 4, njs_date_magic2(NJS_DATE_HR, 4, 0)), - NJS_DECLARE_PROP_NATIVE("setDate", + NJS_DECLARE_PROP_NATIVE(STRING_setDate, njs_date_prototype_set_fields, 1, njs_date_magic2(NJS_DATE_DAY, 1, 1)), - NJS_DECLARE_PROP_NATIVE("setUTCDate", + NJS_DECLARE_PROP_NATIVE(STRING_setUTCDate, njs_date_prototype_set_fields, 1, njs_date_magic2(NJS_DATE_DAY, 1, 0)), - NJS_DECLARE_PROP_NATIVE("setMonth", + NJS_DECLARE_PROP_NATIVE(STRING_setMonth, njs_date_prototype_set_fields, 2, njs_date_magic2(NJS_DATE_MON, 2, 1)), - NJS_DECLARE_PROP_NATIVE("setUTCMonth", + NJS_DECLARE_PROP_NATIVE(STRING_setUTCMonth, njs_date_prototype_set_fields, 2, njs_date_magic2(NJS_DATE_MON, 2, 0)), - NJS_DECLARE_PROP_NATIVE("setFullYear", + NJS_DECLARE_PROP_NATIVE(STRING_setFullYear, njs_date_prototype_set_fields, 3, njs_date_magic2(NJS_DATE_YR, 3, 1)), - NJS_DECLARE_PROP_NATIVE("setUTCFullYear", + NJS_DECLARE_PROP_NATIVE(STRING_setUTCFullYear, njs_date_prototype_set_fields, 3, njs_date_magic2(NJS_DATE_YR, 3, 0)), }; diff --git a/src/njs_encoding.c b/src/njs_encoding.c index f70c084d..37bdecf3 100644 --- a/src/njs_encoding.c +++ b/src/njs_encoding.c @@ -100,7 +100,7 @@ njs_text_encoder_encode(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - (void) njs_string_prop(&prop, input); + (void) njs_string_prop(vm, &prop, input); if (prop.length != 0) { return njs_text_encoder_encode_utf8(vm, &prop, retval); @@ -164,13 +164,11 @@ njs_text_encoder_encode_into(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_int_t ret; njs_str_t str; njs_value_t *this, *input, *dest, value, read, written; + njs_object_t *object; const u_char *start, *end; njs_typed_array_t *array; njs_unicode_decode_t ctx; - static const njs_value_t read_str = njs_string("read"); - static const njs_value_t written_str = njs_string("written"); - this = njs_argument(args, 0); input = njs_arg(args, nargs, 1); dest = njs_arg(args, nargs, 2); @@ -195,7 +193,7 @@ njs_text_encoder_encode_into(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - njs_string_get(input, &str); + njs_string_get(vm, input, &str); start = str.start; end = start + str.length; @@ -228,22 +226,41 @@ njs_text_encoder_encode_into(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, to = njs_utf8_encode(to, cp); } - return njs_vm_object_alloc(vm, retval, &read_str, &read, - &written_str, &written, NULL); + object = njs_object_alloc(vm); + if (njs_slow_path(object == NULL)) { + return NJS_ERROR; + } + + njs_set_object(retval, object); + + ret = njs_object_prop_define(vm, retval, NJS_ATOM_STRING_read, &read, + NJS_OBJECT_PROP_VALUE_CW); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + ret = njs_object_prop_define(vm, retval, NJS_ATOM_STRING_written, &written, + NJS_OBJECT_PROP_VALUE_CW); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + return NJS_OK; } -static const njs_object_prop_t njs_text_encoder_properties[] = +static const njs_object_prop_init_t njs_text_encoder_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("encoding", njs_string("utf-8"), 0), + NJS_DECLARE_PROP_VALUE(STRING_encoding, njs_ascii_strval("utf-8"), 0), - NJS_DECLARE_PROP_NATIVE("encode", njs_text_encoder_encode, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_encode, njs_text_encoder_encode, 0, 0), - NJS_DECLARE_PROP_NATIVE("encodeInto", njs_text_encoder_encode_into, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_encodeInto, njs_text_encoder_encode_into, + 2, 0), }; @@ -253,13 +270,14 @@ const njs_object_init_t njs_text_encoder_init = { }; -static const njs_object_prop_t njs_text_encoder_constructor_properties[] = +static const njs_object_prop_init_t njs_text_encoder_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(0), NJS_DECLARE_PROP_NAME("TextEncoder"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -341,7 +359,7 @@ njs_text_decoder_arg_encoding(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - njs_string_get(value, &str); + njs_string_get(vm, value, &str); for (label = &njs_encoding_labels[0]; label->name.length != 0; label++) { if (njs_strstr_eq(&str, &label->name)) { @@ -363,9 +381,6 @@ njs_text_decoder_arg_options(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_int_t ret; njs_value_t retval, *value; - static const njs_value_t fatal_str = njs_string("fatal"); - static const njs_value_t ignore_bom_str = njs_string("ignoreBOM"); - if (nargs < 3) { data->fatal = 0; data->ignore_bom = 0; @@ -380,15 +395,14 @@ njs_text_decoder_arg_options(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - ret = njs_value_property(vm, value, njs_value_arg(&fatal_str), &retval); + ret = njs_value_property(vm, value, NJS_ATOM_STRING_fatal, &retval); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } data->fatal = njs_bool(&retval); - ret = njs_value_property(vm, value, njs_value_arg(&ignore_bom_str), - &retval); + ret = njs_value_property(vm, value, NJS_ATOM_STRING_ignoreBOM, &retval); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -400,13 +414,11 @@ njs_text_decoder_arg_options(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t -njs_text_decoder_encoding(njs_vm_t *vm, njs_object_prop_t *prop, +njs_text_decoder_encoding(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { njs_encoding_decode_t *data; - static const njs_value_t utf8_str = njs_string("utf-8"); - if (njs_slow_path(!njs_is_object_data(value, NJS_DATA_TAG_TEXT_DECODER))) { njs_set_undefined(retval); return NJS_DECLINED; @@ -416,7 +428,7 @@ njs_text_decoder_encoding(njs_vm_t *vm, njs_object_prop_t *prop, switch (data->encoding) { case NJS_ENCODING_UTF8: - *retval = utf8_str; + njs_atom_to_value(vm, retval, NJS_ATOM_STRING_utf_8); break; default: @@ -429,7 +441,7 @@ njs_text_decoder_encoding(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -njs_text_decoder_fatal(njs_vm_t *vm, njs_object_prop_t *prop, +njs_text_decoder_fatal(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { njs_encoding_decode_t *data; @@ -449,7 +461,8 @@ njs_text_decoder_fatal(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t njs_text_decoder_ignore_bom(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_encoding_decode_t *data; @@ -482,8 +495,6 @@ njs_text_decoder_decode(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, const njs_typed_array_t *array; const njs_array_buffer_t *buffer; - static const njs_value_t stream_str = njs_string("stream"); - start = NULL; end = NULL; @@ -527,8 +538,7 @@ njs_text_decoder_decode(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - ret = njs_value_property(vm, options, njs_value_arg(&stream_str), - retval); + ret = njs_value_property(vm, options, NJS_ATOM_STRING_stream, retval); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -568,19 +578,21 @@ njs_text_decoder_decode(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_object_prop_t njs_text_decoder_properties[] = +static const njs_object_prop_init_t njs_text_decoder_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("encoding", njs_text_decoder_encoding, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_encoding, njs_text_decoder_encoding, 0, + 0), - NJS_DECLARE_PROP_HANDLER("fatal", njs_text_decoder_fatal, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_fatal, njs_text_decoder_fatal, 0, 0), - NJS_DECLARE_PROP_HANDLER("ignoreBOM", njs_text_decoder_ignore_bom, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_ignoreBOM, njs_text_decoder_ignore_bom, + 0, 0), - NJS_DECLARE_PROP_NATIVE("decode", njs_text_decoder_decode, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_decode, njs_text_decoder_decode, 0, 0), }; @@ -590,13 +602,14 @@ const njs_object_init_t njs_text_decoder_init = { }; -static const njs_object_prop_t njs_text_decoder_constructor_properties[] = +static const njs_object_prop_init_t njs_text_decoder_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(0), NJS_DECLARE_PROP_NAME("TextDecoder"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; diff --git a/src/njs_error.c b/src/njs_error.c index b9da6597..6e12aa61 100644 --- a/src/njs_error.c +++ b/src/njs_error.c @@ -30,12 +30,6 @@ static njs_int_t njs_backtrace_to_string(njs_vm_t *vm, njs_arr_t *backtrace, njs_str_t *dst); -static const njs_value_t njs_error_message_string = njs_string("message"); -static const njs_value_t njs_error_name_string = njs_string("name"); -static const njs_value_t njs_error_stack_string = njs_string("stack"); -static const njs_value_t njs_error_errors_string = njs_string("errors"); - - void njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_object_t *proto, u_char *start, size_t size) @@ -171,8 +165,7 @@ njs_error_stack(njs_vm_t *vm, njs_value_t *value, njs_value_t *stack) { njs_int_t ret; - ret = njs_value_property(vm, value, njs_value_arg(&njs_error_stack_string), - stack); + ret = njs_value_property(vm, value, NJS_ATOM_STRING_stack, stack); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -189,11 +182,11 @@ njs_object_t * njs_error_alloc(njs_vm_t *vm, njs_object_t *proto, const njs_value_t *name, const njs_value_t *message, const njs_value_t *errors) { - njs_int_t ret; - njs_object_t *error; - njs_object_prop_t *prop; - njs_object_value_t *ov; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_object_t *error; + njs_object_prop_t *prop; + njs_object_value_t *ov; + njs_flathsh_query_t lhq; ov = njs_mp_alloc(vm->mem_pool, sizeof(njs_object_value_t)); if (njs_slow_path(ov == NULL)) { @@ -219,17 +212,15 @@ njs_error_alloc(njs_vm_t *vm, njs_object_t *proto, const njs_value_t *name, lhq.proto = &njs_object_hash_proto; if (name != NULL) { - lhq.key = njs_str_value("name"); - lhq.key_hash = NJS_NAME_HASH; - - prop = njs_object_prop_alloc(vm, &njs_error_name_string, name, 1); + prop = njs_object_prop_alloc(vm, name, 1); if (njs_slow_path(prop == NULL)) { goto memory_error; } lhq.value = prop; + lhq.key_hash = NJS_ATOM_STRING_name; - ret = njs_lvlhsh_insert(&error->hash, &lhq); + ret = njs_flathsh_unique_insert(&error->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NULL; @@ -237,10 +228,7 @@ njs_error_alloc(njs_vm_t *vm, njs_object_t *proto, const njs_value_t *name, } if (message!= NULL) { - lhq.key = njs_str_value("message"); - lhq.key_hash = NJS_MESSAGE_HASH; - - prop = njs_object_prop_alloc(vm, &njs_error_message_string, message, 1); + prop = njs_object_prop_alloc(vm, message, 1); if (njs_slow_path(prop == NULL)) { goto memory_error; } @@ -248,8 +236,9 @@ njs_error_alloc(njs_vm_t *vm, njs_object_t *proto, const njs_value_t *name, prop->enumerable = 0; lhq.value = prop; + lhq.key_hash = NJS_ATOM_STRING_message; - ret = njs_lvlhsh_insert(&error->hash, &lhq); + ret = njs_flathsh_unique_insert(&error->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NULL; @@ -257,10 +246,7 @@ njs_error_alloc(njs_vm_t *vm, njs_object_t *proto, const njs_value_t *name, } if (errors != NULL) { - lhq.key = njs_str_value("errors"); - lhq.key_hash = NJS_ERRORS_HASH; - - prop = njs_object_prop_alloc(vm, &njs_error_errors_string, errors, 1); + prop = njs_object_prop_alloc(vm, errors, 1); if (njs_slow_path(prop == NULL)) { goto memory_error; } @@ -268,8 +254,9 @@ njs_error_alloc(njs_vm_t *vm, njs_object_t *proto, const njs_value_t *name, prop->enumerable = 0; lhq.value = prop; + lhq.key_hash = NJS_ATOM_STRING_errors; - ret = njs_lvlhsh_insert(&error->hash, &lhq); + ret = njs_flathsh_unique_insert(&error->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NULL; @@ -340,13 +327,14 @@ njs_error_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_object_prop_t njs_error_constructor_properties[] = +static const njs_object_prop_init_t njs_error_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("Error"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -356,13 +344,14 @@ const njs_object_init_t njs_error_constructor_init = { }; -static const njs_object_prop_t njs_eval_error_constructor_properties[] = +static const njs_object_prop_init_t njs_eval_error_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("EvalError"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -372,13 +361,14 @@ const njs_object_init_t njs_eval_error_constructor_init = { }; -static const njs_object_prop_t njs_internal_error_constructor_properties[] = +static const njs_object_prop_init_t njs_internal_error_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("InternalError"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -388,13 +378,14 @@ const njs_object_init_t njs_internal_error_constructor_init = { }; -static const njs_object_prop_t njs_range_error_constructor_properties[] = +static const njs_object_prop_init_t njs_range_error_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("RangeError"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -404,13 +395,14 @@ const njs_object_init_t njs_range_error_constructor_init = { }; -static const njs_object_prop_t njs_reference_error_constructor_properties[] = +static const njs_object_prop_init_t njs_reference_error_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("ReferenceError"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -420,13 +412,14 @@ const njs_object_init_t njs_reference_error_constructor_init = { }; -static const njs_object_prop_t njs_syntax_error_constructor_properties[] = +static const njs_object_prop_init_t njs_syntax_error_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("SyntaxError"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -436,13 +429,14 @@ const njs_object_init_t njs_syntax_error_constructor_init = { }; -static const njs_object_prop_t njs_type_error_constructor_properties[] = +static const njs_object_prop_init_t njs_type_error_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("TypeError"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -452,13 +446,14 @@ const njs_object_init_t njs_type_error_constructor_init = { }; -static const njs_object_prop_t njs_uri_error_constructor_properties[] = +static const njs_object_prop_init_t njs_uri_error_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("URIError"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -468,13 +463,14 @@ const njs_object_init_t njs_uri_error_constructor_init = { }; -static const njs_object_prop_t njs_aggregate_error_constructor_properties[] = +static const njs_object_prop_init_t njs_aggregate_error_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("AggregateError"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -532,7 +528,8 @@ njs_memory_error_constructor(njs_vm_t *vm, njs_value_t *args, static njs_int_t njs_memory_error_prototype_create(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { int32_t index; njs_function_t *function; @@ -555,14 +552,14 @@ njs_memory_error_prototype_create(njs_vm_t *vm, njs_object_prop_t *prop, } -static const njs_object_prop_t njs_memory_error_constructor_properties[] = +static const njs_object_prop_init_t njs_memory_error_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("MemoryError"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_memory_error_prototype_create, - 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, + njs_memory_error_prototype_create, 0, 0), }; @@ -593,9 +590,6 @@ njs_error_to_string2(njs_vm_t *vm, njs_value_t *retval, njs_value_t *name_value, *message_value; njs_string_prop_t name, message; - static const njs_value_t string_message = njs_string("message"); - static const njs_value_t default_name = njs_string("Error"); - njs_assert(njs_is_object(error)); if (want_stack) { @@ -609,34 +603,38 @@ njs_error_to_string2(njs_vm_t *vm, njs_value_t *retval, } } - ret = njs_value_property(vm, (njs_value_t *) error, - njs_value_arg(&njs_string_name), + ret = njs_value_property(vm, (njs_value_t *) error, NJS_ATOM_STRING_name, &value1); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } - name_value = (ret == NJS_OK) ? &value1 : njs_value_arg(&default_name); + if (ret == NJS_DECLINED) { + njs_atom_to_value(vm, &value1, NJS_ATOM_STRING_Error); + } + + name_value = &value1; if (njs_slow_path(!njs_is_string(name_value))) { ret = njs_value_to_string(vm, &value1, name_value); if (njs_slow_path(ret != NJS_OK)) { return ret; } - - name_value = &value1; } - (void) njs_string_prop(&name, name_value); + (void) njs_string_prop(vm, &name, name_value); - ret = njs_value_property(vm, (njs_value_t *) error, - njs_value_arg(&string_message), &value2); + ret = njs_value_property(vm, (njs_value_t *) error, NJS_ATOM_STRING_message, + &value2); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } - message_value = (ret == NJS_OK) ? &value2 - : njs_value_arg(&njs_string_empty); + if (ret == NJS_DECLINED) { + njs_set_empty_string(vm, &value2); + } + + message_value = &value2; if (njs_slow_path(!njs_is_string(message_value))) { ret = njs_value_to_string(vm, &value2, message_value); @@ -647,7 +645,7 @@ njs_error_to_string2(njs_vm_t *vm, njs_value_t *retval, message_value = &value2; } - (void) njs_string_prop(&message, message_value); + (void) njs_string_prop(vm, &message, message_value); if (name.size == 0) { *retval = *message_value; @@ -697,7 +695,7 @@ njs_error_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t -njs_error_prototype_stack(njs_vm_t *vm, njs_object_prop_t *prop, +njs_error_prototype_stack(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { njs_int_t ret; @@ -750,7 +748,7 @@ njs_error_prototype_stack(njs_vm_t *vm, njs_object_prop_t *prop, return ret; } - njs_string_get(&rv, &string); + njs_string_get(vm, &rv, &string); ret = njs_backtrace_to_string(vm, backtrace, &string); @@ -794,23 +792,26 @@ njs_error_to_string(njs_vm_t *vm, njs_value_t *retval, const njs_value_t *error) } -static const njs_object_prop_t njs_error_prototype_properties[] = +static const njs_object_prop_init_t njs_error_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("name", njs_string("Error"), + NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval("Error"), NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("message", njs_string(""), NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_VALUE(STRING_message, njs_ascii_strval(""), + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_NATIVE("valueOf", njs_error_prototype_value_of, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_valueOf, njs_error_prototype_value_of, + 0, 0), - NJS_DECLARE_PROP_NATIVE("toString", njs_error_prototype_to_string, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toString, njs_error_prototype_to_string, + 0, 0), - NJS_DECLARE_PROP_HANDLER("stack", njs_error_prototype_stack, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_stack, njs_error_prototype_stack, + 0, NJS_OBJECT_PROP_VALUE_CW), }; @@ -829,16 +830,17 @@ const njs_object_type_init_t njs_error_type_init = { }; -static const njs_object_prop_t njs_eval_error_prototype_properties[] = +static const njs_object_prop_init_t njs_eval_error_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("name", njs_string("EvalError"), + NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval("EvalError"), NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("message", njs_string(""), NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_VALUE(STRING_message, njs_ascii_strval(""), + NJS_OBJECT_PROP_VALUE_CW), }; @@ -861,12 +863,10 @@ static njs_int_t njs_internal_error_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - static const njs_value_t name = njs_string("MemoryError"); - if (nargs >= 1 && njs_is_object(&args[0])) { /* MemoryError is a nonextensible internal error. */ if (!njs_object(&args[0])->extensible) { - njs_value_assign(retval, &name); + njs_atom_to_value(vm, retval, NJS_ATOM_STRING_MemoryError); return NJS_OK; } } @@ -875,15 +875,16 @@ njs_internal_error_prototype_to_string(njs_vm_t *vm, njs_value_t *args, } -static const njs_object_prop_t njs_internal_error_prototype_properties[] = +static const njs_object_prop_init_t njs_internal_error_prototype_properties[] = { - NJS_DECLARE_PROP_VALUE("name", njs_string("InternalError"), + NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval("InternalError"), NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("message", njs_string(""), NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_VALUE(STRING_message, njs_ascii_strval(""), + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_NATIVE("toString", njs_internal_error_prototype_to_string, - 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toString, + njs_internal_error_prototype_to_string, 0, 0), }; @@ -910,16 +911,17 @@ const njs_object_type_init_t njs_memory_error_type_init = { }; -static const njs_object_prop_t njs_range_error_prototype_properties[] = +static const njs_object_prop_init_t njs_range_error_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("name", njs_string("RangeError"), + NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval("RangeError"), NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("message", njs_string(""), NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_VALUE(STRING_message, njs_ascii_strval(""), + NJS_OBJECT_PROP_VALUE_CW), }; @@ -938,16 +940,17 @@ const njs_object_type_init_t njs_range_error_type_init = { }; -static const njs_object_prop_t njs_reference_error_prototype_properties[] = +static const njs_object_prop_init_t njs_reference_error_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("name", njs_string("ReferenceError"), + NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval("ReferenceError"), NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("message", njs_string(""), NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_VALUE(STRING_message, njs_ascii_strval(""), + NJS_OBJECT_PROP_VALUE_CW), }; @@ -966,16 +969,17 @@ const njs_object_type_init_t njs_reference_error_type_init = { }; -static const njs_object_prop_t njs_syntax_error_prototype_properties[] = +static const njs_object_prop_init_t njs_syntax_error_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("name", njs_string("SyntaxError"), + NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval("SyntaxError"), NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("message", njs_string(""), NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_VALUE(STRING_message, njs_ascii_strval(""), + NJS_OBJECT_PROP_VALUE_CW), }; @@ -994,16 +998,17 @@ const njs_object_type_init_t njs_syntax_error_type_init = { }; -static const njs_object_prop_t njs_type_error_prototype_properties[] = +static const njs_object_prop_init_t njs_type_error_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("name", njs_string("TypeError"), + NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval("TypeError"), NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("message", njs_string(""), NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_VALUE(STRING_message, njs_ascii_strval(""), + NJS_OBJECT_PROP_VALUE_CW), }; @@ -1022,16 +1027,17 @@ const njs_object_type_init_t njs_type_error_type_init = { }; -static const njs_object_prop_t njs_uri_error_prototype_properties[] = +static const njs_object_prop_init_t njs_uri_error_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("name", njs_string("URIError"), + NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval("URIError"), NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("message", njs_string(""), NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_VALUE(STRING_message, njs_ascii_strval(""), + NJS_OBJECT_PROP_VALUE_CW), }; @@ -1050,16 +1056,17 @@ const njs_object_type_init_t njs_uri_error_type_init = { }; -static const njs_object_prop_t njs_aggregate_error_prototype_properties[] = +static const njs_object_prop_init_t njs_aggregate_error_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("name", njs_string("AggregateError"), + NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval("AggregateError"), NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_VALUE("message", njs_string(""), NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_VALUE(STRING_message, njs_ascii_strval(""), + NJS_OBJECT_PROP_VALUE_CW), }; diff --git a/src/njs_extern.c b/src/njs_extern.c index 621cb76d..077d2a5f 100644 --- a/src/njs_extern.c +++ b/src/njs_extern.c @@ -9,8 +9,8 @@ static njs_int_t njs_external_prop_handler(njs_vm_t *vm, - njs_object_prop_t *self, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *self, uint32_t atom_id, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); static njs_int_t @@ -19,12 +19,13 @@ njs_external_add(njs_vm_t *vm, njs_arr_t *protos, { size_t size; njs_int_t ret; - njs_lvlhsh_t *hash; + njs_value_t prop_name; const u_char *start; + njs_flathsh_t *hash; njs_function_t *function; njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; njs_exotic_slots_t *slot, *next; + njs_flathsh_query_t lhq; const njs_external_t *end; slot = njs_arr_add(protos); @@ -57,8 +58,7 @@ njs_external_add(njs_vm_t *vm, njs_arr_t *protos, continue; } - prop = njs_object_prop_alloc(vm, &njs_string_empty, - &njs_value_invalid, 1); + prop = njs_object_prop_alloc(vm, &njs_value_invalid, 1); if (njs_slow_path(prop == NULL)) { goto memory_error; } @@ -68,20 +68,17 @@ njs_external_add(njs_vm_t *vm, njs_arr_t *protos, prop->enumerable = external->enumerable; if (external->flags & NJS_EXTERN_SYMBOL) { - njs_set_symbol(&prop->name, external->name.symbol, NULL); - lhq.key_hash = external->name.symbol; } else { - ret = njs_string_create(vm, &prop->name, - external->name.string.start, - external->name.string.length); + ret = njs_atom_string_create(vm, &prop_name, + external->name.string.start, + external->name.string.length); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - lhq.key = external->name.string; - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); + lhq.key_hash = prop_name.atom_id; } lhq.value = prop; @@ -170,7 +167,7 @@ njs_external_add(njs_vm_t *vm, njs_arr_t *protos, break; } - ret = njs_lvlhsh_insert(hash, &lhq); + ret = njs_flathsh_unique_insert(hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; @@ -191,14 +188,15 @@ memory_error: static njs_int_t njs_external_prop_handler(njs_vm_t *vm, njs_object_prop_t *self, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { - njs_int_t ret; - njs_object_prop_t *prop; - njs_external_ptr_t external; - njs_object_value_t *ov; - njs_lvlhsh_query_t lhq; - njs_exotic_slots_t *slots; + njs_int_t ret; + njs_object_prop_t *prop; + njs_external_ptr_t external; + njs_object_value_t *ov; + njs_exotic_slots_t *slots; + njs_flathsh_query_t lhq; if (njs_slow_path(retval == NULL)) { return NJS_DECLINED; @@ -226,7 +224,7 @@ njs_external_prop_handler(njs_vm_t *vm, njs_object_prop_t *self, njs_set_object_value(retval, ov); } - prop = njs_object_prop_alloc(vm, &self->name, retval, 1); + prop = njs_object_prop_alloc(vm, retval, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -236,13 +234,12 @@ njs_external_prop_handler(njs_vm_t *vm, njs_object_prop_t *self, prop->enumerable = self->enumerable; lhq.value = prop; - njs_string_get(&self->name, &lhq.key); - lhq.key_hash = njs_prop_magic32(self); + lhq.key_hash = atom_id; lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(njs_object_hash(value), &lhq); + ret = njs_flathsh_unique_insert(njs_object_hash(value), &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert/replace failed"); return NJS_ERROR; @@ -315,7 +312,8 @@ njs_vm_external_prototype(njs_vm_t *vm, const njs_external_t *definition, static njs_int_t njs_vm_external_constructor_handler(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t atom_id, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_set_function(retval, &njs_vm_ctor(vm, njs_prop_magic32(prop))); @@ -325,7 +323,7 @@ njs_vm_external_constructor_handler(njs_vm_t *vm, njs_object_prop_t *prop, njs_int_t njs_vm_external_constructor(njs_vm_t *vm, const njs_str_t *name, - njs_function_native_t native, const njs_external_t *ctor_props, + const njs_function_native_t native, const njs_external_t *ctor_props, njs_uint_t ctor_nprops, const njs_external_t *proto_props, njs_uint_t proto_nprops) { @@ -445,8 +443,8 @@ njs_value_external_tag(const njs_value_t *value) njs_int_t -njs_external_property(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +njs_external_property(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { char *p; njs_int_t i; diff --git a/src/njs_flathsh.c b/src/njs_flathsh.c index c823c466..f2387c95 100644 --- a/src/njs_flathsh.c +++ b/src/njs_flathsh.c @@ -144,13 +144,6 @@ njs_flathsh_chunk(njs_flathsh_descr_t *h) } -njs_inline njs_flathsh_elt_t * -njs_hash_elts(njs_flathsh_descr_t *h) -{ - return (njs_flathsh_elt_t *) ((char *) h + sizeof(njs_flathsh_descr_t)); -} - - /* * Create a new empty flat hash. */ @@ -343,8 +336,6 @@ njs_flathsh_find(const njs_flathsh_t *fh, njs_flathsh_query_t *fhq) while (elt_num != 0) { e = &elts[elt_num - 1]; - /* TODO: need to be replaced by atomic test. */ - if (e->key_hash == fhq->key_hash && fhq->proto->test(fhq, e->value) == NJS_OK) { @@ -359,6 +350,37 @@ njs_flathsh_find(const njs_flathsh_t *fh, njs_flathsh_query_t *fhq) } +njs_int_t +njs_flathsh_unique_find(const njs_flathsh_t *fh, njs_flathsh_query_t *fhq) +{ + njs_int_t cell_num, elt_num; + njs_flathsh_elt_t *e, *elts; + njs_flathsh_descr_t *h; + + h = fh->slot; + if (njs_slow_path(h == NULL)) { + return NJS_DECLINED; + } + + cell_num = fhq->key_hash & h->hash_mask; + elt_num = njs_hash_cells_end(h)[-cell_num - 1]; + elts = njs_hash_elts(h); + + while (elt_num != 0) { + e = &elts[elt_num - 1]; + + if (e->key_hash == fhq->key_hash) { + fhq->value = e->value; + return NJS_OK; + } + + elt_num = e->next_elt; + } + + return NJS_DECLINED; +} + + njs_int_t njs_flathsh_insert(njs_flathsh_t *fh, njs_flathsh_query_t *fhq) { @@ -385,8 +407,6 @@ njs_flathsh_insert(njs_flathsh_t *fh, njs_flathsh_query_t *fhq) while (elt_num != 0) { elt = &elts[elt_num - 1]; - /* TODO: need to be replaced by atomic test. */ - if (elt->key_hash == fhq->key_hash && fhq->proto->test(fhq, elt->value) == NJS_OK) { @@ -418,6 +438,61 @@ njs_flathsh_insert(njs_flathsh_t *fh, njs_flathsh_query_t *fhq) } +njs_int_t +njs_flathsh_unique_insert(njs_flathsh_t *fh, njs_flathsh_query_t *fhq) +{ + void *tmp; + njs_int_t cell_num, elt_num; + njs_flathsh_elt_t *elt, *elts; + njs_flathsh_descr_t *h; + + h = fh->slot; + + if (h == NULL) { + h = njs_flathsh_new(fhq); + if (h == NULL) { + return NJS_ERROR; + } + + fh->slot = h; + } + + cell_num = fhq->key_hash & h->hash_mask; + elt_num = njs_hash_cells_end(h)[-cell_num - 1]; + elts = njs_hash_elts(h); + + while (elt_num != 0) { + elt = &elts[elt_num - 1]; + + if (elt->key_hash == fhq->key_hash) { + if (fhq->replace) { + tmp = fhq->value; + fhq->value = elt->value; + elt->value = tmp; + + return NJS_OK; + + } else { + fhq->value = elt->value; + + return NJS_DECLINED; + } + } + + elt_num = elt->next_elt; + } + + elt = njs_flathsh_add_elt(fh, fhq); + if (elt == NULL) { + return NJS_ERROR; + } + + elt->value = fhq->value; + + return NJS_OK; +} + + static njs_flathsh_descr_t * njs_shrink_elts(njs_flathsh_query_t *fhq, njs_flathsh_descr_t *h) { @@ -502,8 +577,6 @@ njs_flathsh_delete(njs_flathsh_t *fh, njs_flathsh_query_t *fhq) while (elt_num != 0) { elt = &elts[elt_num - 1]; - /* TODO: use atomic comparision. */ - if (elt->key_hash == fhq->key_hash && fhq->proto->test(fhq, elt->value) == NJS_OK) { @@ -550,11 +623,75 @@ njs_flathsh_delete(njs_flathsh_t *fh, njs_flathsh_query_t *fhq) } -void * +njs_int_t +njs_flathsh_unique_delete(njs_flathsh_t *fh, njs_flathsh_query_t *fhq) +{ + njs_int_t cell_num, elt_num; + njs_flathsh_elt_t *elt, *elt_prev, *elts; + njs_flathsh_descr_t *h; + + h = fh->slot; + + if (njs_slow_path(h == NULL)) { + return NJS_DECLINED; + } + + cell_num = fhq->key_hash & h->hash_mask; + elt_num = njs_hash_cells_end(h)[-cell_num - 1]; + elts = njs_hash_elts(h); + elt_prev = NULL; + + while (elt_num != 0) { + elt = &elts[elt_num - 1]; + + if (elt->key_hash == fhq->key_hash) { + fhq->value = elt->value; + + if (elt_prev != NULL) { + elt_prev->next_elt = elt->next_elt; + + } else { + njs_hash_cells_end(h)[-cell_num - 1] = elt->next_elt; + } + + h->elts_deleted_count++; + + elt->value = NULL; + + /* Shrink elts if elts_deleted_count is eligible. */ + + if (h->elts_deleted_count >= NJS_FLATHSH_ELTS_MINIMUM_TO_SHRINK + && h->elts_deleted_count + >= (h->elts_count / NJS_FLATHSH_ELTS_FRACTION_TO_SHRINK)) + { + h = njs_shrink_elts(fhq, h); + if (njs_slow_path(h == NULL)) { + return NJS_ERROR; + } + + fh->slot = h; + } + + if (h->elts_deleted_count == h->elts_count) { + njs_flathsh_free(fhq, njs_flathsh_chunk(h)); + fh->slot = NULL; + } + + return NJS_OK; + } + + elt_prev = elt; + elt_num = elt->next_elt; + } + + return NJS_DECLINED; +} + + +njs_flathsh_elt_t * njs_flathsh_each(const njs_flathsh_t *fh, njs_flathsh_each_t *fhe) { - void *v; - njs_flathsh_elt_t *elt; + njs_flathsh_elt_t *e, *elt; njs_flathsh_descr_t *h; h = fh->slot; @@ -565,9 +702,9 @@ njs_flathsh_each(const njs_flathsh_t *fh, njs_flathsh_each_t *fhe) elt = njs_hash_elts(h); while (fhe->cp < h->elts_count) { - v = elt[fhe->cp++].value; - if (v != NULL) { - return v; + e = &elt[fhe->cp++]; + if (e->value != NULL) { + return e; } } diff --git a/src/njs_flathsh.h b/src/njs_flathsh.h index d347bb81..651afcff 100644 --- a/src/njs_flathsh.h +++ b/src/njs_flathsh.h @@ -64,6 +64,10 @@ struct njs_flathsh_query_s { ((fhl)->slot == (fhr)->slot) +#define njs_hash_elts(h) \ + ((njs_flathsh_elt_t *) ((char *) (h) + 16 /* njs_flathsh_descr_t size */)) + + /* * njs_flathsh_find() finds a hash element. If the element has been * found then it is stored in the fhq->value and njs_flathsh_find() @@ -73,6 +77,11 @@ struct njs_flathsh_query_s { */ NJS_EXPORT njs_int_t njs_flathsh_find(const njs_flathsh_t *fh, njs_flathsh_query_t *fhq); +/* + * The same as njs_flathsh_find(), but for hashes with unique keys. + */ +NJS_EXPORT njs_int_t njs_flathsh_unique_find(const njs_flathsh_t *fh, + njs_flathsh_query_t *fhq); /* * njs_flathsh_insert() adds a hash element. If the element is already @@ -91,6 +100,11 @@ NJS_EXPORT njs_int_t njs_flathsh_find(const njs_flathsh_t *fh, */ NJS_EXPORT njs_int_t njs_flathsh_insert(njs_flathsh_t *fh, njs_flathsh_query_t *fhq); +/* + * The same as njs_flathsh_insert(), but for hashes with unique keys. + */ +NJS_EXPORT njs_int_t njs_flathsh_unique_insert(njs_flathsh_t *fh, + njs_flathsh_query_t *fhq); /* * njs_flathsh_delete() deletes a hash element. If the element has been @@ -102,11 +116,14 @@ NJS_EXPORT njs_int_t njs_flathsh_insert(njs_flathsh_t *fh, */ NJS_EXPORT njs_int_t njs_flathsh_delete(njs_flathsh_t *fh, njs_flathsh_query_t *fhq); +/* + * The same as njs_flathsh_delete(), but for hashes with unique keys. + */ +NJS_EXPORT njs_int_t njs_flathsh_unique_delete(njs_flathsh_t *fh, + njs_flathsh_query_t *fhq); typedef struct { - const njs_flathsh_proto_t *proto; - uint32_t key_hash; uint32_t cp; } njs_flathsh_each_t; @@ -114,11 +131,10 @@ typedef struct { #define njs_flathsh_each_init(lhe, _proto) \ do { \ njs_memzero(lhe, sizeof(njs_flathsh_each_t)); \ - (lhe)->proto = _proto; \ } while (0) -NJS_EXPORT void *njs_flathsh_each(const njs_flathsh_t *fh, +NJS_EXPORT njs_flathsh_elt_t *njs_flathsh_each(const njs_flathsh_t *fh, njs_flathsh_each_t *fhe); /* @@ -151,7 +167,19 @@ typedef struct njs_flathsh_proto_s njs_lvlhsh_proto_t; #define njs_lvlhsh_insert(lh, lhq) njs_flathsh_insert(lh, lhq) #define njs_lvlhsh_delete(lh, lhq) njs_flathsh_delete(lh, lhq) #define njs_lvlhsh_each_init(lhe, _proto) njs_flathsh_each_init(lhe, _proto) -#define njs_lvlhsh_each(lh, lhe) njs_flathsh_each(lh, lhe) + +njs_inline void * +njs_lvlhsh_each(const njs_flathsh_t *lh, njs_flathsh_each_t *lhe) +{ + njs_flathsh_elt_t *e; + + e = njs_flathsh_each(lh, lhe); + if (e == NULL) { + return NULL; + } + + return e->value; +} #endif /* _NJS_FLATHSH_H_INCLUDED_ */ diff --git a/src/njs_function.c b/src/njs_function.c index 326549f5..0840d437 100644 --- a/src/njs_function.c +++ b/src/njs_function.c @@ -118,15 +118,15 @@ njs_int_t njs_function_name_set(njs_vm_t *vm, njs_function_t *function, njs_value_t *name, const char *prefix) { - u_char *p; - size_t len, symbol; - njs_int_t ret; - njs_value_t value; - njs_string_prop_t string; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; - - prop = njs_object_prop_alloc(vm, &njs_string_name, name, 0); + u_char *p; + size_t len, symbol; + njs_int_t ret; + njs_value_t value; + njs_string_prop_t string; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; + + prop = njs_object_prop_alloc(vm, name, 0); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -142,7 +142,7 @@ njs_function_name_set(njs_vm_t *vm, njs_function_t *function, if (prefix != NULL || symbol != 0) { if (njs_is_defined(njs_prop_value(prop))) { njs_value_assign(&value, njs_prop_value(prop)); - (void) njs_string_prop(&string, &value); + (void) njs_string_prop(vm, &string, &value); len = (prefix != NULL) ? njs_strlen(prefix) + 1: 0; p = njs_string_alloc(vm, njs_prop_value(prop), @@ -168,20 +168,19 @@ njs_function_name_set(njs_vm_t *vm, njs_function_t *function, } } else { - njs_value_assign(njs_prop_value(prop), &njs_string_empty); + njs_set_empty_string(vm, njs_prop_value(prop)); } } prop->configurable = 1; - lhq.key_hash = NJS_NAME_HASH; - lhq.key = njs_str_value("name"); - lhq.replace = 0; lhq.value = prop; - lhq.proto = &njs_object_hash_proto; + lhq.key_hash = NJS_ATOM_STRING_name; + lhq.replace = 0; lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(&function->object.hash, &lhq); + ret = njs_flathsh_unique_insert(&function->object.hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; @@ -251,8 +250,6 @@ njs_function_arguments_object_init(njs_vm_t *vm, njs_native_frame_t *frame) njs_value_t value, length; njs_object_t *arguments; - static const njs_value_t string_length = njs_string("length"); - arguments = njs_object_alloc(vm); if (njs_slow_path(arguments == NULL)) { return NJS_ERROR; @@ -263,9 +260,8 @@ njs_function_arguments_object_init(njs_vm_t *vm, njs_native_frame_t *frame) njs_set_object(&value, arguments); njs_set_number(&length, frame->nargs); - ret = njs_object_prop_define(vm, &value, njs_value_arg(&string_length), - &length, NJS_OBJECT_PROP_VALUE_CW, - NJS_LENGTH_HASH); + ret = njs_object_prop_define(vm, &value, NJS_ATOM_STRING_length, &length, + NJS_OBJECT_PROP_VALUE_CW); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -328,14 +324,16 @@ njs_function_prototype_thrower(njs_vm_t *vm, njs_value_t *args, } -const njs_object_prop_t njs_arguments_object_instance_properties[] = +const njs_object_prop_init_t njs_arguments_object_instance_properties[] = { { - .type = NJS_ACCESSOR, - .name = njs_string("callee"), - .u.accessor = njs_accessor(njs_function_prototype_thrower, 0, - njs_function_prototype_thrower, 0), - .writable = NJS_ATTRIBUTE_UNSET, + .atom_id = NJS_ATOM_STRING_callee, + .desc = { + .type = NJS_ACCESSOR, + .u.accessor = njs_accessor(njs_function_prototype_thrower, 0, + njs_function_prototype_thrower, 0), + .writable = NJS_ATTRIBUTE_UNSET, + }, }, }; @@ -905,16 +903,14 @@ njs_function_capture_global_closures(njs_vm_t *vm, njs_function_t *function) static njs_value_t * -njs_function_property_prototype_set(njs_vm_t *vm, njs_lvlhsh_t *hash, +njs_function_property_prototype_set(njs_vm_t *vm, njs_flathsh_t *hash, njs_value_t *prototype) { - njs_int_t ret; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; - const njs_value_t proto_string = njs_string("prototype"); - - prop = njs_object_prop_alloc(vm, &proto_string, prototype, 0); + prop = njs_object_prop_alloc(vm, prototype, 0); if (njs_slow_path(prop == NULL)) { return NULL; } @@ -922,13 +918,12 @@ njs_function_property_prototype_set(njs_vm_t *vm, njs_lvlhsh_t *hash, prop->writable = 1; lhq.value = prop; - lhq.key_hash = NJS_PROTOTYPE_HASH; - lhq.key = njs_str_value("prototype"); + lhq.key_hash = NJS_ATOM_STRING_prototype; lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(hash, &lhq); + ret = njs_flathsh_unique_insert(hash, &lhq); if (njs_fast_path(ret == NJS_OK)) { return njs_prop_value(prop); @@ -952,7 +947,8 @@ njs_function_property_prototype_set(njs_vm_t *vm, njs_lvlhsh_t *hash, njs_int_t njs_function_prototype_create(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_value_t *proto, proto_value, *cons; njs_object_t *prototype; @@ -1002,6 +998,7 @@ njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_int_t ret; njs_str_t str, file; njs_uint_t i; + njs_value_t name; njs_parser_t parser; njs_vm_code_t *code; njs_function_t *function; @@ -1072,7 +1069,7 @@ njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, file = njs_str_value("runtime"); ret = njs_parser_init(vm, &parser, NULL, &file, str.start, - str.start + str.length, 1); + str.start + str.length); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -1139,8 +1136,9 @@ njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, function->global_this = 1; function->args_count = lambda->nargs - lambda->rest_parameters; - ret = njs_function_name_set(vm, function, - njs_value_arg(&njs_string_anonymous), NULL); + njs_atom_to_value(vm, &name, NJS_ATOM_STRING_anonymous); + + ret = njs_function_name_set(vm, function, &name, NULL); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -1156,13 +1154,14 @@ fail: } -static const njs_object_prop_t njs_function_constructor_properties[] = +static const njs_object_prop_init_t njs_function_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("Function"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -1174,7 +1173,8 @@ const njs_object_init_t njs_function_constructor_init = { njs_int_t njs_function_instance_length(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_function_t *function; @@ -1193,7 +1193,8 @@ njs_function_instance_length(njs_vm_t *vm, njs_object_prop_t *prop, njs_int_t njs_function_instance_name(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_function_t *function; @@ -1209,7 +1210,7 @@ njs_function_instance_name(njs_vm_t *vm, njs_object_prop_t *prop, return NJS_OK; } - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -1376,14 +1377,13 @@ njs_function_prototype_bind(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, function->context = njs_function(&args[0]); - ret = njs_value_property(vm, &args[0], njs_value_arg(&njs_string_name), - &name); + ret = njs_value_property(vm, &args[0], NJS_ATOM_STRING_name, &name); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } if (!njs_is_string(&name)) { - name = njs_string_empty; + njs_set_empty_string(vm, &name); } ret = njs_function_name_set(vm, function, &name, "bound"); @@ -1428,38 +1428,43 @@ njs_function_prototype_bind(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_object_prop_t njs_function_prototype_properties[] = +static const njs_object_prop_init_t njs_function_prototype_properties[] = { NJS_DECLARE_PROP_LENGTH(0), NJS_DECLARE_PROP_NAME(""), - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_NATIVE("call", njs_function_prototype_call, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_call, njs_function_prototype_call, 1, 0), - NJS_DECLARE_PROP_NATIVE("apply", njs_function_prototype_apply, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_apply, njs_function_prototype_apply, 2, + 0), - NJS_DECLARE_PROP_NATIVE("bind", njs_function_prototype_bind, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_bind, njs_function_prototype_bind, 1, 0), { - .type = NJS_ACCESSOR, - .name = njs_string("caller"), - .u.accessor = njs_accessor(njs_function_prototype_thrower, 0, - njs_function_prototype_thrower, 0), - .writable = NJS_ATTRIBUTE_UNSET, - .configurable = 1, + .atom_id = NJS_ATOM_STRING_caller, + .desc = { + .type = NJS_ACCESSOR, + .u.accessor = njs_accessor(njs_function_prototype_thrower, 0, + njs_function_prototype_thrower, 0), + .writable = NJS_ATTRIBUTE_UNSET, + .configurable = 1, + }, }, { - .type = NJS_ACCESSOR, - .name = njs_string("arguments"), - .u.accessor = njs_accessor(njs_function_prototype_thrower, 0, - njs_function_prototype_thrower, 0), - .writable = NJS_ATTRIBUTE_UNSET, - .configurable = 1, + .atom_id = NJS_ATOM_STRING_arguments, + .desc = { + .type = NJS_ACCESSOR, + .u.accessor = njs_accessor(njs_function_prototype_thrower, 0, + njs_function_prototype_thrower, 0), + .writable = NJS_ATTRIBUTE_UNSET, + .configurable = 1, + }, }, }; @@ -1470,15 +1475,16 @@ const njs_object_init_t njs_function_prototype_init = { }; -const njs_object_prop_t njs_function_instance_properties[] = +const njs_object_prop_init_t njs_function_instance_properties[] = { - NJS_DECLARE_PROP_HANDLER("length", njs_function_instance_length, 0, 0, - NJS_OBJECT_PROP_VALUE_C), + NJS_DECLARE_PROP_HANDLER(STRING_length, njs_function_instance_length, + 0, NJS_OBJECT_PROP_VALUE_C), - NJS_DECLARE_PROP_HANDLER("name", njs_function_instance_name, 0, 0, + NJS_DECLARE_PROP_HANDLER(STRING_name, njs_function_instance_name, 0, NJS_OBJECT_PROP_VALUE_C), - NJS_DECLARE_PROP_HANDLER("prototype", njs_function_prototype_create, 0, 0, + NJS_DECLARE_PROP_HANDLER(STRING_prototype, + njs_function_prototype_create, 0, NJS_OBJECT_PROP_VALUE_W), }; @@ -1489,12 +1495,12 @@ const njs_object_init_t njs_function_instance_init = { }; -const njs_object_prop_t njs_arrow_instance_properties[] = +const njs_object_prop_init_t njs_arrow_instance_properties[] = { - NJS_DECLARE_PROP_HANDLER("length", njs_function_instance_length, 0, 0, - NJS_OBJECT_PROP_VALUE_C), + NJS_DECLARE_PROP_HANDLER(STRING_length, njs_function_instance_length, + 0, NJS_OBJECT_PROP_VALUE_C), - NJS_DECLARE_PROP_HANDLER("name", njs_function_instance_name, 0, 0, + NJS_DECLARE_PROP_HANDLER(STRING_name, njs_function_instance_name, 0, NJS_OBJECT_PROP_VALUE_C), }; diff --git a/src/njs_function.h b/src/njs_function.h index 0b316251..6516ff78 100644 --- a/src/njs_function.h +++ b/src/njs_function.h @@ -94,13 +94,16 @@ njs_int_t njs_function_arguments_object_init(njs_vm_t *vm, njs_int_t njs_function_rest_parameters_init(njs_vm_t *vm, njs_native_frame_t *frame); njs_int_t njs_function_prototype_create(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); njs_int_t njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); njs_int_t njs_function_instance_length(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); njs_int_t njs_function_instance_name(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); njs_int_t njs_eval_function(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); njs_int_t njs_function_native_frame(njs_vm_t *vm, njs_function_t *function, diff --git a/src/njs_generator.c b/src/njs_generator.c index 2e81a407..a2cc4b1c 100644 --- a/src/njs_generator.c +++ b/src/njs_generator.c @@ -1062,11 +1062,11 @@ static njs_int_t njs_generate_var_statement_after(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { - njs_int_t ret; - njs_variable_t *var; - njs_parser_node_t *lvalue, *expr; - njs_vmcode_move_t *move; - const njs_lexer_entry_t *lex_entry; + njs_int_t ret; + njs_string_t name; + njs_variable_t *var; + njs_parser_node_t *lvalue, *expr; + njs_vmcode_move_t *move; lvalue = node->left; expr = node->right; @@ -1093,20 +1093,14 @@ njs_generate_var_statement_after(njs_vm_t *vm, njs_generator_t *generator, node->index = expr->index; node->temporary = expr->temporary; - if ((expr->token_type == NJS_TOKEN_FUNCTION_EXPRESSION + if (expr->token_type == NJS_TOKEN_FUNCTION_EXPRESSION || expr->token_type == NJS_TOKEN_ASYNC_FUNCTION_EXPRESSION) - && njs_values_same(&expr->u.value.data.u.lambda->name, - &njs_string_empty)) { - lex_entry = njs_lexer_entry(node->left->u.reference.unique_id); - if (njs_slow_path(lex_entry == NULL)) { - return NJS_ERROR; - } + njs_string_get_unsafe(&expr->u.value.data.u.lambda->name, &name); - ret = njs_string_create(vm, &expr->u.value.data.u.lambda->name, - lex_entry->name.start, lex_entry->name.length); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; + if (name.length == 0) { + njs_atom_to_value(vm, &expr->u.value.data.u.lambda->name, + node->left->u.reference.atom_id); } } @@ -3023,11 +3017,9 @@ static njs_int_t njs_generate_global_property_set(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node_dst, njs_parser_node_t *node_src) { - njs_int_t ret; - njs_value_t property; - njs_variable_t *var; - njs_vmcode_prop_set_t *prop_set; - const njs_lexer_entry_t *lex_entry; + njs_value_t property; + njs_variable_t *var; + njs_vmcode_prop_set_t *prop_set; var = njs_variable_reference(vm, node_dst); if (var == NULL) { @@ -3037,16 +3029,7 @@ njs_generate_global_property_set(njs_vm_t *vm, njs_generator_t *generator, prop_set->value = node_dst->index; prop_set->object = njs_scope_global_this_index(); - lex_entry = njs_lexer_entry(node_dst->u.reference.unique_id); - if (njs_slow_path(lex_entry == NULL)) { - return NJS_ERROR; - } - - ret = njs_string_create(vm, &property, lex_entry->name.start, - lex_entry->name.length); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } + njs_atom_to_value(vm, &property,node_dst->u.reference.atom_id); prop_set->property = njs_scope_global_index(vm, &property, generator->runtime); @@ -3628,11 +3611,11 @@ static njs_int_t njs_generate_function_expression(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { - njs_int_t ret; - njs_variable_t *var; - njs_function_lambda_t *lambda; - njs_vmcode_function_t *function; - const njs_lexer_entry_t *lex_entry; + njs_int_t ret; + njs_str_t name; + njs_variable_t *var; + njs_function_lambda_t *lambda; + njs_vmcode_function_t *function; var = njs_variable_reference(vm, node->left); if (njs_slow_path(var == NULL)) { @@ -3646,23 +3629,14 @@ njs_generate_function_expression(njs_vm_t *vm, njs_generator_t *generator, lambda = node->u.value.data.u.lambda; - lex_entry = njs_lexer_entry(var->unique_id); - if (njs_slow_path(lex_entry == NULL)) { - return NJS_ERROR; - } + njs_atom_to_value(vm, &lambda->name, var->atom_id); + njs_string_get(vm, &lambda->name, &name); - ret = njs_generate_function_scope(vm, generator, lambda, node, - &lex_entry->name); + ret = njs_generate_function_scope(vm, generator, lambda, node, &name); if (njs_slow_path(ret != NJS_OK)) { return ret; } - ret = njs_string_create(vm, &lambda->name, lex_entry->name.start, - lex_entry->name.length); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } - njs_generate_code(generator, njs_vmcode_function_t, function, NJS_VMCODE_FUNCTION, node); function->lambda = lambda; @@ -4188,12 +4162,12 @@ static njs_int_t njs_generate_function_declaration(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { - njs_int_t ret; - njs_bool_t async; - njs_variable_t *var; - njs_function_t *function; - njs_function_lambda_t *lambda; - const njs_lexer_entry_t *lex_entry; + njs_int_t ret; + njs_str_t name; + njs_bool_t async; + njs_variable_t *var; + njs_function_t *function; + njs_function_lambda_t *lambda; var = njs_variable_reference(vm, node); if (njs_slow_path(var == NULL)) { @@ -4207,19 +4181,10 @@ njs_generate_function_declaration(njs_vm_t *vm, njs_generator_t *generator, lambda = njs_variable_lambda(var); - lex_entry = njs_lexer_entry(node->u.reference.unique_id); - if (njs_slow_path(lex_entry == NULL)) { - return NJS_ERROR; - } + njs_atom_to_value(vm, &lambda->name, node->u.reference.atom_id); + njs_string_get(vm, &lambda->name, &name); - ret = njs_string_create(vm, &lambda->name, lex_entry->name.start, - lex_entry->name.length); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } - - ret = njs_generate_function_scope(vm, generator, lambda, node, - &lex_entry->name); + ret = njs_generate_function_scope(vm, generator, lambda, node, &name); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -5388,11 +5353,9 @@ static njs_int_t njs_generate_global_reference(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node, njs_bool_t exception) { - njs_int_t ret; - njs_index_t index; - njs_value_t property; - njs_vmcode_prop_get_t *prop_get; - const njs_lexer_entry_t *lex_entry; + njs_index_t index; + njs_value_t property; + njs_vmcode_prop_get_t *prop_get; index = njs_generate_temp_index_get(vm, generator, node); if (njs_slow_path(index == NJS_INDEX_ERROR)) { @@ -5410,16 +5373,7 @@ njs_generate_global_reference(njs_vm_t *vm, njs_generator_t *generator, return NJS_ERROR; } - lex_entry = njs_lexer_entry(node->u.reference.unique_id); - if (njs_slow_path(lex_entry == NULL)) { - return NJS_ERROR; - } - - ret = njs_string_create(vm, &property, lex_entry->name.start, - lex_entry->name.length); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } + njs_atom_to_value(vm, &property, node->u.reference.atom_id); prop_get->property = njs_scope_global_index(vm, &property, generator->runtime); @@ -5441,8 +5395,8 @@ static njs_int_t njs_generate_reference_error(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { - njs_vmcode_error_t *ref_err; - const njs_lexer_entry_t *lex_entry; + njs_str_t entry; + njs_vmcode_error_t *ref_err; if (njs_slow_path(!node->u.reference.not_defined)) { njs_internal_error(vm, "variable is not defined but not_defined " @@ -5454,12 +5408,10 @@ njs_generate_reference_error(njs_vm_t *vm, njs_generator_t *generator, NULL); ref_err->type = NJS_OBJ_TYPE_REF_ERROR; - lex_entry = njs_lexer_entry(node->u.reference.unique_id); - if (njs_slow_path(lex_entry == NULL)) { - return NJS_ERROR; - } - return njs_name_copy(vm, &ref_err->u.name, &lex_entry->name); + njs_lexer_entry(vm, node->u.reference.atom_id, &entry); + + return njs_name_copy(vm, &ref_err->u.name, &entry); } diff --git a/src/njs_iterator.c b/src/njs_iterator.c index 34bb073e..7bb6a6ce 100644 --- a/src/njs_iterator.c +++ b/src/njs_iterator.c @@ -18,10 +18,6 @@ struct njs_value_iterator_s { typedef struct njs_value_iterator_s njs_array_iterator_t; -static const njs_value_t string_done = njs_string("done"); -static const njs_value_t string_value = njs_string("value"); - - static njs_int_t njs_iterator_object_handler(njs_vm_t *vm, njs_iterator_handler_t handler, njs_iterator_args_t *args, njs_value_t *key, int64_t i, njs_value_t *retval); @@ -179,15 +175,10 @@ njs_iterator_prototype_get_this(njs_vm_t *vm, njs_value_t *args, } -static const njs_object_prop_t njs_iterator_prototype_properties[] = +static const njs_object_prop_init_t njs_iterator_prototype_properties[] = { - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_ITERATOR), - .u.value = njs_native_function(njs_iterator_prototype_get_this, 0), - .configurable = 1, - .writable = 1, - }, + NJS_DECLARE_PROP_NATIVE(SYMBOL_iterator, + njs_iterator_prototype_get_this, 0, 0), }; @@ -232,14 +223,12 @@ njs_array_iterator_prototype_next(njs_vm_t *vm, njs_value_t *args, njs_set_object(retval, object); - prop_value = njs_object_property_add(vm, retval, - njs_value_arg(&string_value), 0); + prop_value = njs_object_property_add(vm, retval, NJS_ATOM_STRING_value, 0); if (njs_slow_path(prop_value == NULL)) { return NJS_ERROR; } - prop_done = njs_object_property_add(vm, retval, - njs_value_arg(&string_done), 0); + prop_done = njs_object_property_add(vm, retval, NJS_ATOM_STRING_done, 0); if (njs_slow_path(prop_done == NULL)) { return NJS_ERROR; } @@ -262,17 +251,14 @@ njs_array_iterator_prototype_next(njs_vm_t *vm, njs_value_t *args, } -static const njs_object_prop_t njs_array_iterator_prototype_properties[] = +static const njs_object_prop_init_t njs_array_iterator_prototype_properties[] = { - NJS_DECLARE_PROP_NATIVE("next", njs_array_iterator_prototype_next, 0, - NJS_DATA_TAG_ARRAY_ITERATOR), - - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.value = njs_string("Array Iterator"), - .configurable = 1, - }, + NJS_DECLARE_PROP_NATIVE(STRING_next, njs_array_iterator_prototype_next, + 0, NJS_DATA_TAG_ARRAY_ITERATOR), + + NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, + njs_ascii_strval("Array Iterator"), + NJS_OBJECT_PROP_VALUE_C), }; @@ -349,7 +335,7 @@ njs_object_iterate(njs_vm_t *vm, njs_iterator_args_t *args, value = njs_object_value(value); } - length = njs_string_prop(&string_prop, value); + length = njs_string_prop(vm, &string_prop, value); p = string_prop.start; end = p + string_prop.size; @@ -358,8 +344,10 @@ njs_object_iterate(njs_vm_t *vm, njs_iterator_args_t *args, /* ASCII string. */ for (i = from; i < to; i++) { - /* This cannot fail. */ - (void) njs_string_new(vm, &character, p + i, 1, 1); + ret = njs_string_new(vm, &character, p + i, 1, 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } ret = handler(vm, args, &character, i, retval); if (njs_slow_path(ret != NJS_OK)) { @@ -377,8 +365,10 @@ njs_object_iterate(njs_vm_t *vm, njs_iterator_args_t *args, for (i = from; i < to; i++) { pos = njs_utf8_next(p, end); - /* This cannot fail. */ - (void) njs_string_new(vm, &character, p, pos - p, 1); + ret = njs_string_new(vm, &character, p, pos - p, 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } ret = handler(vm, args, &character, i, retval); if (njs_slow_path(ret != NJS_OK)) { @@ -502,7 +492,7 @@ njs_object_iterate_reverse(njs_vm_t *vm, njs_iterator_args_t *args, value = njs_object_value(value); } - length = njs_string_prop(&string_prop, value); + length = njs_string_prop(vm, &string_prop, value); end = string_prop.start + string_prop.size; if ((size_t) length == string_prop.size) { @@ -513,8 +503,10 @@ njs_object_iterate_reverse(njs_vm_t *vm, njs_iterator_args_t *args, i = from + 1; while (i-- > to) { - /* This cannot fail. */ - (void) njs_string_new(vm, &character, p, 1, 1); + ret = njs_string_new(vm, &character, p, 1, 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } ret = handler(vm, args, &character, i, retval); if (njs_slow_path(ret != NJS_OK)) { @@ -542,8 +534,10 @@ njs_object_iterate_reverse(njs_vm_t *vm, njs_iterator_args_t *args, while (i-- > to) { pos = njs_utf8_prev(p, string_prop.start); - /* This cannot fail. */ - (void) njs_string_new(vm, &character, pos, p - pos , 1); + ret = njs_string_new(vm, &character, pos, p - pos , 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } ret = handler(vm, args, &character, i, retval); if (njs_slow_path(ret != NJS_OK)) { @@ -616,7 +610,8 @@ njs_iterator_object_handler(njs_vm_t *vm, njs_iterator_handler_t handler, njs_value_t prop, *entry; if (key != NULL) { - ret = njs_value_property(vm, njs_value_arg(&args->value), key, &prop); + ret = njs_value_property_val(vm, njs_value_arg(&args->value), key, + &prop); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } diff --git a/src/njs_json.c b/src/njs_json.c index 8ba13314..e79b1eb4 100644 --- a/src/njs_json.c +++ b/src/njs_json.c @@ -63,7 +63,7 @@ static const u_char *njs_json_skip_space(const u_char *start, const u_char *end); static njs_int_t njs_json_internalize_property(njs_vm_t *vm, - njs_function_t *reviver, njs_value_t *holder, njs_value_t *name, + njs_function_t *reviver, njs_value_t *holder, uint32_t atom_id, njs_int_t depth, njs_value_t *retval); static void njs_json_parse_exception(njs_json_parse_ctx_t *ctx, const char *msg, const u_char *pos); @@ -80,15 +80,15 @@ static njs_int_t njs_json_stringify_array(njs_json_stringify_t *stringify); static njs_int_t njs_json_append_value(njs_vm_t *vm, njs_chb_t *chain, njs_value_t *value); -static void njs_json_append_string(njs_chb_t *chain, const njs_value_t *value, - char quote); +static void njs_json_append_string(njs_vm_t *vm, njs_chb_t *chain, + const njs_value_t *value, char quote); static void njs_json_append_number(njs_chb_t *chain, const njs_value_t *value); static njs_object_t *njs_json_wrap_value(njs_vm_t *vm, njs_value_t *wrapper, const njs_value_t *value); -static const njs_object_prop_t njs_json_object_properties[]; +static const njs_object_prop_init_t njs_json_object_properties[]; static njs_int_t @@ -112,7 +112,7 @@ njs_json_parse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - (void) njs_string_prop(&string, text); + (void) njs_string_prop(vm, &string, text); p = string.start; end = p + string.size; @@ -149,9 +149,8 @@ njs_json_parse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } return njs_json_internalize_property(vm, njs_function(reviver), - &wrapper, - njs_value_arg(&njs_string_empty), - 0, retval); + &wrapper, NJS_ATOM_STRING_empty, 0, + retval); } njs_value_assign(retval, &value); @@ -166,7 +165,7 @@ njs_vm_json_parse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, { njs_function_t *parse; - parse = njs_function(&njs_json_object_properties[1].u.value); + parse = njs_function(&njs_json_object_properties[1].desc.u.value); return njs_vm_invoke(vm, parse, args, nargs, retval); } @@ -225,7 +224,7 @@ njs_json_stringify(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, switch (space->type) { case NJS_STRING: - length = njs_string_prop(&prop, space); + length = njs_string_prop(vm, &prop, space); p = njs_string_offset(&prop, njs_min(length, 10)); stringify->space.start = prop.start; @@ -272,7 +271,7 @@ njs_vm_json_stringify(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, { njs_function_t *stringify; - stringify = njs_function(&njs_json_object_properties[2].u.value); + stringify = njs_function(&njs_json_object_properties[2].desc.u.value); return njs_vm_invoke(vm, stringify, args, nargs, retval); } @@ -336,11 +335,11 @@ static const u_char * njs_json_parse_object(njs_json_parse_ctx_t *ctx, njs_value_t *value, const u_char *p) { - njs_int_t ret; - njs_object_t *object; - njs_value_t prop_name, prop_value; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_object_t *object; + njs_value_t prop_name, prop_value; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; if (njs_slow_path(--ctx->depth == 0)) { njs_json_parse_exception(ctx, "Nested too deep", p); @@ -395,19 +394,18 @@ njs_json_parse_object(njs_json_parse_ctx_t *ctx, njs_value_t *value, return NULL; } - prop = njs_object_prop_alloc(ctx->vm, &prop_name, &prop_value, 1); + prop = njs_object_prop_alloc(ctx->vm, &prop_value, 1); if (njs_slow_path(prop == NULL)) { goto memory_error; } - njs_string_get(&prop_name, &lhq.key); - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); lhq.value = prop; + lhq.key_hash = prop_name.atom_id; lhq.replace = 1; lhq.pool = ctx->pool; lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(&object->hash, &lhq); + ret = njs_flathsh_unique_insert(&object->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(ctx->vm, "lvlhsh insert/replace failed"); return NULL; @@ -734,7 +732,7 @@ njs_json_parse_string(njs_json_parse_ctx_t *ctx, njs_value_t *value, start = dst; } - ret = njs_string_create(ctx->vm, value, (u_char *) start, size); + ret = njs_atom_string_create(ctx->vm, value, (u_char *) start, size); if (njs_slow_path(ret != NJS_OK)) { return NULL; } @@ -829,12 +827,12 @@ njs_json_skip_space(const u_char *start, const u_char *end) static njs_int_t njs_json_internalize_property(njs_vm_t *vm, njs_function_t *reviver, - njs_value_t *holder, njs_value_t *name, njs_int_t depth, + njs_value_t *holder, uint32_t atom_id, njs_int_t depth, njs_value_t *retval) { int64_t k, length; njs_int_t ret; - njs_value_t val, new_elem, index; + njs_value_t val, new_elem; njs_value_t arguments[3]; njs_array_t *keys; @@ -843,7 +841,7 @@ njs_json_internalize_property(njs_vm_t *vm, njs_function_t *reviver, return NJS_ERROR; } - ret = njs_value_property(vm, holder, name, &val); + ret = njs_value_property(vm, holder, atom_id, &val); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -859,19 +857,21 @@ njs_json_internalize_property(njs_vm_t *vm, njs_function_t *reviver, for (k = 0; k < keys->length; k++) { ret = njs_json_internalize_property(vm, reviver, &val, - &keys->start[k], depth, - &new_elem); + keys->start[k].atom_id, + depth, &new_elem); if (njs_slow_path(ret != NJS_OK)) { goto done; } if (njs_is_undefined(&new_elem)) { - ret = njs_value_property_delete(vm, &val, &keys->start[k], + ret = njs_value_property_delete(vm, &val, + keys->start[k].atom_id, NULL, 0); } else { - ret = njs_value_property_set(vm, &val, &keys->start[k], + ret = njs_value_property_set(vm, &val, + keys->start[k].atom_id, &new_elem); } @@ -888,12 +888,8 @@ njs_json_internalize_property(njs_vm_t *vm, njs_function_t *reviver, } for (k = 0; k < length; k++) { - ret = njs_int64_to_string(vm, &index, k); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } - - ret = njs_json_internalize_property(vm, reviver, &val, &index, + ret = njs_json_internalize_property(vm, reviver, &val, + njs_number_atom(k), depth, &new_elem); if (njs_slow_path(ret != NJS_OK)) { @@ -901,10 +897,13 @@ njs_json_internalize_property(njs_vm_t *vm, njs_function_t *reviver, } if (njs_is_undefined(&new_elem)) { - ret = njs_value_property_delete(vm, &val, &index, NULL, 0); + ret = njs_value_property_delete(vm, &val, + njs_number_atom(k), NULL, + 0); } else { - ret = njs_value_property_set(vm, &val, &index, &new_elem); + ret = njs_value_property_set(vm, &val, njs_number_atom(k), + &new_elem); } if (njs_slow_path(ret == NJS_ERROR)) { @@ -915,7 +914,7 @@ njs_json_internalize_property(njs_vm_t *vm, njs_function_t *reviver, } njs_value_assign(&arguments[0], holder); - njs_value_assign(&arguments[1], name); + njs_atom_to_value(vm, &arguments[1], atom_id); njs_value_assign(&arguments[2], &val); ret = njs_function_apply(vm, reviver, arguments, 3, retval); @@ -1123,7 +1122,7 @@ njs_json_stringify_iterator(njs_json_stringify_t *stringify, key = &state->keys->start[state->index]; } - ret = njs_value_property(stringify->vm, &state->value, key, value); + ret = njs_value_property_val(stringify->vm, &state->value, key, value); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -1161,7 +1160,7 @@ njs_json_stringify_iterator(njs_json_stringify_t *stringify, state->written = 1; if (!state->array) { - njs_json_append_string(&chain, key, '\"'); + njs_json_append_string(stringify->vm, &chain, key, '\"'); njs_chb_append_literal(&chain,":"); if (stringify->space.length != 0) { njs_chb_append_literal(&chain," "); @@ -1232,14 +1231,13 @@ memory_error: static njs_function_t * njs_object_to_json_function(njs_vm_t *vm, njs_value_t *value) { - njs_int_t ret; - njs_value_t retval; - njs_lvlhsh_query_t lhq; - - static const njs_value_t to_json_string = njs_string("toJSON"); + njs_int_t ret; + njs_value_t retval; + njs_flathsh_query_t lhq; if (njs_is_object(value)) { - njs_object_property_init(&lhq, &to_json_string, NJS_TO_JSON_HASH); + lhq.proto = &njs_object_hash_proto; + lhq.key_hash = NJS_ATOM_STRING_toJSON; ret = njs_object_property(vm, njs_object(value), &lhq, &retval); @@ -1258,6 +1256,7 @@ static njs_int_t njs_json_stringify_to_json(njs_json_stringify_t* stringify, njs_json_state_t *state, njs_value_t *key, njs_value_t *value) { + njs_int_t ret; njs_value_t arguments[2]; njs_function_t *to_json; @@ -1276,7 +1275,10 @@ njs_json_stringify_to_json(njs_json_stringify_t* stringify, arguments[1] = *key; } else { - njs_uint32_to_string(&arguments[1], state->index); + ret = njs_uint32_to_string(stringify->vm, &arguments[1], state->index); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } return njs_function_apply(stringify->vm, to_json, arguments, 2, @@ -1288,6 +1290,7 @@ static njs_int_t njs_json_stringify_replacer(njs_json_stringify_t* stringify, njs_json_state_t *state, njs_value_t *key, njs_value_t *value) { + njs_int_t ret; njs_value_t arguments[3]; if (!njs_is_function(&stringify->replacer)) { @@ -1301,7 +1304,10 @@ njs_json_stringify_replacer(njs_json_stringify_t* stringify, arguments[1] = *key; } else { - njs_uint32_to_string(&arguments[1], state->index); + ret = njs_uint32_to_string(stringify->vm, &arguments[1], state->index); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } return njs_function_apply(stringify->vm, njs_function(&stringify->replacer), @@ -1328,7 +1334,7 @@ njs_json_stringify_array(njs_json_stringify_t *stringify) } item = njs_array_push(stringify->vm, properties); - njs_value_assign(item, &njs_string_empty); + njs_set_empty_string(stringify->vm, item); for (i = 0; i < length; i++) { ret = njs_value_property_i64(stringify->vm, &stringify->replacer, i, @@ -1373,7 +1379,9 @@ njs_json_stringify_array(njs_json_stringify_t *stringify) } for (k = 0; k < properties->length; k++) { - if (njs_values_strict_equal(value, &properties->start[k]) == 1) { + if (njs_values_strict_equal(stringify->vm, value, + &properties->start[k]) == 1) + { break; } } @@ -1428,7 +1436,7 @@ njs_json_append_value(njs_vm_t *vm, njs_chb_t *chain, njs_value_t *value) switch (value->type) { case NJS_STRING: - njs_json_append_string(chain, value, '\"'); + njs_json_append_string(vm, chain, value, '\"'); break; case NJS_NUMBER: @@ -1459,7 +1467,8 @@ njs_json_append_value(njs_vm_t *vm, njs_chb_t *chain, njs_value_t *value) static void -njs_json_append_string(njs_chb_t *chain, const njs_value_t *value, char quote) +njs_json_append_string(njs_vm_t *vm, njs_chb_t *chain, const njs_value_t *value, + char quote) { size_t size; u_char c, *dst, *dst_end; @@ -1470,7 +1479,7 @@ njs_json_append_string(njs_chb_t *chain, const njs_value_t *value, char quote) static char hex2char[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - (void) njs_string_prop(&string, value); + (void) njs_string_prop(vm, &string, value); p = string.start; end = p + string.size; @@ -1588,9 +1597,9 @@ static njs_object_t * njs_json_wrap_value(njs_vm_t *vm, njs_value_t *wrapper, const njs_value_t *value) { - njs_int_t ret; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; wrapper->data.u.object = njs_object_alloc(vm); if (njs_slow_path(njs_object(wrapper) == NULL)) { @@ -1600,20 +1609,18 @@ njs_json_wrap_value(njs_vm_t *vm, njs_value_t *wrapper, wrapper->type = NJS_OBJECT; wrapper->data.truth = 1; - lhq.replace = 0; - lhq.proto = &njs_object_hash_proto; - lhq.pool = vm->mem_pool; - lhq.key = njs_str_value(""); - lhq.key_hash = NJS_DJB_HASH_INIT; - - prop = njs_object_prop_alloc(vm, &njs_string_empty, value, 1); + prop = njs_object_prop_alloc(vm, value, 1); if (njs_slow_path(prop == NULL)) { return NULL; } lhq.value = prop; + lhq.key_hash = NJS_ATOM_STRING_empty; + lhq.replace = 0; + lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(njs_object_hash(wrapper), &lhq); + ret = njs_flathsh_unique_insert(njs_object_hash(wrapper), &lhq); if (njs_slow_path(ret != NJS_OK)) { return NULL; } @@ -1622,18 +1629,14 @@ njs_json_wrap_value(njs_vm_t *vm, njs_value_t *wrapper, } -static const njs_object_prop_t njs_json_object_properties[] = +static const njs_object_prop_init_t njs_json_object_properties[] = { - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.value = njs_string("JSON"), - .configurable = 1, - }, + NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, njs_ascii_strval("JSON"), + NJS_OBJECT_PROP_VALUE_C), - NJS_DECLARE_PROP_NATIVE("parse", njs_json_parse, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_parse, njs_json_parse, 2, 0), - NJS_DECLARE_PROP_NATIVE("stringify", njs_json_stringify, 3, 0), + NJS_DECLARE_PROP_NATIVE(STRING_stringify, njs_json_stringify, 3, 0), }; @@ -1653,8 +1656,6 @@ njs_dump_terminal(njs_json_stringify_t *stringify, njs_chb_t *chain, njs_typed_array_t *array; njs_string_prop_t string; - static const njs_value_t name_string = njs_string("name"); - njs_int_t (*to_string)(njs_vm_t *, njs_value_t *, const njs_value_t *); switch (value->type) { @@ -1677,10 +1678,10 @@ njs_dump_terminal(njs_json_stringify_t *stringify, njs_chb_t *chain, break; case NJS_STRING: - njs_string_get(value, &str); + njs_string_get(stringify->vm, value, &str); if (!console || stringify->depth != 0) { - njs_json_append_string(chain, value, '\''); + njs_json_append_string(stringify->vm, chain, value, '\''); return NJS_OK; } @@ -1694,7 +1695,7 @@ njs_dump_terminal(njs_json_stringify_t *stringify, njs_chb_t *chain, return NJS_ERROR; } - njs_string_get(&str_val, &str); + njs_string_get(stringify->vm, &str_val, &str); njs_chb_append_str(chain, &str); break; @@ -1731,7 +1732,7 @@ njs_dump_terminal(njs_json_stringify_t *stringify, njs_chb_t *chain, return NJS_ERROR; } - njs_string_get(&str_val, &str); + njs_string_get(stringify->vm, &str_val, &str); njs_chb_sprintf(chain, 16 + str.length, "[Number: %V]", &str); break; @@ -1741,7 +1742,7 @@ njs_dump_terminal(njs_json_stringify_t *stringify, njs_chb_t *chain, return NJS_ERROR; } - njs_string_get(&str_val, &str); + njs_string_get(stringify->vm, &str_val, &str); njs_chb_sprintf(chain, 16 + str.length, "[Symbol: %V]", &str); break; @@ -1749,7 +1750,7 @@ njs_dump_terminal(njs_json_stringify_t *stringify, njs_chb_t *chain, case NJS_STRING: default: njs_chb_append_literal(chain, "[String: "); - njs_json_append_string(chain, value, '\''); + njs_json_append_string(stringify->vm, chain, value, '\''); njs_chb_append_literal(chain, "]"); break; } @@ -1764,14 +1765,14 @@ njs_dump_terminal(njs_json_stringify_t *stringify, njs_chb_t *chain, str = njs_str_value(""); } - ret = njs_value_property(stringify->vm, value, - njs_value_arg(&name_string), &tag); + ret = njs_value_property(stringify->vm, value, NJS_ATOM_STRING_name, + &tag); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } if (njs_is_string(&tag)) { - njs_string_get(&tag, &str); + njs_string_get(stringify->vm, &tag, &str); } if (str.length != 0) { @@ -1791,7 +1792,7 @@ njs_dump_terminal(njs_json_stringify_t *stringify, njs_chb_t *chain, } if (ret == NJS_OK) { - (void) njs_string_prop(&string, &tag); + (void) njs_string_prop(stringify->vm, &string, &tag); njs_chb_append(chain, string.start, string.size); njs_chb_append_literal(chain, " "); } @@ -1841,7 +1842,7 @@ njs_dump_terminal(njs_json_stringify_t *stringify, njs_chb_t *chain, return NJS_ERROR; } - njs_string_get(&str_val, &str); + njs_string_get(stringify->vm, &str_val, &str); njs_chb_append_str(chain, &str); break; @@ -1874,7 +1875,7 @@ njs_dump_visited(njs_vm_t *vm, njs_json_stringify_t *stringify, depth = stringify->depth - 1; for (; depth >= 0; depth--) { - if (njs_values_same(&stringify->states[depth].value, value)) { + if (njs_values_same(vm, &stringify->states[depth].value, value)) { return 1; } } @@ -1943,11 +1944,6 @@ njs_dump_empty(njs_json_stringify_t *stringify, njs_json_state_t *state, } -static const njs_value_t string_get = njs_string("[Getter]"); -static const njs_value_t string_set = njs_string("[Setter]"); -static const njs_value_t string_get_set = njs_long_string("[Getter/Setter]"); - - njs_int_t njs_vm_value_dump(njs_vm_t *vm, njs_str_t *retval, njs_value_t *value, njs_uint_t console, njs_uint_t indent) @@ -1955,7 +1951,7 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_t *retval, njs_value_t *value, njs_int_t ret; njs_chb_t chain; njs_str_t str; - njs_value_t *key, *val, tag, exception; + njs_value_t *key, *val, s, tag, exception; njs_json_state_t *state; njs_string_prop_t string; njs_object_prop_t *prop; @@ -2009,7 +2005,7 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_t *retval, njs_value_t *value, } if (ret == NJS_OK) { - (void) njs_string_prop(&string, &tag); + (void) njs_string_prop(vm, &string, &tag); njs_chb_append(&chain, string.start, string.size); njs_chb_append_literal(&chain, " "); } @@ -2032,22 +2028,17 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_t *retval, njs_value_t *value, continue; } - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0, 0); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); key = &state->keys->start[state->index++]; - if(state->array) { - if (key->type == NJS_STRING) { - njs_string_get(key, &str); - if (str.length == 6 && memcmp(str.start, "length", 6) == 0) { - continue; - } - } + if (state->array && key->atom_id == NJS_ATOM_STRING_length) { + continue; } state->key = key; - ret = njs_property_query(vm, &pq, &state->value, key); + ret = njs_property_query_val(vm, &pq, &state->value, key); if (njs_slow_path(ret != NJS_OK)) { if (ret == NJS_DECLINED) { continue; @@ -2074,7 +2065,7 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_t *retval, njs_value_t *value, njs_dump_empty(stringify, state, &chain, 1); if (!state->array || isnan(njs_key_to_index(key))) { - njs_key_string_get(vm, key, &pq.lhq.key); + njs_atom_string_get(vm, key->atom_id, &pq.lhq.key); njs_chb_append(&chain, pq.lhq.key.start, pq.lhq.key.length); njs_chb_append_literal(&chain, ":"); if (stringify->space.length != 0) { @@ -2087,7 +2078,8 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_t *retval, njs_value_t *value, if (prop->type == NJS_PROPERTY_HANDLER) { pq.scratch = *prop; prop = &pq.scratch; - ret = njs_prop_handler(prop)(vm, prop, &state->value, NULL, + ret = njs_prop_handler(prop)(vm, prop, pq.lhq.key_hash, + &state->value, NULL, njs_prop_value(prop)); if (njs_slow_path(ret == NJS_ERROR)) { @@ -2100,15 +2092,17 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_t *retval, njs_value_t *value, if (njs_is_accessor_descriptor(prop)) { if (njs_prop_getter(prop) != NULL) { if (njs_prop_setter(prop) != NULL) { - val = njs_value_arg(&string_get_set); + njs_atom_to_value(vm, &s, NJS_ATOM_STRING__Getter_Setter_); } else { - val = njs_value_arg(&string_get); + njs_atom_to_value(vm, &s, NJS_ATOM_STRING__Getter_); } } else { - val = njs_value_arg(&string_set); + njs_atom_to_value(vm, &s, NJS_ATOM_STRING__Setter_); } + + val = &s; } if (njs_dump_is_recursive(val)) { diff --git a/src/njs_lexer.c b/src/njs_lexer.c index 4a51c668..4131301d 100644 --- a/src/njs_lexer.c +++ b/src/njs_lexer.c @@ -18,7 +18,6 @@ struct njs_lexer_multi_s { }; -static njs_int_t njs_lexer_hash_test(njs_lvlhsh_query_t *lhq, void *data); static njs_int_t njs_lexer_word(njs_lexer_t *lexer, njs_lexer_token_t *token); static void njs_lexer_string(njs_lexer_t *lexer, njs_lexer_token_t *token, u_char quote); @@ -28,16 +27,6 @@ static void njs_lexer_multi(njs_lexer_t *lexer, njs_lexer_token_t *token, static void njs_lexer_division(njs_lexer_t *lexer, njs_lexer_token_t *token); -const njs_lvlhsh_proto_t njs_lexer_hash_proto - njs_aligned(64) = -{ - NJS_LVLHSH_DEFAULT, - njs_lexer_hash_test, - njs_lvlhsh_alloc, - njs_lvlhsh_free, -}; - - static const uint8_t njs_tokens[256] njs_aligned(64) = { NJS_TOKEN_ILLEGAL, NJS_TOKEN_ILLEGAL, @@ -290,21 +279,13 @@ static const njs_lexer_multi_t njs_assignment_token[] = { njs_int_t njs_lexer_init(njs_vm_t *vm, njs_lexer_t *lexer, njs_str_t *file, - u_char *start, u_char *end, njs_uint_t runtime, - njs_int_t init_lexer_memory) + u_char *start, u_char *end) { - if (init_lexer_memory) { - njs_memzero(lexer, sizeof(njs_lexer_t)); - - } - lexer->file = *file; lexer->start = start; lexer->end = end; lexer->line = 1; - lexer->keywords_hash = (runtime) ? &vm->keywords_hash - : &vm->shared->keywords_hash; - lexer->mem_pool = vm->mem_pool; + lexer->vm = vm; njs_queue_init(&lexer->preread); @@ -316,7 +297,7 @@ njs_int_t njs_lexer_in_stack_init(njs_lexer_t *lexer) { lexer->in_stack_size = 128; - lexer->in_stack = njs_mp_zalloc(lexer->mem_pool, lexer->in_stack_size); + lexer->in_stack = njs_mp_zalloc(lexer->vm->mem_pool, lexer->in_stack_size); if (lexer->in_stack == NULL) { return NJS_ERROR; } @@ -345,7 +326,7 @@ njs_lexer_in_stack_push(njs_lexer_t *lexer) size = lexer->in_stack_size; lexer->in_stack_size = size * 2; - tmp = njs_mp_alloc(lexer->mem_pool, size * 2); + tmp = njs_mp_alloc(lexer->vm->mem_pool, size * 2); if (tmp == NULL) { return NJS_ERROR; } @@ -353,7 +334,7 @@ njs_lexer_in_stack_push(njs_lexer_t *lexer) memcpy(tmp, lexer->in_stack, size); memset(&tmp[size], 0, size); - njs_mp_free(lexer->mem_pool, lexer->in_stack); + njs_mp_free(lexer->vm->mem_pool, lexer->in_stack); lexer->in_stack = tmp; return NJS_OK; @@ -417,7 +398,7 @@ njs_lexer_next_token(njs_lexer_t *lexer) njs_int_t ret; njs_lexer_token_t *token; - token = njs_mp_zalloc(lexer->mem_pool, sizeof(njs_lexer_token_t)); + token = njs_mp_zalloc(lexer->vm->mem_pool, sizeof(njs_lexer_token_t)); if (njs_slow_path(token == NULL)) { return NULL; } @@ -537,7 +518,7 @@ njs_lexer_consume_token(njs_lexer_t *lexer, unsigned length) njs_queue_remove(lnk); - njs_mp_free(lexer->mem_pool, token); + njs_mp_free(lexer->vm->mem_pool, token); } } @@ -709,76 +690,12 @@ njs_lexer_make_token(njs_lexer_t *lexer, njs_lexer_token_t *token) } -static njs_int_t -njs_lexer_hash_test(njs_lvlhsh_query_t *lhq, void *data) -{ - njs_lexer_entry_t *entry; - - entry = data; - - if (entry->name.length == lhq->key.length - && memcmp(entry->name.start, lhq->key.start, lhq->key.length) == 0) - { - return NJS_OK; - } - - return NJS_DECLINED; -} - - -static njs_lexer_entry_t * -njs_lexer_keyword_find(njs_lexer_t *lexer, u_char *key, size_t length, - uint32_t hash) -{ - njs_int_t ret; - njs_lexer_entry_t *entry; - njs_lvlhsh_query_t lhq; - - lhq.key.start = key; - lhq.key.length = length; - - lhq.key_hash = hash; - lhq.proto = &njs_lexer_hash_proto; - - ret = njs_lvlhsh_find(lexer->keywords_hash, &lhq); - if (ret == NJS_OK) { - return lhq.value; - } - - entry = njs_mp_alloc(lexer->mem_pool, sizeof(njs_lexer_entry_t)); - if (njs_slow_path(entry == NULL)) { - return NULL; - } - - entry->name.start = njs_mp_alloc(lexer->mem_pool, length + 1); - if (njs_slow_path(entry->name.start == NULL)) { - return NULL; - } - - memcpy(entry->name.start, key, length); - - entry->name.start[length] = '\0'; - entry->name.length = length; - - lhq.value = entry; - lhq.pool = lexer->mem_pool; - - ret = njs_lvlhsh_insert(lexer->keywords_hash, &lhq); - if (njs_slow_path(ret != NJS_OK)) { - return NULL; - } - - return entry; -} - - static njs_int_t njs_lexer_word(njs_lexer_t *lexer, njs_lexer_token_t *token) { - u_char *p, c; - uint32_t hash_id; - const njs_lexer_entry_t *entry; - const njs_lexer_keyword_entry_t *key_entry; + u_char *p, c; + uint32_t hash_id; + const njs_value_t *entry; /* TODO: UTF-8 */ @@ -817,27 +734,23 @@ njs_lexer_word(njs_lexer_t *lexer, njs_lexer_token_t *token) token->text.length = p - token->text.start; lexer->start = p; - key_entry = njs_lexer_keyword(token->text.start, token->text.length); - - if (key_entry == NULL) { - entry = njs_lexer_keyword_find(lexer, token->text.start, - token->text.length, hash_id); - if (njs_slow_path(entry == NULL)) { - return NJS_ERROR; - } + entry = njs_atom_find_or_add(lexer->vm, token->text.start, + token->text.length, token->text.length, + hash_id); + if (njs_slow_path(entry == NULL)) { + return NJS_ERROR; + } + if (entry->string.token_type == NJS_KEYWORD_TYPE_UNDEF) { token->type = NJS_TOKEN_NAME; token->keyword_type = NJS_KEYWORD_TYPE_UNDEF; } else { - entry = &key_entry->value->entry; - token->type = key_entry->value->type; - - token->keyword_type = NJS_KEYWORD_TYPE_KEYWORD; - token->keyword_type |= key_entry->value->reserved; + token->type = entry->string.token_id; + token->keyword_type = entry->string.token_type; } - token->unique_id = (uintptr_t) entry; + token->atom_id = entry->atom_id; return NJS_OK; } diff --git a/src/njs_lexer.h b/src/njs_lexer.h index 6b1d04b6..42f612a6 100644 --- a/src/njs_lexer.h +++ b/src/njs_lexer.h @@ -219,12 +219,6 @@ typedef enum { typedef struct { - njs_str_t name; -} njs_lexer_entry_t; - - -typedef struct { - njs_lexer_entry_t entry; njs_token_type_t type; njs_bool_t reserved; } njs_keyword_t; @@ -243,7 +237,7 @@ typedef struct { njs_token_type_t type:16; njs_keyword_type_t keyword_type; uint32_t line; - uintptr_t unique_id; + uint32_t atom_id; njs_str_t text; double number; njs_queue_link_t link; @@ -261,9 +255,7 @@ typedef struct { uint32_t line; njs_str_t file; - njs_lvlhsh_t *keywords_hash; - - njs_mp_t *mem_pool; + njs_vm_t *vm; u_char *start; u_char *end; @@ -276,8 +268,7 @@ typedef struct { njs_int_t njs_lexer_init(njs_vm_t *vm, njs_lexer_t *lexer, njs_str_t *file, - u_char *start, u_char *end, njs_uint_t runtime, - njs_int_t init_lexer_memory); + u_char *start, u_char *end); njs_lexer_token_t *njs_lexer_token(njs_lexer_t *lexer, njs_bool_t with_end_line); @@ -297,10 +288,13 @@ const njs_lexer_keyword_entry_t *njs_lexer_keyword(const u_char *key, njs_int_t njs_lexer_keywords(njs_arr_t *array); -njs_inline const njs_lexer_entry_t * -njs_lexer_entry(uintptr_t unique_id) +njs_inline void +njs_lexer_entry(njs_vm_t *vm, uintptr_t atom_id, njs_str_t *entry) { - return (const njs_lexer_entry_t *) unique_id; + njs_value_t value; + + njs_atom_to_value(vm, &value, atom_id); + njs_string_get(vm, &value, entry); } @@ -363,8 +357,4 @@ njs_lexer_token_is_identifier_reference(njs_lexer_token_t *token) return njs_lexer_token_is_binding_identifier(token); } - -extern const njs_lvlhsh_proto_t njs_lexer_hash_proto; - - #endif /* _NJS_LEXER_H_INCLUDED_ */ diff --git a/src/njs_lexer_tables.h b/src/njs_lexer_tables.h deleted file mode 100644 index e6503252..00000000 --- a/src/njs_lexer_tables.h +++ /dev/null @@ -1,445 +0,0 @@ - -/* - * Copyright (C) Nginx, Inc. - * - * Do not edit, generated by: utils/lexer_keyword.py. - */ - - -#ifndef _NJS_LEXER_TABLES_H_INCLUDED_ -#define _NJS_LEXER_TABLES_H_INCLUDED_ - - -static const njs_keyword_t njs_lexer_kws[54] = -{ - { - .entry = { njs_str("arguments") }, - .type = NJS_TOKEN_ARGUMENTS, - .reserved = 0 - }, - - { - .entry = { njs_str("async") }, - .type = NJS_TOKEN_ASYNC, - .reserved = 0 - }, - - { - .entry = { njs_str("await") }, - .type = NJS_TOKEN_AWAIT, - .reserved = 1 - }, - - { - .entry = { njs_str("break") }, - .type = NJS_TOKEN_BREAK, - .reserved = 1 - }, - - { - .entry = { njs_str("case") }, - .type = NJS_TOKEN_CASE, - .reserved = 1 - }, - - { - .entry = { njs_str("catch") }, - .type = NJS_TOKEN_CATCH, - .reserved = 1 - }, - - { - .entry = { njs_str("class") }, - .type = NJS_TOKEN_CLASS, - .reserved = 1 - }, - - { - .entry = { njs_str("const") }, - .type = NJS_TOKEN_CONST, - .reserved = 1 - }, - - { - .entry = { njs_str("continue") }, - .type = NJS_TOKEN_CONTINUE, - .reserved = 1 - }, - - { - .entry = { njs_str("debugger") }, - .type = NJS_TOKEN_DEBUGGER, - .reserved = 1 - }, - - { - .entry = { njs_str("default") }, - .type = NJS_TOKEN_DEFAULT, - .reserved = 1 - }, - - { - .entry = { njs_str("delete") }, - .type = NJS_TOKEN_DELETE, - .reserved = 1 - }, - - { - .entry = { njs_str("do") }, - .type = NJS_TOKEN_DO, - .reserved = 1 - }, - - { - .entry = { njs_str("else") }, - .type = NJS_TOKEN_ELSE, - .reserved = 1 - }, - - { - .entry = { njs_str("enum") }, - .type = NJS_TOKEN_ENUM, - .reserved = 1 - }, - - { - .entry = { njs_str("eval") }, - .type = NJS_TOKEN_EVAL, - .reserved = 0 - }, - - { - .entry = { njs_str("export") }, - .type = NJS_TOKEN_EXPORT, - .reserved = 1 - }, - - { - .entry = { njs_str("extends") }, - .type = NJS_TOKEN_EXTENDS, - .reserved = 1 - }, - - { - .entry = { njs_str("false") }, - .type = NJS_TOKEN_FALSE, - .reserved = 1 - }, - - { - .entry = { njs_str("finally") }, - .type = NJS_TOKEN_FINALLY, - .reserved = 1 - }, - - { - .entry = { njs_str("for") }, - .type = NJS_TOKEN_FOR, - .reserved = 1 - }, - - { - .entry = { njs_str("from") }, - .type = NJS_TOKEN_FROM, - .reserved = 0 - }, - - { - .entry = { njs_str("function") }, - .type = NJS_TOKEN_FUNCTION, - .reserved = 1 - }, - - { - .entry = { njs_str("if") }, - .type = NJS_TOKEN_IF, - .reserved = 1 - }, - - { - .entry = { njs_str("implements") }, - .type = NJS_TOKEN_IMPLEMENTS, - .reserved = 1 - }, - - { - .entry = { njs_str("import") }, - .type = NJS_TOKEN_IMPORT, - .reserved = 1 - }, - - { - .entry = { njs_str("in") }, - .type = NJS_TOKEN_IN, - .reserved = 1 - }, - - { - .entry = { njs_str("instanceof") }, - .type = NJS_TOKEN_INSTANCEOF, - .reserved = 1 - }, - - { - .entry = { njs_str("interface") }, - .type = NJS_TOKEN_INTERFACE, - .reserved = 1 - }, - - { - .entry = { njs_str("let") }, - .type = NJS_TOKEN_LET, - .reserved = 1 - }, - - { - .entry = { njs_str("meta") }, - .type = NJS_TOKEN_META, - .reserved = 0 - }, - - { - .entry = { njs_str("new") }, - .type = NJS_TOKEN_NEW, - .reserved = 1 - }, - - { - .entry = { njs_str("null") }, - .type = NJS_TOKEN_NULL, - .reserved = 1 - }, - - { - .entry = { njs_str("of") }, - .type = NJS_TOKEN_OF, - .reserved = 0 - }, - - { - .entry = { njs_str("package") }, - .type = NJS_TOKEN_PACKAGE, - .reserved = 1 - }, - - { - .entry = { njs_str("private") }, - .type = NJS_TOKEN_PRIVATE, - .reserved = 1 - }, - - { - .entry = { njs_str("protected") }, - .type = NJS_TOKEN_PROTECTED, - .reserved = 1 - }, - - { - .entry = { njs_str("public") }, - .type = NJS_TOKEN_PUBLIC, - .reserved = 1 - }, - - { - .entry = { njs_str("return") }, - .type = NJS_TOKEN_RETURN, - .reserved = 1 - }, - - { - .entry = { njs_str("static") }, - .type = NJS_TOKEN_STATIC, - .reserved = 1 - }, - - { - .entry = { njs_str("super") }, - .type = NJS_TOKEN_SUPER, - .reserved = 1 - }, - - { - .entry = { njs_str("switch") }, - .type = NJS_TOKEN_SWITCH, - .reserved = 1 - }, - - { - .entry = { njs_str("target") }, - .type = NJS_TOKEN_TARGET, - .reserved = 0 - }, - - { - .entry = { njs_str("this") }, - .type = NJS_TOKEN_THIS, - .reserved = 1 - }, - - { - .entry = { njs_str("throw") }, - .type = NJS_TOKEN_THROW, - .reserved = 1 - }, - - { - .entry = { njs_str("true") }, - .type = NJS_TOKEN_TRUE, - .reserved = 1 - }, - - { - .entry = { njs_str("try") }, - .type = NJS_TOKEN_TRY, - .reserved = 1 - }, - - { - .entry = { njs_str("typeof") }, - .type = NJS_TOKEN_TYPEOF, - .reserved = 1 - }, - - { - .entry = { njs_str("undefined") }, - .type = NJS_TOKEN_UNDEFINED, - .reserved = 0 - }, - - { - .entry = { njs_str("var") }, - .type = NJS_TOKEN_VAR, - .reserved = 1 - }, - - { - .entry = { njs_str("void") }, - .type = NJS_TOKEN_VOID, - .reserved = 1 - }, - - { - .entry = { njs_str("while") }, - .type = NJS_TOKEN_WHILE, - .reserved = 1 - }, - - { - .entry = { njs_str("with") }, - .type = NJS_TOKEN_WITH, - .reserved = 1 - }, - - { - .entry = { njs_str("yield") }, - .type = NJS_TOKEN_YIELD, - .reserved = 1 - }, -}; - - -static const njs_lexer_keyword_entry_t njs_lexer_keyword_entries[99] = -{ - { NULL, NULL, 98, 0 }, - { "continue", &njs_lexer_kws[8], 8, 0 }, - { "finally", &njs_lexer_kws[19], 7, 0 }, - { "return", &njs_lexer_kws[38], 6, 0 }, - { "static", &njs_lexer_kws[39], 6, 0 }, - { "async", &njs_lexer_kws[1], 5, 0 }, - { "break", &njs_lexer_kws[3], 5, 0 }, - { "interface", &njs_lexer_kws[28], 9, 0 }, - { "case", &njs_lexer_kws[4], 4, 0 }, - { "import", &njs_lexer_kws[25], 6, 0 }, - { "protected", &njs_lexer_kws[36], 9, 0 }, - { "switch", &njs_lexer_kws[41], 6, 0 }, - { "catch", &njs_lexer_kws[5], 5, 1 }, - { "delete", &njs_lexer_kws[11], 6, 0 }, - { "else", &njs_lexer_kws[13], 4, 0 }, - { "private", &njs_lexer_kws[35], 7, 0 }, - { "extends", &njs_lexer_kws[17], 7, 0 }, - { "this", &njs_lexer_kws[43], 4, 0 }, - { "false", &njs_lexer_kws[18], 5, 0 }, - { "await", &njs_lexer_kws[2], 5, 0 }, - { NULL, NULL, 0, 0 }, - { "public", &njs_lexer_kws[37], 6, 0 }, - { NULL, NULL, 0, 0 }, - { "class", &njs_lexer_kws[6], 5, 0 }, - { "const", &njs_lexer_kws[7], 5, 4 }, - { NULL, NULL, 0, 0 }, - { "try", &njs_lexer_kws[46], 3, 0 }, - { "null", &njs_lexer_kws[32], 4, 0 }, - { NULL, NULL, 0, 0 }, - { "do", &njs_lexer_kws[12], 2, 0 }, - { "var", &njs_lexer_kws[49], 3, 0 }, - { "if", &njs_lexer_kws[23], 2, 7 }, - { "implements", &njs_lexer_kws[24], 10, 0 }, - { "with", &njs_lexer_kws[52], 4, 0 }, - { NULL, NULL, 0, 0 }, - { "eval", &njs_lexer_kws[15], 4, 9 }, - { NULL, NULL, 0, 0 }, - { "target", &njs_lexer_kws[42], 6, 0 }, - { "enum", &njs_lexer_kws[14], 4, 10 }, - { "instanceof", &njs_lexer_kws[27], 10, 0 }, - { NULL, NULL, 0, 0 }, - { "debugger", &njs_lexer_kws[9], 8, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { "default", &njs_lexer_kws[10], 7, 0 }, - { "void", &njs_lexer_kws[50], 4, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { "undefined", &njs_lexer_kws[48], 9, 0 }, - { "from", &njs_lexer_kws[21], 4, 0 }, - { "package", &njs_lexer_kws[34], 7, 15 }, - { NULL, NULL, 0, 0 }, - { "yield", &njs_lexer_kws[53], 5, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { "of", &njs_lexer_kws[33], 2, 0 }, - { NULL, NULL, 0, 0 }, - { "function", &njs_lexer_kws[22], 8, 0 }, - { NULL, NULL, 0, 0 }, - { "true", &njs_lexer_kws[45], 4, 16 }, - { "new", &njs_lexer_kws[31], 3, 0 }, - { "export", &njs_lexer_kws[16], 6, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { "for", &njs_lexer_kws[20], 3, 0 }, - { "while", &njs_lexer_kws[51], 5, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { "typeof", &njs_lexer_kws[47], 6, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { "super", &njs_lexer_kws[40], 5, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { "let", &njs_lexer_kws[29], 3, 19 }, - { "in", &njs_lexer_kws[26], 2, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { "throw", &njs_lexer_kws[44], 5, 0 }, - { "arguments", &njs_lexer_kws[0], 9, 0 }, - { "meta", &njs_lexer_kws[30], 4, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, - { NULL, NULL, 0, 0 }, -}; - - -#endif /* _NJS_LEXER_TABLES_H_INCLUDED_ */ diff --git a/src/njs_main.h b/src/njs_main.h index 563065a1..e40fe085 100644 --- a/src/njs_main.h +++ b/src/njs_main.h @@ -45,6 +45,8 @@ #include #include #include +#include +#include #include #include #include @@ -56,9 +58,7 @@ #include #include -#include #include -#include #include #include #include diff --git a/src/njs_math.c b/src/njs_math.c index 6bc76fd1..b2892e7e 100644 --- a/src/njs_math.c +++ b/src/njs_math.c @@ -374,101 +374,132 @@ njs_object_math_random(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_object_prop_t njs_math_object_properties[] = +static const njs_object_prop_init_t njs_math_object_properties[] = { - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.value = njs_string("Math"), - .configurable = 1, - }, + NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, njs_ascii_strval("Math"), + NJS_OBJECT_PROP_VALUE_C), - NJS_DECLARE_PROP_VALUE("E", njs_value(NJS_NUMBER, 1, M_E), 0), + NJS_DECLARE_PROP_VALUE(STRING_E, njs_value(NJS_NUMBER, 1, M_E), 0), - NJS_DECLARE_PROP_VALUE("LN10", njs_value(NJS_NUMBER, 1, M_LN10), 0), + NJS_DECLARE_PROP_VALUE(STRING_LN10, njs_value(NJS_NUMBER, 1, M_LN10), + 0), - NJS_DECLARE_PROP_VALUE("LN2", njs_value(NJS_NUMBER, 1, M_LN2), 0), + NJS_DECLARE_PROP_VALUE(STRING_LN2, njs_value(NJS_NUMBER, 1, M_LN2), 0), - NJS_DECLARE_PROP_VALUE("LOG10E", njs_value(NJS_NUMBER, 1, M_LOG10E), 0), + NJS_DECLARE_PROP_VALUE(STRING_LOG10E, + njs_value(NJS_NUMBER, 1, M_LOG10E), 0), - NJS_DECLARE_PROP_VALUE("LOG2E", njs_value(NJS_NUMBER, 1, M_LOG2E), 0), + NJS_DECLARE_PROP_VALUE(STRING_LOG2E, njs_value(NJS_NUMBER, 1, M_LOG2E), + 0), - NJS_DECLARE_PROP_VALUE("PI", njs_value(NJS_NUMBER, 1, M_PI), 0), + NJS_DECLARE_PROP_VALUE(STRING_PI, njs_value(NJS_NUMBER, 1, M_PI), 0), - NJS_DECLARE_PROP_VALUE("SQRT1_2", njs_value(NJS_NUMBER, 1, M_SQRT1_2), 0), + NJS_DECLARE_PROP_VALUE(STRING_SQRT1_2, + njs_value(NJS_NUMBER, 1, M_SQRT1_2), 0), - NJS_DECLARE_PROP_VALUE("SQRT2", njs_value(NJS_NUMBER, 1, M_SQRT2), 0), + NJS_DECLARE_PROP_VALUE(STRING_SQRT2, njs_value(NJS_NUMBER, 1, M_SQRT2), + 0), - NJS_DECLARE_PROP_NATIVE("abs", njs_object_math_func, 1, NJS_MATH_ABS), + NJS_DECLARE_PROP_NATIVE(STRING_abs, njs_object_math_func, 1, + NJS_MATH_ABS), - NJS_DECLARE_PROP_NATIVE("acos", njs_object_math_func, 1, NJS_MATH_ACOS), + NJS_DECLARE_PROP_NATIVE(STRING_acos, njs_object_math_func, 1, + NJS_MATH_ACOS), - NJS_DECLARE_PROP_NATIVE("acosh", njs_object_math_func, 1, NJS_MATH_ACOSH), + NJS_DECLARE_PROP_NATIVE(STRING_acosh, njs_object_math_func, 1, + NJS_MATH_ACOSH), - NJS_DECLARE_PROP_NATIVE("asin", njs_object_math_func, 1, NJS_MATH_ASIN), + NJS_DECLARE_PROP_NATIVE(STRING_asin, njs_object_math_func, 1, + NJS_MATH_ASIN), - NJS_DECLARE_PROP_NATIVE("asinh", njs_object_math_func, 1, NJS_MATH_ASINH), + NJS_DECLARE_PROP_NATIVE(STRING_asinh, njs_object_math_func, 1, + NJS_MATH_ASINH), - NJS_DECLARE_PROP_NATIVE("atan", njs_object_math_func, 1, NJS_MATH_ATAN), + NJS_DECLARE_PROP_NATIVE(STRING_atan, njs_object_math_func, 1, + NJS_MATH_ATAN), - NJS_DECLARE_PROP_NATIVE("atan2", njs_object_math_func, 2, NJS_MATH_ATAN2), + NJS_DECLARE_PROP_NATIVE(STRING_atan2, njs_object_math_func, 2, + NJS_MATH_ATAN2), - NJS_DECLARE_PROP_NATIVE("atanh", njs_object_math_func, 1, NJS_MATH_ATANH), + NJS_DECLARE_PROP_NATIVE(STRING_atanh, njs_object_math_func, 1, + NJS_MATH_ATANH), - NJS_DECLARE_PROP_NATIVE("cbrt", njs_object_math_func, 1, NJS_MATH_CBRT), + NJS_DECLARE_PROP_NATIVE(STRING_cbrt, njs_object_math_func, 1, + NJS_MATH_CBRT), - NJS_DECLARE_PROP_NATIVE("ceil", njs_object_math_func, 1, NJS_MATH_CEIL), + NJS_DECLARE_PROP_NATIVE(STRING_ceil, njs_object_math_func, 1, + NJS_MATH_CEIL), - NJS_DECLARE_PROP_NATIVE("clz32", njs_object_math_func, 1, NJS_MATH_CLZ32), + NJS_DECLARE_PROP_NATIVE(STRING_clz32, njs_object_math_func, 1, + NJS_MATH_CLZ32), - NJS_DECLARE_PROP_NATIVE("cos", njs_object_math_func, 1, NJS_MATH_COS), + NJS_DECLARE_PROP_NATIVE(STRING_cos, njs_object_math_func, 1, + NJS_MATH_COS), - NJS_DECLARE_PROP_NATIVE("cosh", njs_object_math_func, 1, NJS_MATH_COSH), + NJS_DECLARE_PROP_NATIVE(STRING_cosh, njs_object_math_func, 1, + NJS_MATH_COSH), - NJS_DECLARE_PROP_NATIVE("exp", njs_object_math_func, 1, NJS_MATH_EXP), + NJS_DECLARE_PROP_NATIVE(STRING_exp, njs_object_math_func, 1, + NJS_MATH_EXP), - NJS_DECLARE_PROP_NATIVE("expm1", njs_object_math_func, 1, NJS_MATH_EXPM1), + NJS_DECLARE_PROP_NATIVE(STRING_expm1, njs_object_math_func, 1, + NJS_MATH_EXPM1), - NJS_DECLARE_PROP_NATIVE("floor", njs_object_math_func, 1, NJS_MATH_FLOOR), + NJS_DECLARE_PROP_NATIVE(STRING_floor, njs_object_math_func, 1, + NJS_MATH_FLOOR), - NJS_DECLARE_PROP_NATIVE("fround", njs_object_math_func, 1, + NJS_DECLARE_PROP_NATIVE(STRING_fround, njs_object_math_func, 1, NJS_MATH_FROUND), - NJS_DECLARE_PROP_NATIVE("hypot", njs_object_math_hypot, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_hypot, njs_object_math_hypot, 2, 0), - NJS_DECLARE_PROP_NATIVE("imul", njs_object_math_func, 2, NJS_MATH_IMUL), + NJS_DECLARE_PROP_NATIVE(STRING_imul, njs_object_math_func, 2, + NJS_MATH_IMUL), - NJS_DECLARE_PROP_NATIVE("log", njs_object_math_func, 1, NJS_MATH_LOG), + NJS_DECLARE_PROP_NATIVE(STRING_log, njs_object_math_func, 1, + NJS_MATH_LOG), - NJS_DECLARE_PROP_NATIVE("log10", njs_object_math_func, 1, NJS_MATH_LOG10), + NJS_DECLARE_PROP_NATIVE(STRING_log10, njs_object_math_func, 1, + NJS_MATH_LOG10), - NJS_DECLARE_PROP_NATIVE("log1p", njs_object_math_func, 1, NJS_MATH_LOG1P), + NJS_DECLARE_PROP_NATIVE(STRING_log1p, njs_object_math_func, 1, + NJS_MATH_LOG1P), - NJS_DECLARE_PROP_NATIVE("log2", njs_object_math_func, 1, NJS_MATH_LOG2), + NJS_DECLARE_PROP_NATIVE(STRING_log2, njs_object_math_func, 1, + NJS_MATH_LOG2), - NJS_DECLARE_PROP_NATIVE("max", njs_object_math_min_max, 2, 1), + NJS_DECLARE_PROP_NATIVE(STRING_max, njs_object_math_min_max, 2, 1), - NJS_DECLARE_PROP_NATIVE("min", njs_object_math_min_max, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_min, njs_object_math_min_max, 2, 0), - NJS_DECLARE_PROP_NATIVE("pow", njs_object_math_func, 2, NJS_MATH_POW), + NJS_DECLARE_PROP_NATIVE(STRING_pow, njs_object_math_func, 2, + NJS_MATH_POW), - NJS_DECLARE_PROP_NATIVE("random", njs_object_math_random, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_random, njs_object_math_random, 0, 0), - NJS_DECLARE_PROP_NATIVE("round", njs_object_math_func, 1, NJS_MATH_ROUND), + NJS_DECLARE_PROP_NATIVE(STRING_round, njs_object_math_func, 1, + NJS_MATH_ROUND), - NJS_DECLARE_PROP_NATIVE("sign", njs_object_math_func, 1, NJS_MATH_SIGN), + NJS_DECLARE_PROP_NATIVE(STRING_sign, njs_object_math_func, 1, + NJS_MATH_SIGN), - NJS_DECLARE_PROP_NATIVE("sin", njs_object_math_func, 1, NJS_MATH_SIN), + NJS_DECLARE_PROP_NATIVE(STRING_sin, njs_object_math_func, 1, + NJS_MATH_SIN), - NJS_DECLARE_PROP_NATIVE("sinh", njs_object_math_func, 1, NJS_MATH_SINH), + NJS_DECLARE_PROP_NATIVE(STRING_sinh, njs_object_math_func, 1, + NJS_MATH_SINH), - NJS_DECLARE_PROP_NATIVE("sqrt", njs_object_math_func, 1, NJS_MATH_SQRT), + NJS_DECLARE_PROP_NATIVE(STRING_sqrt, njs_object_math_func, 1, + NJS_MATH_SQRT), - NJS_DECLARE_PROP_NATIVE("tan", njs_object_math_func, 1, NJS_MATH_TAN), + NJS_DECLARE_PROP_NATIVE(STRING_tan, njs_object_math_func, 1, + NJS_MATH_TAN), - NJS_DECLARE_PROP_NATIVE("tanh", njs_object_math_func, 1, NJS_MATH_TANH), + NJS_DECLARE_PROP_NATIVE(STRING_tanh, njs_object_math_func, 1, + NJS_MATH_TANH), - NJS_DECLARE_PROP_NATIVE("trunc", njs_object_math_func, 1, NJS_MATH_TRUNC), + NJS_DECLARE_PROP_NATIVE(STRING_trunc, njs_object_math_func, 1, + NJS_MATH_TRUNC), }; diff --git a/src/njs_module.c b/src/njs_module.c index 5d9c96ae..5af174f3 100644 --- a/src/njs_module.c +++ b/src/njs_module.c @@ -144,7 +144,7 @@ njs_module_require(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - njs_string_get(path, &name); + njs_string_get(vm, path, &name); module = njs_module_find(vm, &name, 0); if (njs_slow_path(module == NULL)) { diff --git a/src/njs_number.c b/src/njs_number.c index 4ca6456d..29df50a5 100644 --- a/src/njs_number.c +++ b/src/njs_number.c @@ -217,23 +217,22 @@ njs_int_t njs_number_to_string(njs_vm_t *vm, njs_value_t *string, const njs_value_t *number) { - double num; - size_t size; - const njs_value_t *value; - u_char buf[128]; + double num; + size_t size; + u_char buf[128]; num = njs_number(number); if (isnan(num)) { - value = &njs_string_nan; + njs_atom_to_value(vm, string, NJS_ATOM_STRING_NaN); } else if (isinf(num)) { if (num < 0) { - value = &njs_string_minus_infinity; + njs_atom_to_value(vm, string, NJS_ATOM_STRING__Infinity); } else { - value = &njs_string_plus_infinity; + njs_atom_to_value(vm, string, NJS_ATOM_STRING_Infinity); } } else { @@ -242,8 +241,6 @@ njs_number_to_string(njs_vm_t *vm, njs_value_t *string, return njs_string_new(vm, string, buf, size, size); } - *string = *value; - return NJS_OK; } @@ -252,20 +249,8 @@ njs_int_t njs_int64_to_string(njs_vm_t *vm, njs_value_t *value, int64_t i64) { size_t size; - u_char *dst, *p; u_char buf[128]; - if (njs_fast_path(i64 >= 0 && i64 < 0x3fffffffffffLL)) { - /* Fits to short_string. */ - dst = njs_string_short_start(value); - - p = njs_sprintf(dst, dst + NJS_STRING_SHORT, "%L", i64); - - njs_string_short_set(value, p - dst, p - dst); - - return NJS_OK; - } - size = njs_dtoa(i64, (char *) buf); return njs_string_new(vm, value, buf, size, size); @@ -439,49 +424,55 @@ njs_number_is_finite(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_object_prop_t njs_number_constructor_properties[] = +static const njs_object_prop_init_t njs_number_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("Number"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_VALUE("EPSILON", njs_value(NJS_NUMBER, 1, DBL_EPSILON), 0), + NJS_DECLARE_PROP_VALUE(STRING_EPSILON, + njs_value(NJS_NUMBER, 1, DBL_EPSILON), 0), - NJS_DECLARE_PROP_LVALUE("MAX_SAFE_INTEGER", - njs_value(NJS_NUMBER, 1, NJS_MAX_SAFE_INTEGER), 0), + NJS_DECLARE_PROP_VALUE(STRING_MAX_SAFE_INTEGER, + njs_value(NJS_NUMBER, 1, NJS_MAX_SAFE_INTEGER), 0), - NJS_DECLARE_PROP_LVALUE("MIN_SAFE_INTEGER", - njs_value(NJS_NUMBER, 1, -NJS_MAX_SAFE_INTEGER), 0), + NJS_DECLARE_PROP_VALUE(STRING_MIN_SAFE_INTEGER, + njs_value(NJS_NUMBER, 1, -NJS_MAX_SAFE_INTEGER), 0), - NJS_DECLARE_PROP_VALUE("MAX_VALUE", njs_value(NJS_NUMBER, 1, DBL_MAX), 0), + NJS_DECLARE_PROP_VALUE(STRING_MAX_VALUE, + njs_value(NJS_NUMBER, 1, DBL_MAX), 0), - NJS_DECLARE_PROP_VALUE("MIN_VALUE", njs_value(NJS_NUMBER, 1, DBL_MIN), 0), + NJS_DECLARE_PROP_VALUE(STRING_MIN_VALUE, + njs_value(NJS_NUMBER, 1, DBL_MIN), 0), - NJS_DECLARE_PROP_VALUE("NaN", njs_value(NJS_NUMBER, 0, NAN), 0), + NJS_DECLARE_PROP_VALUE(STRING_NaN, njs_value(NJS_NUMBER, 0, NAN), 0), - NJS_DECLARE_PROP_LVALUE("POSITIVE_INFINITY", - njs_value(NJS_NUMBER, 1, INFINITY), 0), + NJS_DECLARE_PROP_VALUE(STRING_POSITIVE_INFINITY, + njs_value(NJS_NUMBER, 1, INFINITY), 0), - NJS_DECLARE_PROP_LVALUE("NEGATIVE_INFINITY", - njs_value(NJS_NUMBER, 1, -INFINITY), 0), + NJS_DECLARE_PROP_VALUE(STRING_NEGATIVE_INFINITY, + njs_value(NJS_NUMBER, 1, -INFINITY), 0), - NJS_DECLARE_PROP_NATIVE("isFinite", njs_number_is_finite, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_isFinite, njs_number_is_finite, 1, 0), - NJS_DECLARE_PROP_NATIVE("isInteger", njs_number_is_integer, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_isInteger, njs_number_is_integer, 1, 0), - NJS_DECLARE_PROP_NATIVE("isSafeInteger", njs_number_is_safe_integer, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_isSafeInteger, + njs_number_is_safe_integer, 1, 0), - NJS_DECLARE_PROP_NATIVE("isNaN", njs_number_is_nan, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_isNaN, njs_number_is_nan, 1, 0), - NJS_DECLARE_PROP_NATIVE("parseFloat", njs_number_parse_float, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_parseFloat, njs_number_parse_float, 1, + 0), - NJS_DECLARE_PROP_NATIVE("parseInt", njs_number_parse_int, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_parseInt, njs_number_parse_int, 2, 0), }; -const njs_object_init_t njs_number_constructor_init = { +static const njs_object_init_t njs_number_constructor_init = { njs_number_constructor_properties, njs_nitems(njs_number_constructor_properties), }; @@ -884,25 +875,29 @@ njs_number_to_string_radix(njs_vm_t *vm, njs_value_t *string, } -static const njs_object_prop_t njs_number_prototype_properties[] = +static const njs_object_prop_init_t njs_number_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("__proto__", njs_primitive_prototype_get_proto, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING___proto__, + njs_primitive_prototype_get_proto, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_NATIVE("valueOf", njs_number_prototype_value_of, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_valueOf, njs_number_prototype_value_of, + 0, 0), - NJS_DECLARE_PROP_NATIVE("toString", njs_number_prototype_to_string, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toString, + njs_number_prototype_to_string, 1, 0), - NJS_DECLARE_PROP_NATIVE("toFixed", njs_number_prototype_to_fixed, 1, 0), - - NJS_DECLARE_PROP_NATIVE("toPrecision", njs_number_prototype_to_precision, + NJS_DECLARE_PROP_NATIVE(STRING_toFixed, njs_number_prototype_to_fixed, 1, 0), - NJS_DECLARE_PROP_NATIVE("toExponential", + NJS_DECLARE_PROP_NATIVE(STRING_toPrecision, + njs_number_prototype_to_precision, 1, 0), + + NJS_DECLARE_PROP_NATIVE(STRING_toExponential, njs_number_prototype_to_exponential, 1, 0), }; @@ -970,7 +965,7 @@ njs_number_parse_int(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - (void) njs_string_trim(value, &string, NJS_TRIM_START); + (void) njs_string_trim(vm, value, &string, NJS_TRIM_START); if (string.size == 0) { goto done; @@ -1048,7 +1043,7 @@ njs_number_parse_float(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - (void) njs_string_trim(value, &string, NJS_TRIM_START); + (void) njs_string_trim(vm, value, &string, NJS_TRIM_START); p = string.start; end = p + string.size; diff --git a/src/njs_number.h b/src/njs_number.h index 98137a5d..d4c7a286 100644 --- a/src/njs_number.h +++ b/src/njs_number.h @@ -168,15 +168,30 @@ njs_char_to_hex(u_char c) } -njs_inline void -njs_uint32_to_string(njs_value_t *value, uint32_t u32) +njs_inline njs_int_t +njs_uint32_to_string(njs_vm_t *vm, njs_value_t *value, uint32_t u32) { - u_char *dst, *p; + size_t size; + u_char *p; + + if (!(u32 & 0x80000000)) { + value->type = NJS_STRING; + value->data.truth = (u32 != 0); + value->atom_id = njs_number_atom(u32); + value->string.data = NULL; + return NJS_OK; + } + + p = njs_string_alloc(vm, value, 10, 10); + if (njs_slow_path(p == NULL)) { + return NJS_ERROR; + } - dst = njs_string_short_start(value); - p = njs_sprintf(dst, dst + NJS_STRING_SHORT, "%uD", u32); + size = njs_sprintf(p, p + 10, "%uD", u32) - p; + value->string.data->length = size; + value->string.data->size = size; - njs_string_short_set(value, p - dst, p - dst); + return NJS_OK; } diff --git a/src/njs_object.c b/src/njs_object.c index b3eae9a8..63273628 100644 --- a/src/njs_object.c +++ b/src/njs_object.c @@ -14,9 +14,8 @@ typedef enum { } njs_object_integrity_level_t; -static njs_int_t njs_object_hash_test(njs_lvlhsh_query_t *lhq, void *data); static njs_object_prop_t *njs_object_exist_in_proto(const njs_object_t *begin, - const njs_object_t *end, njs_lvlhsh_query_t *lhq); + const njs_object_t *end, njs_flathsh_query_t *lhq); static njs_int_t njs_object_enumerate_array(njs_vm_t *vm, const njs_array_t *array, njs_array_t *items, uint32_t flags); static njs_int_t njs_object_enumerate_typed_array(njs_vm_t *vm, @@ -154,23 +153,21 @@ njs_object_value_alloc(njs_vm_t *vm, njs_uint_t prototype_index, size_t extra, njs_int_t -njs_object_hash_create(njs_vm_t *vm, njs_lvlhsh_t *hash, - const njs_object_prop_t *prop, njs_uint_t n) +njs_object_hash_create(njs_vm_t *vm, njs_flathsh_t *hash, + const njs_object_prop_init_t *prop, njs_uint_t n) { - njs_int_t ret; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_flathsh_query_t lhq; lhq.replace = 0; lhq.proto = &njs_object_hash_proto; lhq.pool = vm->mem_pool; while (n != 0) { - - njs_object_property_key_set(&lhq, &prop->name, 0); - + lhq.key_hash = prop->atom_id; lhq.value = (void *) prop; - ret = njs_lvlhsh_insert(hash, &lhq); + ret = njs_flathsh_unique_insert(hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; @@ -184,59 +181,16 @@ njs_object_hash_create(njs_vm_t *vm, njs_lvlhsh_t *hash, } -const njs_lvlhsh_proto_t njs_object_hash_proto +const njs_flathsh_proto_t njs_object_hash_proto njs_aligned(64) = { - NJS_LVLHSH_DEFAULT, - njs_object_hash_test, + 0, + NULL, njs_lvlhsh_alloc, njs_lvlhsh_free, }; -static njs_int_t -njs_object_hash_test(njs_lvlhsh_query_t *lhq, void *data) -{ - size_t size; - u_char *start; - njs_value_t *name; - njs_object_prop_t *prop; - - prop = data; - name = &prop->name; - - if (njs_slow_path(njs_is_symbol(name))) { - return ((njs_symbol_key(name) == lhq->key_hash) - && lhq->key.start == NULL) ? NJS_OK : NJS_DECLINED; - } - - /* string. */ - - size = name->short_string.size; - - if (size != NJS_STRING_LONG) { - if (lhq->key.length != size) { - return NJS_DECLINED; - } - - start = name->short_string.start; - - } else { - if (lhq->key.length != name->long_string.size) { - return NJS_DECLINED; - } - - start = name->long_string.data->start; - } - - if (memcmp(start, lhq->key.start, lhq->key.length) == 0) { - return NJS_OK; - } - - return NJS_DECLINED; -} - - static njs_int_t njs_object_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) @@ -417,13 +371,13 @@ njs_object_entries(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_object_prop_t * njs_object_exist_in_proto(const njs_object_t *object, const njs_object_t *end, - njs_lvlhsh_query_t *lhq) + njs_flathsh_query_t *lhq) { njs_int_t ret; njs_object_prop_t *prop; while (object != end) { - ret = njs_lvlhsh_find(&object->hash, lhq); + ret = njs_flathsh_unique_find(&object->hash, lhq); if (njs_fast_path(ret == NJS_OK)) { prop = lhq->value; @@ -435,7 +389,7 @@ njs_object_exist_in_proto(const njs_object_t *object, const njs_object_t *end, return lhq->value; } - ret = njs_lvlhsh_find(&object->shared_hash, lhq); + ret = njs_flathsh_unique_find(&object->shared_hash, lhq); if (njs_fast_path(ret == NJS_OK)) { return lhq->value; @@ -628,7 +582,11 @@ njs_object_enumerate_array(njs_vm_t *vm, const njs_array_t *array, return NJS_ERROR; } - njs_uint32_to_string(&items->start[items->length++], p - start); + ret = njs_uint32_to_string(vm, &items->start[items->length++], + p - start); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } p++; @@ -658,7 +616,11 @@ njs_object_enumerate_array(njs_vm_t *vm, const njs_array_t *array, return NJS_ERROR; } - njs_uint32_to_string(&entry->start[0], p - start); + ret = njs_uint32_to_string(vm, &entry->start[0], p - start); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + entry->start[1] = *p; ret = njs_array_expand(vm, items, 0, 1); @@ -700,7 +662,10 @@ njs_object_enumerate_typed_array(njs_vm_t *vm, const njs_typed_array_t *array, switch (njs_object_enum_kind(flags)) { case NJS_ENUM_KEYS: for (i = 0; i < length; i++) { - njs_uint32_to_string(item++, i); + ret = njs_uint32_to_string(vm, item++, i); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } break; @@ -719,7 +684,11 @@ njs_object_enumerate_typed_array(njs_vm_t *vm, const njs_typed_array_t *array, return NJS_ERROR; } - njs_uint32_to_string(&entry->start[0], i); + ret = njs_uint32_to_string(vm, &entry->start[0], i); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + njs_set_number(&entry->start[1], njs_typed_array_prop(array, i)); njs_set_array(item++, entry); @@ -738,7 +707,7 @@ static njs_int_t njs_object_enumerate_string(njs_vm_t *vm, const njs_value_t *value, njs_array_t *items, uint32_t flags) { - u_char *begin; + u_char buf[4], *c; uint32_t i, len, size; njs_int_t ret; njs_value_t *item, *string; @@ -746,7 +715,7 @@ njs_object_enumerate_string(njs_vm_t *vm, const njs_value_t *value, const u_char *src, *end; njs_string_prop_t str_prop; - len = (uint32_t) njs_string_prop(&str_prop, value); + len = (uint32_t) njs_string_prop(vm, &str_prop, value); ret = njs_array_expand(vm, items, 0, len); if (njs_slow_path(ret != NJS_OK)) { @@ -758,7 +727,10 @@ njs_object_enumerate_string(njs_vm_t *vm, const njs_value_t *value, switch (njs_object_enum_kind(flags)) { case NJS_ENUM_KEYS: for (i = 0; i < len; i++) { - njs_uint32_to_string(item++, i); + ret = njs_uint32_to_string(vm, item++, i); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } break; @@ -768,10 +740,10 @@ njs_object_enumerate_string(njs_vm_t *vm, const njs_value_t *value, /* ASCII string. */ for (i = 0; i < len; i++) { - begin = njs_string_short_start(item); - *begin = str_prop.start[i]; - - njs_string_short_set(item, 1, 1); + ret = njs_string_new(vm, item, &str_prop.start[i], 1, 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } item++; } @@ -783,11 +755,15 @@ njs_object_enumerate_string(njs_vm_t *vm, const njs_value_t *value, end = src + str_prop.size; do { - begin = (u_char *) src; - njs_utf8_copy(njs_string_short_start(item), &src, end); - size = (uint32_t) (src - begin); + c = buf; - njs_string_short_set(item, size, 1); + c = njs_utf8_copy(c, &src, end); + size = c - buf; + + ret = njs_string_new(vm, item, buf, size, 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } item++; @@ -807,14 +783,17 @@ njs_object_enumerate_string(njs_vm_t *vm, const njs_value_t *value, return NJS_ERROR; } - njs_uint32_to_string(&entry->start[0], i); + ret = njs_uint32_to_string(vm, &entry->start[0], i); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } string = &entry->start[1]; - begin = njs_string_short_start(string); - *begin = str_prop.start[i]; - - njs_string_short_set(string, 1, 1); + ret = njs_string_new(vm, string, &str_prop.start[i], 1, 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } njs_set_array(item, entry); @@ -834,15 +813,22 @@ njs_object_enumerate_string(njs_vm_t *vm, const njs_value_t *value, return NJS_ERROR; } - njs_uint32_to_string(&entry->start[0], i++); + ret = njs_uint32_to_string(vm, &entry->start[0], i++); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } string = &entry->start[1]; - begin = (u_char *) src; - njs_utf8_copy(njs_string_short_start(string), &src, end); - size = (uint32_t) (src - begin); + c = buf; - njs_string_short_set(string, size, 1); + c = njs_utf8_copy(c, &src, end); + size = c - buf; + + ret = njs_string_new(vm, string, buf, size, 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } njs_set_array(item, entry); @@ -887,14 +873,14 @@ njs_object_enumerate_object(njs_vm_t *vm, const njs_object_t *object, } -#define njs_process_prop(vm, prop, flags, items, items_symbol) \ - if (!(flags & NJS_ENUM_SYMBOL && njs_is_symbol(&prop->name))) { \ +#define njs_process_prop(vm, prop_name, flags, items, items_symbol) \ + if (!(flags & NJS_ENUM_SYMBOL && njs_is_symbol(prop_name))) { \ /* \ * prop from shared_hash is not symbol: \ * add to items before props from hash \ */ \ \ - ret = njs_array_add(vm, items, &prop->name); \ + ret = njs_array_add(vm, items, prop_name); \ if (njs_slow_path(ret != NJS_OK)) { \ return NJS_ERROR; \ } \ @@ -904,7 +890,7 @@ njs_object_enumerate_object(njs_vm_t *vm, const njs_object_t *object, * prop from shared_hash is symbol: \ * add to items_symbol \ */ \ - ret = njs_array_add(vm, items_symbol, &prop->name); \ + ret = njs_array_add(vm, items_symbol, prop_name); \ if (njs_slow_path(ret != NJS_OK)) { \ return NJS_ERROR; \ } \ @@ -915,14 +901,16 @@ static njs_int_t njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, const njs_object_t *parent, njs_array_t *items, uint32_t flags) { - double num; - uint32_t items_length; - njs_int_t ret; - njs_array_t *items_string, *items_symbol; - njs_lvlhsh_each_t lhe; - njs_object_prop_t *prop, *ext_prop; - njs_lvlhsh_query_t lhq; - const njs_lvlhsh_t *hash; + double num; + uint32_t items_length; + njs_int_t ret; + njs_array_t *items_string, *items_symbol; + njs_value_t prop_name; + njs_object_prop_t *prop, *ext_prop; + njs_flathsh_elt_t *elt; + njs_flathsh_each_t lhe; + const njs_flathsh_t *hash; + njs_flathsh_query_t lhq; items_length = items->length; @@ -938,7 +926,7 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, lhq.proto = &njs_object_hash_proto; - njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + njs_flathsh_each_init(&lhe, &njs_object_hash_proto); hash = &object->shared_hash; if (flags & NJS_ENUM_NON_SHARED_ONLY) { @@ -946,24 +934,30 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, } for ( ;; ) { - prop = njs_lvlhsh_each(hash, &lhe); - - if (prop == NULL) { + elt = njs_flathsh_each(hash, &lhe); + if (elt == NULL) { break; } - if (!njs_is_enumerable(&prop->name, flags)) { + prop = elt->value; + + ret = njs_atom_to_value(vm, &prop_name, elt->key_hash); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + if (!njs_is_enumerable(&prop_name, flags)) { continue; } - njs_object_property_key_set(&lhq, &prop->name, lhe.key_hash); + lhq.key_hash = elt->key_hash; ext_prop = njs_object_exist_in_proto(parent, object, &lhq); if (ext_prop != NULL) { continue; } - ret = njs_lvlhsh_find(&object->hash, &lhq); + ret = njs_flathsh_unique_find(&object->hash, &lhq); if (ret != NJS_OK) { if (!(prop->enumerable || !(flags & NJS_ENUM_ENUMERABLE_ONLY))) { @@ -972,12 +966,13 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, /* prop is: !in_hash && in_shared_hash */ - num = njs_string_to_index(&prop->name); + num = njs_string_to_index(&prop_name); if (!njs_number_is_integer_index(num)) { - njs_process_prop(vm, prop, flags, items_string, items_symbol); + njs_process_prop(vm, &prop_name, flags, items_string, + items_symbol); } else { - ret = njs_array_add(vm, items, &prop->name); + ret = njs_array_add(vm, items, &prop_name); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -993,7 +988,7 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, /* prop is: in_hash && in_shared_hash */ - num = njs_string_to_index(&prop->name); + num = njs_string_to_index(&prop_name); if (!njs_number_is_integer_index(num)) { njs_object_prop_t *hash_prop = lhq.value; @@ -1005,7 +1000,7 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, if (hash_prop->type != NJS_WHITEOUT && !(hash_prop->enum_in_object_hash)) { - njs_process_prop(vm, prop, flags, items_string, + njs_process_prop(vm, &prop_name, flags, items_string, items_symbol); } } @@ -1014,56 +1009,60 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, local_hash: - njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + njs_flathsh_each_init(&lhe, &njs_object_hash_proto); hash = &object->hash; for ( ;; ) { - prop = njs_lvlhsh_each(hash, &lhe); - - if (prop == NULL) { + elt = njs_flathsh_each(hash, &lhe); + if (elt == NULL) { break; } - if (!njs_is_enumerable(&prop->name, flags) || + prop = elt->value; + + ret = njs_atom_to_value(vm, &prop_name, elt->key_hash); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + if (!njs_is_enumerable(&prop_name, flags) || !(prop->enumerable || !(flags & NJS_ENUM_ENUMERABLE_ONLY)) || prop->type == NJS_WHITEOUT) { continue; } - njs_object_property_key_set(&lhq, &prop->name, lhe.key_hash); + lhq.key_hash = elt->key_hash; ext_prop = njs_object_exist_in_proto(parent, object, &lhq); if (ext_prop != NULL) { continue; } - num = njs_string_to_index(&prop->name); + num = njs_string_to_index(&prop_name); if (njs_number_is_integer_index(num)) { - ret = njs_array_add(vm, items, &prop->name); + ret = njs_array_add(vm, items, &prop_name); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } } else { - ret = njs_lvlhsh_find(&object->shared_hash, &lhq); + ret = njs_flathsh_unique_find(&object->shared_hash, &lhq); if (ret != NJS_OK) { /* prop is: in_hash && !in_shared_hash */ /* select names of not deleted props */ - - njs_process_prop(vm, prop, flags, items_string, + njs_process_prop(vm, &prop_name, flags, items_string, items_symbol); } else { /* prop is: in_hash && in_shared_hash */ /* select names of not deleted and created again */ - if (prop->enum_in_object_hash) { - njs_process_prop(vm, prop, flags, items_string, + njs_process_prop(vm, &prop_name, flags, items_string, items_symbol); } } @@ -1139,8 +1138,8 @@ njs_object_own_enumerate_object(njs_vm_t *vm, const njs_object_t *object, njs_set_object(&value, (njs_object_t *) object); for (i = 0; i< items_sorted->length; i++) { - ret = njs_value_property(vm, &value, &items_sorted->start[i], - &retval); + ret = njs_value_property_val(vm, &value, &items_sorted->start[i], + &retval); if (njs_slow_path(ret != NJS_OK)) { njs_array_destroy(vm, items_sorted); return NJS_ERROR; @@ -1221,8 +1220,10 @@ static njs_int_t njs_object_copy_shared_hash(njs_vm_t *vm, njs_object_t *object) { njs_int_t ret; + njs_value_t prop_name; njs_flathsh_t new_hash, *shared_hash; njs_object_prop_t *prop; + njs_flathsh_elt_t *elt; njs_flathsh_each_t fhe; njs_flathsh_query_t fhq; @@ -1236,24 +1237,30 @@ njs_object_copy_shared_hash(njs_vm_t *vm, njs_object_t *object) njs_flathsh_each_init(&fhe, &njs_object_hash_proto); for ( ;; ) { - prop = njs_flathsh_each(shared_hash, &fhe); - - if (prop == NULL) { + elt = njs_flathsh_each(shared_hash, &fhe); + if (elt == NULL) { break; } - if (njs_is_symbol(&prop->name)) { - fhq.key_hash = njs_symbol_key(&prop->name); + prop = elt->value; + + ret = njs_atom_to_value(vm, &prop_name, elt->key_hash); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + if (njs_is_symbol(&prop_name)) { + fhq.key_hash = njs_symbol_key(&prop_name); fhq.key.start = NULL; } else { - njs_string_get(&prop->name, &fhq.key); - fhq.key_hash = njs_djb_hash(fhq.key.start, fhq.key.length); + njs_string_get(vm, &prop_name, &fhq.key); + fhq.key_hash = elt->key_hash; } fhq.value = prop; - ret = njs_flathsh_insert(&new_hash, &fhq); + ret = njs_flathsh_unique_insert(&new_hash, &fhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; @@ -1331,10 +1338,10 @@ njs_object_make_shared(njs_vm_t *vm, njs_object_t *object) } - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0, 0); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); key = &s->keys->start[s->index++]; - ret = njs_property_query(vm, &pq, &s->value, key); + ret = njs_property_query_val(vm, &pq, &s->value, key); if (njs_slow_path(ret != NJS_OK)) { if (ret == NJS_DECLINED) { continue; @@ -1346,7 +1353,8 @@ njs_object_make_shared(njs_vm_t *vm, njs_object_t *object) prop = pq.lhq.value; - ret = njs_flathsh_insert(&njs_object(&s->value)->shared_hash, &pq.lhq); + ret = njs_flathsh_unique_insert(&njs_object(&s->value)->shared_hash, + &pq.lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; @@ -1445,10 +1453,10 @@ njs_object_traverse(njs_vm_t *vm, njs_object_t *object, void *ctx, continue; } - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0, 0); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); key = &s->keys->start[s->index++]; - ret = njs_property_query(vm, &pq, &s->value, key); + ret = njs_property_query_val(vm, &pq, &s->value, key); if (njs_slow_path(ret != NJS_OK)) { if (ret == NJS_DECLINED) { continue; @@ -1459,6 +1467,7 @@ njs_object_traverse(njs_vm_t *vm, njs_object_t *object, void *ctx, prop = pq.lhq.value; s->prop = prop; + s->atom_id = pq.lhq.key_hash; ret = cb(vm, s, ctx); if (njs_slow_path(ret != NJS_OK)) { @@ -1472,7 +1481,8 @@ njs_object_traverse(njs_vm_t *vm, njs_object_t *object, void *ctx, njs_value_assign(&value, njs_prop_value(prop)); if (prop->type == NJS_PROPERTY_HANDLER) { - ret = njs_prop_handler(prop)(vm, prop, &s->value, NULL, &value); + ret = njs_prop_handler(prop)(vm, prop, pq.lhq.key_hash, &s->value, + NULL, &value); if (njs_slow_path(ret == NJS_ERROR)) { return ret; @@ -1536,8 +1546,13 @@ njs_object_define_property(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, value = njs_argument(args, 1); name = njs_lvalue_arg(&lvalue, args, nargs, 2); - ret = njs_object_prop_define(vm, value, name, desc, - NJS_OBJECT_PROP_DESCRIPTOR, 0); + ret = njs_value_to_key(vm, name, name); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + ret = njs_object_prop_define_val(vm, value, name, desc, + NJS_OBJECT_PROP_DESCRIPTOR); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -1578,12 +1593,10 @@ njs_object_define_properties(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, length = keys->length; value = njs_argument(args, 1); - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0, 0); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); for (i = 0; i < length; i++) { - pq.lhq.key_hash = 0; - - ret = njs_property_query(vm, &pq, descs, &keys->start[i]); + ret = njs_property_query_val(vm, &pq, descs, &keys->start[i]); if (njs_slow_path(ret == NJS_ERROR)) { goto done; } @@ -1594,13 +1607,13 @@ njs_object_define_properties(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, continue; } - ret = njs_value_property(vm, descs, &keys->start[i], &desc); + ret = njs_value_property(vm, descs, keys->start[i].atom_id, &desc); if (njs_slow_path(ret == NJS_ERROR)) { goto done; } - ret = njs_object_prop_define(vm, value, &keys->start[i], &desc, - NJS_OBJECT_PROP_DESCRIPTOR, 0); + ret = njs_object_prop_define(vm, value, keys->start[i].atom_id, &desc, + NJS_OBJECT_PROP_DESCRIPTOR); if (njs_slow_path(ret != NJS_OK)) { goto done; } @@ -1641,13 +1654,13 @@ static njs_int_t njs_object_get_own_property_descriptors(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - njs_int_t ret; - uint32_t i, length; - njs_array_t *names; - njs_value_t descriptor, *value, *key; - njs_object_t *descriptors; - njs_object_prop_t *pr; - njs_lvlhsh_query_t lhq; + uint32_t i, length; + njs_int_t ret; + njs_array_t *names; + njs_value_t descriptor, *value, *key; + njs_object_t *descriptors; + njs_object_prop_t *pr; + njs_flathsh_query_t lhq; value = njs_arg(args, nargs, 1); @@ -1684,16 +1697,16 @@ njs_object_get_own_property_descriptors(njs_vm_t *vm, njs_value_t *args, goto done; } - pr = njs_object_prop_alloc(vm, key, &descriptor, 1); + pr = njs_object_prop_alloc(vm, &descriptor, 1); if (njs_slow_path(pr == NULL)) { ret = NJS_ERROR; goto done; } - njs_object_property_key_set(&lhq, key, 0); + lhq.key_hash = key->atom_id; lhq.value = pr; - ret = njs_lvlhsh_insert(&descriptors->hash, &lhq); + ret = njs_flathsh_unique_insert(&descriptors->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); goto done; @@ -1748,7 +1761,7 @@ njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, value = njs_arg(args, nargs, 1); if (njs_is_object(value)) { - njs_object_prototype_proto(vm, NULL, value, NULL, retval); + njs_object_prototype_proto(vm, NULL, 0, value, NULL, retval); return NJS_OK; } @@ -1823,14 +1836,15 @@ static njs_int_t njs_object_set_integrity_level(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t level, njs_value_t *retval) { - uint32_t length; - njs_int_t ret; - njs_array_t *array; - njs_value_t *value; - njs_lvlhsh_t *hash; - njs_object_t *object; - njs_object_prop_t *prop; - njs_lvlhsh_each_t lhe; + uint32_t length; + njs_int_t ret; + njs_array_t *array; + njs_value_t *value; + njs_object_t *object; + njs_flathsh_t *hash; + njs_object_prop_t *prop; + njs_flathsh_elt_t *elt; + njs_flathsh_each_t lhe; value = njs_arg(args, nargs, 1); @@ -1865,17 +1879,18 @@ njs_object_set_integrity_level(njs_vm_t *vm, njs_value_t *args, object = njs_object(value); object->extensible = 0; - njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + njs_flathsh_each_init(&lhe, &njs_object_hash_proto); hash = &object->hash; for ( ;; ) { - prop = njs_lvlhsh_each(hash, &lhe); - - if (prop == NULL) { + elt = njs_flathsh_each(hash, &lhe); + if (elt == NULL) { break; } + prop = elt->value; + if (level == NJS_OBJECT_INTEGRITY_FROZEN && !njs_is_accessor_descriptor(prop)) { @@ -1895,11 +1910,12 @@ static njs_int_t njs_object_test_integrity_level(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t level, njs_value_t *retval) { - njs_value_t *value; - njs_lvlhsh_t *hash; - njs_object_t *object; - njs_object_prop_t *prop; - njs_lvlhsh_each_t lhe; + njs_value_t *value; + njs_object_t *object; + njs_flathsh_t *hash; + njs_object_prop_t *prop; + njs_flathsh_elt_t *elt; + njs_flathsh_each_t lhe; value = njs_arg(args, nargs, 1); @@ -1923,17 +1939,18 @@ njs_object_test_integrity_level(njs_vm_t *vm, njs_value_t *args, goto done; } - njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + njs_flathsh_each_init(&lhe, &njs_object_hash_proto); hash = &object->hash; for ( ;; ) { - prop = njs_lvlhsh_each(hash, &lhe); - - if (prop == NULL) { + elt = njs_flathsh_each(hash, &lhe); + if (elt == NULL) { break; } + prop = elt->value; + if (prop->configurable) { goto done; } @@ -2027,9 +2044,9 @@ njs_object_assign(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, for (j = 0; j < length; j++) { key = &names->start[j]; - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0, 1); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); - ret = njs_property_query(vm, &pq, source, key); + ret = njs_property_query_val(vm, &pq, source, key); if (njs_slow_path(ret != NJS_OK)) { goto exception; } @@ -2039,12 +2056,12 @@ njs_object_assign(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, continue; } - ret = njs_value_property(vm, source, key, &setval); + ret = njs_value_property(vm, source, key->atom_id, &setval); if (njs_slow_path(ret != NJS_OK)) { goto exception; } - ret = njs_value_property_set(vm, value, key, &setval); + ret = njs_value_property_set(vm, value, key->atom_id, &setval); if (njs_slow_path(ret != NJS_OK)) { goto exception; } @@ -2069,8 +2086,8 @@ static njs_int_t njs_object_is(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - njs_set_boolean(retval, njs_values_same(njs_arg(args, nargs, 1), - njs_arg(args, nargs, 2))); + njs_set_boolean(retval, njs_values_same(vm, njs_arg(args, nargs, 1), + njs_arg(args, nargs, 2))); return NJS_OK; } @@ -2084,7 +2101,8 @@ njs_object_is(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_int_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_uint_t index; njs_object_t *proto; @@ -2120,7 +2138,8 @@ njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_object_prop_t *prop, njs_int_t njs_object_prototype_create(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { int64_t index; njs_function_t *function; @@ -2146,30 +2165,29 @@ njs_object_prototype_create(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t * -njs_property_prototype_create(njs_vm_t *vm, njs_lvlhsh_t *hash, +njs_property_prototype_create(njs_vm_t *vm, njs_flathsh_t *hash, njs_object_t *prototype) { - njs_int_t ret; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; - - static const njs_value_t proto_string = njs_string("prototype"); + njs_int_t ret; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; - prop = njs_object_prop_alloc(vm, &proto_string, &njs_value_undefined, 0); + prop = njs_object_prop_alloc(vm, &njs_value_undefined, 0); if (njs_slow_path(prop == NULL)) { return NULL; } + lhq.value = prop; + njs_set_type_object(njs_prop_value(prop), prototype, prototype->type); - lhq.value = prop; - lhq.key_hash = NJS_PROTOTYPE_HASH; - lhq.key = njs_str_value("prototype"); + lhq.key_hash = NJS_ATOM_STRING_prototype; + lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(hash, &lhq); + ret = njs_flathsh_unique_insert(hash, &lhq); if (njs_fast_path(ret == NJS_OK)) { return njs_prop_value(prop); @@ -2181,65 +2199,70 @@ njs_property_prototype_create(njs_vm_t *vm, njs_lvlhsh_t *hash, } -static const njs_object_prop_t njs_object_constructor_properties[] = +static const njs_object_prop_init_t njs_object_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("Object"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_NATIVE("create", njs_object_create, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_create, njs_object_create, 2, 0), - NJS_DECLARE_PROP_NATIVE("keys", njs_object_keys, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_keys, njs_object_keys, 1, 0), - NJS_DECLARE_PROP_NATIVE("values", njs_object_values, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_values, njs_object_values, 1, 0), - NJS_DECLARE_PROP_NATIVE("entries", njs_object_entries, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_entries, njs_object_entries, 1, 0), - NJS_DECLARE_PROP_NATIVE("defineProperty", njs_object_define_property, 3, 0), + NJS_DECLARE_PROP_NATIVE(STRING_defineProperty, + njs_object_define_property, 3, 0), - NJS_DECLARE_PROP_LNATIVE("defineProperties", - njs_object_define_properties, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_defineProperties, + njs_object_define_properties, 2, 0), - NJS_DECLARE_PROP_LNATIVE("getOwnPropertyDescriptor", - njs_object_get_own_property_descriptor, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_getOwnPropertyDescriptor, + njs_object_get_own_property_descriptor, 2, 0), - NJS_DECLARE_PROP_LNATIVE("getOwnPropertyDescriptors", - njs_object_get_own_property_descriptors, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_getOwnPropertyDescriptors, + njs_object_get_own_property_descriptors, 1, 0), - NJS_DECLARE_PROP_LNATIVE("getOwnPropertyNames", - njs_object_get_own_property, 1, NJS_ENUM_STRING), + NJS_DECLARE_PROP_NATIVE(STRING_getOwnPropertyNames, + njs_object_get_own_property, 1, NJS_ENUM_STRING), - NJS_DECLARE_PROP_LNATIVE("getOwnPropertySymbols", - njs_object_get_own_property, 1, NJS_ENUM_SYMBOL), + NJS_DECLARE_PROP_NATIVE(STRING_getOwnPropertySymbols, + njs_object_get_own_property, 1, NJS_ENUM_SYMBOL), - NJS_DECLARE_PROP_NATIVE("getPrototypeOf", njs_object_get_prototype_of, 1, - 0), + NJS_DECLARE_PROP_NATIVE(STRING_getPrototypeOf, + njs_object_get_prototype_of, 1, 0), - NJS_DECLARE_PROP_NATIVE("setPrototypeOf", njs_object_set_prototype_of, 2, - 0), + NJS_DECLARE_PROP_NATIVE(STRING_setPrototypeOf, + njs_object_set_prototype_of, 2, 0), - NJS_DECLARE_PROP_NATIVE("freeze", njs_object_set_integrity_level, 1, - NJS_OBJECT_INTEGRITY_FROZEN), + NJS_DECLARE_PROP_NATIVE(STRING_freeze, njs_object_set_integrity_level, + 1, NJS_OBJECT_INTEGRITY_FROZEN), - NJS_DECLARE_PROP_NATIVE("isFrozen", njs_object_test_integrity_level, 1, + NJS_DECLARE_PROP_NATIVE(STRING_isFrozen, + njs_object_test_integrity_level, 1, NJS_OBJECT_INTEGRITY_FROZEN), - NJS_DECLARE_PROP_NATIVE("seal", njs_object_set_integrity_level, 1, + NJS_DECLARE_PROP_NATIVE(STRING_seal, njs_object_set_integrity_level, 1, NJS_OBJECT_INTEGRITY_SEALED), - NJS_DECLARE_PROP_NATIVE("isSealed", njs_object_test_integrity_level, 1, + NJS_DECLARE_PROP_NATIVE(STRING_isSealed, + njs_object_test_integrity_level, 1, NJS_OBJECT_INTEGRITY_SEALED), - NJS_DECLARE_PROP_LNATIVE("preventExtensions", njs_object_prevent_extensions, - 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_preventExtensions, + njs_object_prevent_extensions, 1, 0), - NJS_DECLARE_PROP_NATIVE("isExtensible", njs_object_is_extensible, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_isExtensible, njs_object_is_extensible, + 1, 0), - NJS_DECLARE_PROP_NATIVE("assign", njs_object_assign, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_assign, njs_object_assign, 2, 0), - NJS_DECLARE_PROP_NATIVE("is", njs_object_is, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_is, njs_object_is, 2, 0), }; @@ -2287,7 +2310,8 @@ njs_object_set_prototype(njs_vm_t *vm, njs_object_t *object, njs_int_t njs_object_prototype_proto(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_int_t ret; njs_object_t *proto, *object; @@ -2334,7 +2358,8 @@ njs_object_prototype_proto(njs_vm_t *vm, njs_object_prop_t *prop, njs_int_t njs_object_prototype_create_constructor(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { int64_t index; njs_value_t *cons, constructor; @@ -2401,16 +2426,14 @@ found: njs_value_t * -njs_property_constructor_set(njs_vm_t *vm, njs_lvlhsh_t *hash, +njs_property_constructor_set(njs_vm_t *vm, njs_flathsh_t *hash, njs_value_t *constructor) { - njs_int_t ret; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; - - static const njs_value_t constructor_string = njs_string("constructor"); + njs_int_t ret; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; - prop = njs_object_prop_alloc(vm, &constructor_string, constructor, 1); + prop = njs_object_prop_alloc(vm, constructor, 1); if (njs_slow_path(prop == NULL)) { return NULL; } @@ -2419,14 +2442,14 @@ njs_property_constructor_set(njs_vm_t *vm, njs_lvlhsh_t *hash, prop->enumerable = 0; lhq.value = prop; - lhq.key_hash = NJS_CONSTRUCTOR_HASH; - lhq.key = njs_str_value("constructor"); + + lhq.key_hash = NJS_ATOM_STRING_constructor; + lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(hash, &lhq); - + ret = njs_flathsh_unique_insert(hash, &lhq); if (njs_fast_path(ret == NJS_OK)) { return njs_prop_value(prop); } @@ -2457,30 +2480,6 @@ njs_object_prototype_value_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_value_t njs_object_null_string = njs_string("[object Null]"); -static const njs_value_t njs_object_undefined_string = - njs_long_string("[object Undefined]"); -static const njs_value_t njs_object_boolean_string = - njs_long_string("[object Boolean]"); -static const njs_value_t njs_object_number_string = - njs_long_string("[object Number]"); -static const njs_value_t njs_object_string_string = - njs_long_string("[object String]"); -static const njs_value_t njs_object_object_string = - njs_long_string("[object Object]"); -static const njs_value_t njs_object_array_string = - njs_string("[object Array]"); -static const njs_value_t njs_object_function_string = - njs_long_string("[object Function]"); -static const njs_value_t njs_object_regexp_string = - njs_long_string("[object RegExp]"); -static const njs_value_t njs_object_date_string = njs_string("[object Date]"); -static const njs_value_t njs_object_error_string = - njs_string("[object Error]"); -static const njs_value_t njs_object_arguments_string = - njs_long_string("[object Arguments]"); - - njs_int_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) @@ -2493,16 +2492,15 @@ njs_int_t njs_object_to_string(njs_vm_t *vm, njs_value_t *this, njs_value_t *retval) { u_char *p; + uint32_t name; njs_int_t ret; njs_value_t tag; njs_string_prop_t string; - const njs_value_t *name; if (njs_is_null_or_undefined(this)) { - njs_value_assign(retval, - njs_is_null(this) ? &njs_object_null_string - : &njs_object_undefined_string); - + njs_atom_to_value(vm, retval, + njs_is_null(this) ? NJS_ATOM_STRING__object_Null_ + : NJS_ATOM_STRING__object_Undefined_); return NJS_OK; } @@ -2511,36 +2509,36 @@ njs_object_to_string(njs_vm_t *vm, njs_value_t *this, njs_value_t *retval) return ret; } - name = &njs_object_object_string; + name = NJS_ATOM_STRING__object_Object_; if (njs_is_array(this)) { - name = &njs_object_array_string; + name = NJS_ATOM_STRING__object_Array_; } else if (njs_is_object(this) && njs_lvlhsh_eq(&njs_object(this)->shared_hash, &vm->shared->arguments_object_instance_hash)) { - name = &njs_object_arguments_string; + name = NJS_ATOM_STRING__object_Arguments_; } else if (njs_is_function(this)) { - name = &njs_object_function_string; + name = NJS_ATOM_STRING__object_Function_; } else if (njs_is_error(this)) { - name = &njs_object_error_string; + name = NJS_ATOM_STRING__object_Error_; } else if (njs_is_object_value(this)) { switch (njs_object_value(this)->type) { case NJS_BOOLEAN: - name = &njs_object_boolean_string; + name = NJS_ATOM_STRING__object_Boolean_; break; case NJS_NUMBER: - name = &njs_object_number_string; + name = NJS_ATOM_STRING__object_Number_; break; case NJS_STRING: - name = &njs_object_string_string; + name = NJS_ATOM_STRING__object_String_; break; default: @@ -2548,10 +2546,10 @@ njs_object_to_string(njs_vm_t *vm, njs_value_t *this, njs_value_t *retval) } } else if (njs_is_date(this)) { - name = &njs_object_date_string; + name = NJS_ATOM_STRING__object_Date_; } else if (njs_is_regexp(this)) { - name = &njs_object_regexp_string; + name = NJS_ATOM_STRING__object_RegExp_; } ret = njs_object_string_tag(vm, this, &tag); @@ -2560,18 +2558,12 @@ njs_object_to_string(njs_vm_t *vm, njs_value_t *this, njs_value_t *retval) } if (ret == NJS_DECLINED) { - if (njs_slow_path(name == NULL)) { - njs_internal_error(vm, "Unknown value type"); - - return NJS_ERROR; - } - - njs_value_assign(retval, name); + njs_atom_to_value(vm, retval, name); return NJS_OK; } - (void) njs_string_prop(&string, &tag); + (void) njs_string_prop(vm, &string, &tag); p = njs_string_alloc(vm, retval, string.size + njs_length("[object ]"), string.length + njs_length("[object ]")); @@ -2612,9 +2604,9 @@ njs_object_prototype_has_own_property(njs_vm_t *vm, njs_value_t *args, } } - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0, 1); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); - ret = njs_property_query(vm, &pq, value, property); + ret = njs_property_query_val(vm, &pq, value, property); switch (ret) { case NJS_OK: @@ -2658,9 +2650,9 @@ njs_object_prototype_prop_is_enumerable(njs_vm_t *vm, njs_value_t *args, } } - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0, 1); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); - ret = njs_property_query(vm, &pq, value, property); + ret = njs_property_query_val(vm, &pq, value, property); switch (ret) { case NJS_OK: @@ -2717,26 +2709,28 @@ njs_object_prototype_is_prototype_of(njs_vm_t *vm, njs_value_t *args, } -static const njs_object_prop_t njs_object_prototype_properties[] = +static const njs_object_prop_init_t njs_object_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("__proto__", njs_object_prototype_proto, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING___proto__, njs_object_prototype_proto, + 0, NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_NATIVE("valueOf", njs_object_prototype_value_of, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_valueOf, njs_object_prototype_value_of, + 0, 0), - NJS_DECLARE_PROP_NATIVE("toString", njs_object_prototype_to_string, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toString, njs_object_prototype_to_string, + 0, 0), - NJS_DECLARE_PROP_NATIVE("hasOwnProperty", + NJS_DECLARE_PROP_NATIVE(STRING_hasOwnProperty, njs_object_prototype_has_own_property, 1, 0), - NJS_DECLARE_PROP_LNATIVE("propertyIsEnumerable", - njs_object_prototype_prop_is_enumerable, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_propertyIsEnumerable, + njs_object_prototype_prop_is_enumerable, 1, 0), - NJS_DECLARE_PROP_NATIVE("isPrototypeOf", + NJS_DECLARE_PROP_NATIVE(STRING_isPrototypeOf, njs_object_prototype_is_prototype_of, 1, 0), }; @@ -2753,15 +2747,12 @@ njs_object_length(njs_vm_t *vm, njs_value_t *value, int64_t *length) njs_int_t ret; njs_value_t value_length; - const njs_value_t string_length = njs_string("length"); - if (njs_is_fast_array(value)) { *length = njs_array(value)->length; return NJS_OK; } - ret = njs_value_property(vm, value, njs_value_arg(&string_length), - &value_length); + ret = njs_value_property(vm, value, NJS_ATOM_STRING_length, &value_length); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } diff --git a/src/njs_object.h b/src/njs_object.h index e3f58fdd..6b2438df 100644 --- a/src/njs_object.h +++ b/src/njs_object.h @@ -19,6 +19,7 @@ typedef enum { NJS_OBJECT_PROP_CONFIGURABLE = 16, NJS_OBJECT_PROP_WRITABLE = 32, NJS_OBJECT_PROP_UNSET = 64, + NJS_OBJECT_PROP_IS_STRING = 128, #define NJS_OBJECT_PROP_VALUE_ECW (NJS_OBJECT_PROP_VALUE \ | NJS_OBJECT_PROP_ENUMERABLE \ | NJS_OBJECT_PROP_CONFIGURABLE \ @@ -39,8 +40,8 @@ typedef enum { struct njs_object_init_s { - const njs_object_prop_t *properties; - njs_uint_t items; + const njs_object_prop_init_t *properties; + njs_uint_t items; }; @@ -49,6 +50,7 @@ typedef struct njs_traverse_s njs_traverse_t; struct njs_traverse_s { struct njs_traverse_s *parent; njs_object_prop_t *prop; + uint32_t atom_id; njs_value_t value; njs_array_t *keys; @@ -73,21 +75,23 @@ njs_array_t *njs_object_own_enumerate(njs_vm_t *vm, const njs_object_t *object, njs_int_t njs_object_traverse(njs_vm_t *vm, njs_object_t *object, void *ctx, njs_object_traverse_cb_t cb); njs_int_t njs_object_make_shared(njs_vm_t *vm, njs_object_t *object); -njs_int_t njs_object_hash_create(njs_vm_t *vm, njs_lvlhsh_t *hash, - const njs_object_prop_t *prop, njs_uint_t n); +njs_int_t njs_object_hash_create(njs_vm_t *vm, njs_flathsh_t *hash, + const njs_object_prop_init_t *prop, njs_uint_t n); njs_int_t njs_primitive_prototype_get_proto(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); njs_int_t njs_object_prototype_create(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -njs_value_t *njs_property_prototype_create(njs_vm_t *vm, njs_lvlhsh_t *hash, + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +njs_value_t *njs_property_prototype_create(njs_vm_t *vm, njs_flathsh_t *hash, njs_object_t *prototype); njs_int_t njs_object_prototype_proto(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -njs_int_t njs_object_prototype_create_constructor(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -njs_value_t *njs_property_constructor_set(njs_vm_t *vm, njs_lvlhsh_t *hash, +njs_int_t njs_object_prototype_create_constructor(njs_vm_t *vm, + njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); +njs_value_t *njs_property_constructor_set(njs_vm_t *vm, njs_flathsh_t *hash, njs_value_t *constructor); njs_int_t njs_object_to_string(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval); @@ -97,21 +101,22 @@ njs_int_t njs_object_length(njs_vm_t *vm, njs_value_t *value, int64_t *dst); njs_int_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq, njs_object_t *proto); -njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name, +njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *value, uint8_t attributes); njs_int_t njs_object_property(njs_vm_t *vm, njs_object_t *object, - njs_lvlhsh_query_t *lhq, njs_value_t *retval); + njs_flathsh_query_t *lhq, njs_value_t *retval); njs_object_prop_t *njs_object_property_add(njs_vm_t *vm, njs_value_t *object, - njs_value_t *key, njs_bool_t replace); + uint32_t atom_id, njs_bool_t replace); njs_int_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, - njs_value_t *name, njs_value_t *value, unsigned flags, uint32_t hash); + uint32_t atom_id, njs_value_t *value, uint32_t flags); njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, njs_value_t *value, njs_value_t *setval); njs_int_t njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); const char *njs_prop_type_string(njs_object_prop_type_t type); njs_int_t njs_object_prop_init(njs_vm_t *vm, const njs_object_init_t* init, - const njs_object_prop_t *base, njs_value_t *value, njs_value_t *retval); + njs_object_prop_t *base, uint32_t atom_id, njs_value_t *value, + njs_value_t *retval); njs_inline njs_bool_t @@ -138,77 +143,38 @@ njs_is_generic_descriptor(njs_object_prop_t *prop) } -njs_inline void -njs_object_property_key_set(njs_lvlhsh_query_t *lhq, const njs_value_t *key, - uint32_t hash) -{ - if (njs_is_symbol(key)) { - - lhq->key.length = 0; - lhq->key.start = NULL; - lhq->key_hash = njs_symbol_key(key); - - } else { - - /* string. */ - - njs_string_get(key, &lhq->key); - - if (hash == 0) { - lhq->key_hash = njs_djb_hash(lhq->key.start, lhq->key.length); - - } else { - lhq->key_hash = hash; - } - } -} - - -njs_inline void -njs_object_property_init(njs_lvlhsh_query_t *lhq, const njs_value_t *key, - uint32_t hash) -{ - lhq->proto = &njs_object_hash_proto; - - njs_object_property_key_set(lhq, key, hash); -} - - njs_inline njs_int_t njs_primitive_value_to_key(njs_vm_t *vm, njs_value_t *dst, const njs_value_t *src) { - const njs_value_t *value; - switch (src->type) { - case NJS_NULL: - value = &njs_string_null; - break; + njs_atom_to_value(vm, dst, NJS_ATOM_STRING_null); + return NJS_OK; case NJS_UNDEFINED: - value = &njs_string_undefined; - break; + njs_atom_to_value(vm, dst, NJS_ATOM_STRING_undefined); + return NJS_OK; case NJS_BOOLEAN: - value = njs_is_true(src) ? &njs_string_true : &njs_string_false; - break; + if (njs_is_true(src)) { + njs_atom_to_value(vm, dst, NJS_ATOM_STRING_true); - case NJS_NUMBER: - return njs_number_to_string(vm, dst, src); + } else { + njs_atom_to_value(vm, dst, NJS_ATOM_STRING_false); + } + return NJS_OK; + + case NJS_NUMBER: case NJS_SYMBOL: case NJS_STRING: - value = src; - break; + *dst = *src; + return NJS_OK; default: return NJS_ERROR; } - - *dst = *value; - - return NJS_OK; } @@ -261,21 +227,63 @@ njs_key_string_get(njs_vm_t *vm, njs_value_t *key, njs_str_t *str) if (njs_slow_path(ret != NJS_OK)) { return ret; } + + } else if (njs_slow_path(!njs_is_string(key))) { + ret = njs_value_to_string(vm, key, key); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + njs_string_get(vm, key, str); + + return NJS_OK; +} + + +njs_inline njs_int_t +njs_atom_string_get(njs_vm_t *vm, uint32_t atom_id, njs_str_t *str) +{ + njs_value_t value; + + if (njs_atom_to_value(vm, &value, atom_id) != NJS_OK) { + return NJS_ERROR; } - njs_string_get(key, str); + njs_key_string_get(vm, &value, str); return NJS_OK; } +njs_inline njs_int_t +njs_object_prop_define_val(njs_vm_t *vm, njs_value_t *object, njs_value_t *name, + njs_value_t *value, unsigned flags) +{ + njs_int_t ret; + + if (njs_value_atom(name) == NJS_ATOM_STRING_unknown) { + ret = njs_atom_atomize_key(vm, name); + if (ret != NJS_OK) { + return ret; + } + } + + if (njs_is_string(name)) { + flags |= NJS_OBJECT_PROP_IS_STRING; + } + + return njs_object_prop_define(vm, object, name->atom_id, value, flags); +} + + njs_inline njs_int_t njs_value_create_data_prop(njs_vm_t *vm, njs_value_t *value, njs_value_t *name, njs_value_t *setval, uint32_t hash) { - return njs_object_prop_define(vm, value, name, setval, - NJS_OBJECT_PROP_CREATE - | NJS_OBJECT_PROP_VALUE_ECW, hash); + return njs_object_prop_define_val(vm, value, name, setval, + NJS_OBJECT_PROP_CREATE + | NJS_OBJECT_PROP_VALUE_ECW); } @@ -296,12 +304,9 @@ njs_object_length_set(njs_vm_t *vm, njs_value_t *value, int64_t length) { njs_value_t index; - static const njs_value_t string_length = njs_string("length"); - njs_value_number_set(&index, length); - return njs_value_property_set(vm, value, njs_value_arg(&string_length), - &index); + return njs_value_property_set(vm, value, NJS_ATOM_STRING_length, &index); } @@ -310,10 +315,7 @@ njs_object_string_tag(njs_vm_t *vm, njs_value_t *value, njs_value_t *tag) { njs_int_t ret; - static const njs_value_t to_string_tag = - njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG); - - ret = njs_value_property(vm, value, njs_value_arg(&to_string_tag), tag); + ret = njs_value_property(vm, value, NJS_ATOM_SYMBOL_toStringTag, tag); if (njs_slow_path(ret != NJS_OK)) { return ret; } diff --git a/src/njs_object_hash.h b/src/njs_object_hash.h deleted file mode 100644 index 163c814c..00000000 --- a/src/njs_object_hash.h +++ /dev/null @@ -1,842 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#ifndef _NJS_OBJECT_HASH_H_INCLUDED_ -#define _NJS_OBJECT_HASH_H_INCLUDED_ - - -#define NJS___PROTO___HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - '_'), '_'), 'p'), 'r'), 'o'), 't'), 'o'), '_'), '_') - - -#define NJS_ARRAY_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'A'), 'r'), 'r'), 'a'), 'y') - - -#define NJS_ARGV_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'a'), 'r'), 'g'), 'v') - - -#define NJS_BOOLEAN_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'B'), 'o'), 'o'), 'l'), 'e'), 'a'), 'n') - - -#define NJS_CONFIGURABLE_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'c'), 'o'), 'n'), 'f'), 'i'), 'g'), 'u'), 'r'), 'a'), 'b'), 'l'), 'e') - - -#define NJS_CONSTRUCTOR_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'c'), 'o'), 'n'), 's'), 't'), 'r'), 'u'), 'c'), 't'), 'o'), 'r') - - -#define NJS_DATE_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'D'), 'a'), 't'), 'e') - - -#define NJS_PROMISE_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'P'), 'r'), 'o'), 'm'), 'i'), 's'), 'e') - - -#define NJS_ENUMERABLE_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'e'), 'n'), 'u'), 'm'), 'e'), 'r'), 'a'), 'b'), 'l'), 'e') - - -#define NJS_ERRNO_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'e'), 'r'), 'r'), 'n'), 'o') - - -#define NJS_ERROR_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'E'), 'r'), 'r'), 'o'), 'r') - - -#define NJS_ENCODING_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'e'), 'n'), 'c'), 'o'), 'd'), 'i'), 'n'), 'g') - - -#define NJS_ENV_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'e'), 'n'), 'v') - - -#define NJS_EVAL_ERROR_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'E'), 'v'), 'a'), 'l'), 'E'), 'r'), 'r'), 'o'), 'r') - - -#define NJS_FLAG_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'f'), 'l'), 'a'), 'g') - - -#define NJS_GET_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'g'), 'e'), 't') - - -#define NJS_GLOBAL_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'g'), 'l'), 'o'), 'b'), 'a'), 'l') - - -#define NJS_GLOBAL_THIS_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'g'), 'l'), 'o'), 'b'), 'a'), 'l'), 'T'), 'h'), 'i'), 's') - - -#define NJS_FUNCTION_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'F'), 'u'), 'n'), 'c'), 't'), 'i'), 'o'), 'n') - - -#define NJS_INDEX_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'i'), 'n'), 'd'), 'e'), 'x') - - -#define NJS_INPUT_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'i'), 'n'), 'p'), 'u'), 't') - - -#define NJS_INTERNAL_ERROR_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'I'), 'n'), 't'), 'e'), 'r'), 'n'), 'a'), 'l'), \ - 'E'), 'r'), 'r'), 'o'), 'r') - - -#define NJS_GROUPS_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'g'), 'r'), 'o'), 'u'), 'p'), 's') - - -#define NJS_JOIN_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'j'), 'o'), 'i'), 'n') - - -#define NJS_JSON_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'J'), 'S'), 'O'), 'N') - - -#define NJS_LENGTH_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'l'), 'e'), 'n'), 'g'), 't'), 'h') - - -#define NJS_NAME_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'n'), 'a'), 'm'), 'e') - - -#define NJS_NJS_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'n'), 'j'), 's') - - -#define NJS_262_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - '$'), '2'), '6'), '2') - - -#define NJS_NUMBER_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'N'), 'u'), 'm'), 'b'), 'e'), 'r') - - -#define NJS_MATH_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'M'), 'a'), 't'), 'h') - - -#define NJS_MEMORY_ERROR_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'M'), 'e'), 'm'), 'o'), 'r'), 'y'), \ - 'E'), 'r'), 'r'), 'o'), 'r') - - -#define NJS_AGGREGATE_ERROR_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'A'), 'g'), 'g'), 'r'), 'e'), 'g'), 'a'), 't'), 'e'), \ - 'E'), 'r'), 'r'), 'o'), 'r') - - -#define NJS_MESSAGE_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'm'), 'e'), 's'), 's'), 'a'), 'g'), 'e') - - -#define NJS_ERRORS_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'e'), 'r'), 'r'), 'o'), 'r'), 's') - - -#define NJS_MODE_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'm'), 'o'), 'd'), 'e') - - -#define NJS_OBJECT_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'O'), 'b'), 'j'), 'e'), 'c'), 't') - - -#define NJS_PATH_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'p'), 'a'), 't'), 'h') - - -#define NJS_PROCESS_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'p'), 'r'), 'o'), 'c'), 'e'), 's'), 's') - - -#define NJS_PROTOTYPE_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'p'), 'r'), 'o'), 't'), 'o'), 't'), 'y'), 'p'), 'e') - - -#define NJS_RANGE_ERROR_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'R'), 'a'), 'n'), 'g'), 'e'), 'E'), 'r'), 'r'), 'o'), 'r') - - -#define NJS_REF_ERROR_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'R'), 'e'), 'f'), 'e'), 'r'), 'e'), 'n'), 'c'), 'e'), \ - 'E'), 'r'), 'r'), 'o'), 'r') - - -#define NJS_REGEXP_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'R'), 'e'), 'g'), 'E'), 'x'), 'p') - - -#define NJS_SET_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 's'), 'e'), 't') - - -#define NJS_STACK_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 's'), 't'), 'a'), 'c'), 'k') - - -#define NJS_STRING_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'S'), 't'), 'r'), 'i'), 'n'), 'g') - - -#define NJS_SYMBOL_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'S'), 'y'), 'm'), 'b'), 'o'), 'l') - - -#define NJS_SYNTAX_ERROR_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'S'), 'y'), 'n'), 't'), 'a'), 'x'), \ - 'E'), 'r'), 'r'), 'o'), 'r') - - -#define NJS_SYSCALL_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 's'), 'y'), 's'), 'c'), 'a'), 'l'), 'l') - - -#define NJS_TO_JSON_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 't'), 'o'), 'J'), 'S'), 'O'), 'N') - - -#define NJS_TO_STRING_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 't'), 'o'), 'S'), 't'), 'r'), 'i'), 'n'), 'g') - - -#define NJS_TO_ISO_STRING_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 't'), 'o'), 'I'), 'S'), 'O'), 'S'), 't'), 'r'), 'i'), 'n'), 'g') - - -#define NJS_TYPE_ERROR_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'T'), 'y'), 'p'), 'e'), 'E'), 'r'), 'r'), 'o'), 'r') - - -#define NJS_VALUE_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'v'), 'a'), 'l'), 'u'), 'e') - - -#define NJS_VALUE_OF_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'v'), 'a'), 'l'), 'u'), 'e'), 'O'), 'f') - - -#define NJS_WRITABABLE_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'w'), 'r'), 'i'), 't'), 'a'), 'b'), 'l'), 'e') - - -#define NJS_URI_ERROR_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'U'), 'R'), 'I'), 'E'), 'r'), 'r'), 'o'), 'r') - - -#define NJS_ARRAY_BUFFER_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'A'), 'r'), 'r'), 'a'), 'y'), 'B'), 'u'), 'f'), 'f'), 'e'), 'r') - - -#define NJS_DATA_VIEW_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'D'), 'a'), 't'), 'a'), 'V'), 'i'), 'e'), 'w') - - -#define NJS_UINT8ARRAY_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'U'), 'i'), 'n'), 't'), '8'), 'A'), 'r'), 'r'), 'a'), 'y') - - -#define NJS_UINT16ARRAY_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'U'), 'i'), 'n'), 't'), '1'), '6'), 'A'), 'r'), 'r'), 'a'), 'y') - - -#define NJS_UINT32ARRAY_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'U'), 'i'), 'n'), 't'), '3'), '2'), 'A'), 'r'), 'r'), 'a'), 'y') - - -#define NJS_INT8ARRAY_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'I'), 'n'), 't'), '8'), 'A'), 'r'), 'r'), 'a'), 'y') - - -#define NJS_INT16ARRAY_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'I'), 'n'), 't'), '1'), '6'), 'A'), 'r'), 'r'), 'a'), 'y') - - -#define NJS_INT32ARRAY_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'I'), 'n'), 't'), '3'), '2'), 'A'), 'r'), 'r'), 'a'), 'y') - - -#define NJS_FLOAT32ARRAY_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'F'), 'l'), 'o'), 'a'), 't'), '3'), '2'), 'A'), 'r'), 'r'), 'a'), 'y') - - -#define NJS_FLOAT64ARRAY_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'F'), 'l'), 'o'), 'a'), 't'), '6'), '4'), 'A'), 'r'), 'r'), 'a'), 'y') - - -#define NJS_UINT8CLAMPEDARRAY_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'U'), 'i'), 'n'), 't'), '8'), 'C'), 'l'), 'a'), 'm'), 'p'), 'e'), \ - 'd'), 'A'), 'r'), 'r'), 'a'), 'y') - - -#define NJS_TEXT_DECODER_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'T'), 'e'), 'x'), 't'), 'D'), 'e'), 'c'), 'o'), 'd'), 'e'), 'r') - - -#define NJS_TEXT_ENCODER_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'T'), 'e'), 'x'), 't'), 'E'), 'n'), 'c'), 'o'), 'd'), 'e'), 'r') - - -#define NJS_BUFFER_HASH \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add( \ - njs_djb_hash_add(NJS_DJB_HASH_INIT, \ - 'B'), 'u'), 'f'), 'f'), 'e'), 'r') - - -#endif /* _NJS_OBJECT_HASH_H_INCLUDED_ */ diff --git a/src/njs_object_prop.c b/src/njs_object_prop.c index a24af753..d7c55d3a 100644 --- a/src/njs_object_prop.c +++ b/src/njs_object_prop.c @@ -9,13 +9,13 @@ static njs_object_prop_t *njs_object_prop_alloc2(njs_vm_t *vm, - const njs_value_t *name, njs_object_prop_type_t type, unsigned flags); + njs_object_prop_type_t type, unsigned flags); static njs_object_prop_t *njs_descriptor_prop(njs_vm_t *vm, - const njs_value_t *name, const njs_value_t *desc); + const njs_value_t *desc); njs_object_prop_t * -njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name, +njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *value, uint8_t attributes) { unsigned flags; @@ -33,7 +33,7 @@ njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name, break; } - prop = njs_object_prop_alloc2(vm, name, NJS_PROPERTY, flags); + prop = njs_object_prop_alloc2(vm, NJS_PROPERTY, flags); if (njs_slow_path(prop == NULL)) { return NULL; } @@ -45,10 +45,9 @@ njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name, static njs_object_prop_t * -njs_object_prop_alloc2(njs_vm_t *vm, const njs_value_t *name, +njs_object_prop_alloc2(njs_vm_t *vm, njs_object_prop_type_t type, unsigned flags) { - njs_int_t ret; njs_object_prop_t *prop; prop = njs_mp_align(vm->mem_pool, sizeof(njs_value_t), @@ -58,15 +57,6 @@ njs_object_prop_alloc2(njs_vm_t *vm, const njs_value_t *name, return NULL; } - njs_value_assign(&prop->name, name); - - if (njs_slow_path(!njs_is_key(&prop->name))) { - ret = njs_value_to_key(vm, &prop->name, &prop->name); - if (njs_slow_path(ret != NJS_OK)) { - return NULL; - } - } - prop->type = type; prop->enum_in_object_hash = 0; @@ -92,15 +82,15 @@ njs_object_prop_alloc2(njs_vm_t *vm, const njs_value_t *name, njs_int_t -njs_object_property(njs_vm_t *vm, njs_object_t *object, njs_lvlhsh_query_t *lhq, - njs_value_t *retval) +njs_object_property(njs_vm_t *vm, njs_object_t *object, + njs_flathsh_query_t *lhq, njs_value_t *retval) { njs_int_t ret; njs_value_t value; njs_object_prop_t *prop; do { - ret = njs_lvlhsh_find(&object->hash, lhq); + ret = njs_flathsh_unique_find(&object->hash, lhq); if (njs_fast_path(ret == NJS_OK)) { prop = lhq->value; @@ -110,7 +100,7 @@ njs_object_property(njs_vm_t *vm, njs_object_t *object, njs_lvlhsh_query_t *lhq, } } - ret = njs_lvlhsh_find(&object->shared_hash, lhq); + ret = njs_flathsh_unique_find(&object->shared_hash, lhq); if (njs_fast_path(ret == NJS_OK)) { goto found; @@ -145,32 +135,25 @@ found: njs_object_prop_t * -njs_object_property_add(njs_vm_t *vm, njs_value_t *object, njs_value_t *key, +njs_object_property_add(njs_vm_t *vm, njs_value_t *object, unsigned atom_id, njs_bool_t replace) { - njs_int_t ret; - njs_value_t key_value; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; - prop = njs_object_prop_alloc(vm, key, &njs_value_invalid, 1); + prop = njs_object_prop_alloc(vm, &njs_value_invalid, 1); if (njs_slow_path(prop == NULL)) { return NULL; } - ret = njs_value_to_key(vm, &key_value, key); - if (njs_slow_path(ret != NJS_OK)) { - return NULL; - } - - lhq.proto = &njs_object_hash_proto; - njs_string_get(&key_value, &lhq.key); - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); lhq.value = prop; + lhq.key_hash = atom_id; lhq.replace = replace; lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(njs_object_hash(object), &lhq); + ret = njs_flathsh_unique_insert(njs_object_hash(object), &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NULL; @@ -184,32 +167,23 @@ njs_object_property_add(njs_vm_t *vm, njs_value_t *object, njs_value_t *key, * ES5.1, 8.12.9: [[DefineOwnProperty]] */ njs_int_t -njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, - njs_value_t *name, njs_value_t *value, unsigned flags, uint32_t hash) +njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, unsigned atom_id, + njs_value_t *value, unsigned flags) { uint32_t length, index; njs_int_t ret; njs_array_t *array; - njs_value_t retval; + njs_value_t key, retval; njs_object_prop_t *prop, *prev; njs_property_query_t pq; - static const njs_str_t length_key = njs_str("length"); - - if (njs_slow_path(!njs_is_index_or_key(name))) { - ret = njs_value_to_key(vm, name, name); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - } - again: - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, hash, 1); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 1); ret = (flags & NJS_OBJECT_PROP_CREATE) ? NJS_DECLINED - : njs_property_query(vm, &pq, object, name); + : njs_property_query(vm, &pq, object, atom_id); if (njs_slow_path(ret == NJS_ERROR)) { return ret; @@ -217,7 +191,7 @@ again: switch (njs_prop_type(flags)) { case NJS_OBJECT_PROP_DESCRIPTOR: - prop = njs_descriptor_prop(vm, name, value); + prop = njs_descriptor_prop(vm, value); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -227,20 +201,18 @@ again: case NJS_OBJECT_PROP_VALUE: if (((flags & NJS_OBJECT_PROP_VALUE_ECW) == NJS_OBJECT_PROP_VALUE_ECW) && njs_is_fast_array(object) - && njs_is_number(name)) + && njs_atom_is_number(atom_id)) { - if (njs_number_is_integer_index(njs_number(name))) { - array = njs_array(object); - index = (uint32_t) njs_number(name); + array = njs_array(object); + index = njs_atom_number(atom_id); - if (index < array->length) { - njs_value_assign(&array->start[index], value); - return NJS_OK; - } + if (index < array->length) { + njs_value_assign(&array->start[index], value); + return NJS_OK; } } - prop = njs_object_prop_alloc2(vm, name, NJS_PROPERTY, + prop = njs_object_prop_alloc2(vm, NJS_PROPERTY, flags & NJS_OBJECT_PROP_VALUE_ECW); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; @@ -254,7 +226,7 @@ again: default: njs_assert(njs_is_function(value)); - prop = njs_object_prop_alloc2(vm, name, NJS_ACCESSOR, + prop = njs_object_prop_alloc2(vm, NJS_ACCESSOR, NJS_OBJECT_PROP_VALUE_EC); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; @@ -277,17 +249,23 @@ again: set_prop: if (!njs_object(object)->extensible) { - njs_key_string_get(vm, name, &pq.lhq.key); + njs_atom_string_get(vm, atom_id, &pq.lhq.key); njs_type_error(vm, "Cannot add property \"%V\", " "object is not extensible", &pq.lhq.key); return NJS_ERROR; } - if (njs_slow_path(njs_is_typed_array(object) - && njs_is_string(name))) + if (njs_slow_path(njs_is_typed_array(object) && + (flags & NJS_OBJECT_PROP_IS_STRING))) { /* Integer-Indexed Exotic Objects [[DefineOwnProperty]]. */ - if (!isnan(njs_string_to_index(name))) { + + ret = njs_atom_to_value(vm, &key, atom_id); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (!isnan(njs_string_to_index(&key))) { njs_type_error(vm, "Invalid typed array index"); return NJS_ERROR; } @@ -332,32 +310,13 @@ set_prop: } else { - if ((flags & NJS_OBJECT_PROP_CREATE)) { - ret = njs_primitive_value_to_key(vm, &pq.key, name); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } - - if (njs_is_symbol(name)) { - pq.lhq.key_hash = njs_symbol_key(name); - pq.lhq.key.start = NULL; - - } else { - njs_string_get(&pq.key, &pq.lhq.key); - pq.lhq.key_hash = (hash == 0) - ? njs_djb_hash(pq.lhq.key.start, - pq.lhq.key.length) - : hash; - } - - pq.lhq.proto = &njs_object_hash_proto; - } - + pq.lhq.key_hash = atom_id; + pq.lhq.proto = &njs_object_hash_proto; pq.lhq.value = prop; pq.lhq.replace = 0; pq.lhq.pool = vm->mem_pool; - ret = njs_lvlhsh_insert(njs_object_hash(object), &pq.lhq); + ret = njs_flathsh_unique_insert(njs_object_hash(object), &pq.lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; @@ -498,7 +457,8 @@ set_prop: if (njs_is_valid(njs_prop_value(prop)) && prev->type != NJS_PROPERTY_HANDLER - && !njs_values_same(njs_prop_value(prop), njs_prop_value(prev))) + && !njs_values_same(vm, njs_prop_value(prop), + njs_prop_value(prev))) { goto exception; } @@ -523,8 +483,7 @@ set_prop: done: if (njs_slow_path(njs_is_fast_array(object) - && pq.lhq.key_hash == NJS_LENGTH_HASH) - && njs_strstr_eq(&pq.lhq.key, &length_key) + && pq.lhq.key_hash == NJS_ATOM_STRING_length) && prop->writable == NJS_ATTRIBUTE_FALSE) { array = njs_array(object); @@ -558,7 +517,7 @@ done: if (prev->type == NJS_PROPERTY_HANDLER) { if (prev->writable) { - ret = njs_prop_handler(prev)(vm, prev, object, + ret = njs_prop_handler(prev)(vm, prev, atom_id, object, njs_prop_value(prop), &retval); if (njs_slow_path(ret == NJS_ERROR)) { return ret; @@ -578,13 +537,12 @@ done: } else { if (njs_slow_path(njs_is_array(object) - && pq.lhq.key_hash == NJS_LENGTH_HASH) - && njs_strstr_eq(&pq.lhq.key, &length_key)) + && pq.lhq.key_hash == NJS_ATOM_STRING_length)) { if (prev->configurable != NJS_ATTRIBUTE_TRUE && prev->writable != NJS_ATTRIBUTE_TRUE - && !njs_values_strict_equal(njs_prop_value(prev), - njs_prop_value(prop))) + && !njs_values_strict_equal(vm, njs_prop_value(prev), + njs_prop_value(prop))) { njs_type_error(vm, "Cannot redefine property: \"length\""); return NJS_ERROR; @@ -623,7 +581,7 @@ done: exception: - njs_key_string_get(vm, &pq.key, &pq.lhq.key); + njs_atom_string_get(vm, atom_id, &pq.lhq.key); njs_type_error(vm, "Cannot redefine property: \"%V\"", &pq.lhq.key); return NJS_ERROR; @@ -635,7 +593,7 @@ njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq, njs_object_t *proto) { njs_int_t ret; - njs_value_t *value; + njs_value_t *value, prop_name; njs_object_t *object; njs_function_t *function; njs_object_prop_t *prop, *shared; @@ -654,7 +612,7 @@ njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq, pq->lhq.value = prop; pq->lhq.pool = vm->mem_pool; - ret = njs_lvlhsh_insert(&proto->hash, &pq->lhq); + ret = njs_flathsh_unique_insert(&proto->hash, &pq->lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; @@ -710,7 +668,12 @@ njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq, return NJS_ERROR; } - return njs_function_name_set(vm, function, &prop->name, NULL); + ret = njs_atom_to_value(vm, &prop_name, pq->lhq.key_hash); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + return njs_function_name_set(vm, function, &prop_name, NULL); default: break; @@ -721,25 +684,22 @@ njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq, static njs_object_prop_t * -njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, - const njs_value_t *desc) +njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc) { - njs_int_t ret; - njs_bool_t data, accessor; - njs_value_t value; - njs_object_t *desc_object; - njs_function_t *getter, *setter; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; - - static const njs_value_t get_string = njs_string("get"); + njs_int_t ret; + njs_bool_t data, accessor; + njs_value_t value; + njs_object_t *desc_object; + njs_function_t *getter, *setter; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; if (!njs_is_object(desc)) { njs_type_error(vm, "property descriptor must be an object"); return NULL; } - prop = njs_object_prop_alloc(vm, name, &njs_value_invalid, + prop = njs_object_prop_alloc(vm, &njs_value_invalid, NJS_ATTRIBUTE_UNSET); if (njs_slow_path(prop == NULL)) { return NULL; @@ -751,7 +711,8 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, setter = NJS_PROP_PTR_UNSET; desc_object = njs_object(desc); - njs_object_property_init(&lhq, &get_string, NJS_GET_HASH); + lhq.proto = &njs_object_hash_proto; + lhq.key_hash = NJS_ATOM_STRING_get; ret = njs_object_property(vm, desc_object, &lhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { @@ -768,8 +729,7 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, getter = njs_is_function(&value) ? njs_function(&value) : NULL; } - lhq.key = njs_str_value("set"); - lhq.key_hash = NJS_SET_HASH; + lhq.key_hash = NJS_ATOM_STRING_set; ret = njs_object_property(vm, desc_object, &lhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { @@ -786,8 +746,7 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, setter = njs_is_function(&value) ? njs_function(&value) : NULL; } - lhq.key = njs_str_value("value"); - lhq.key_hash = NJS_VALUE_HASH; + lhq.key_hash = NJS_ATOM_STRING_value; ret = njs_object_property(vm, desc_object, &lhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { @@ -799,8 +758,7 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, njs_value_assign(njs_prop_value(prop), &value); } - lhq.key = njs_str_value("writable"); - lhq.key_hash = NJS_WRITABABLE_HASH; + lhq.key_hash = NJS_ATOM_STRING_writable; ret = njs_object_property(vm, desc_object, &lhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { @@ -818,8 +776,7 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, return NULL; } - lhq.key = njs_str_value("enumerable"); - lhq.key_hash = NJS_ENUMERABLE_HASH; + lhq.key_hash = NJS_ATOM_STRING_enumerable; ret = njs_object_property(vm, desc_object, &lhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { @@ -830,8 +787,7 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, prop->enumerable = njs_is_true(&value); } - lhq.key = njs_str_value("configurable"); - lhq.key_hash = NJS_CONFIGURABLE_HASH; + lhq.key_hash = NJS_ATOM_STRING_configurable; ret = njs_object_property(vm, desc_object, &lhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { @@ -852,17 +808,6 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, } -static const njs_value_t njs_object_value_string = njs_string("value"); -static const njs_value_t njs_object_get_string = njs_string("get"); -static const njs_value_t njs_object_set_string = njs_string("set"); -static const njs_value_t njs_object_writable_string = - njs_string("writable"); -static const njs_value_t njs_object_enumerable_string = - njs_string("enumerable"); -static const njs_value_t njs_object_configurable_string = - njs_string("configurable"); - - njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, njs_value_t *value, njs_value_t *key) @@ -871,10 +816,10 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, njs_object_t *desc; njs_object_prop_t *pr, *prop; const njs_value_t *setval; - njs_lvlhsh_query_t lhq; + njs_flathsh_query_t lhq; njs_property_query_t pq; - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0, 1); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); if (njs_slow_path(!njs_is_key(key))) { ret = njs_value_to_key(vm, key, key); @@ -883,7 +828,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, } } - ret = njs_property_query(vm, &pq, value, key); + ret = njs_property_query_val(vm, &pq, value, key); switch (ret) { case NJS_OK: @@ -897,7 +842,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, case NJS_PROPERTY_HANDLER: pq.scratch = *prop; prop = &pq.scratch; - ret = njs_prop_handler(prop)(vm, prop, value, NULL, + ret = njs_prop_handler(prop)(vm, prop, key->atom_id, value, NULL, njs_prop_value(prop)); if (njs_slow_path(ret == NJS_ERROR)) { return ret; @@ -932,37 +877,33 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, lhq.pool = vm->mem_pool; if (njs_is_data_descriptor(prop)) { + lhq.key_hash = NJS_ATOM_STRING_value; - lhq.key = njs_str_value("value"); - lhq.key_hash = NJS_VALUE_HASH; - - pr = njs_object_prop_alloc(vm, &njs_object_value_string, - njs_prop_value(prop), 1); + pr = njs_object_prop_alloc(vm, njs_prop_value(prop), 1); if (njs_slow_path(pr == NULL)) { return NJS_ERROR; } lhq.value = pr; - ret = njs_lvlhsh_insert(&desc->hash, &lhq); + ret = njs_flathsh_unique_insert(&desc->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; } - lhq.key = njs_str_value("writable"); - lhq.key_hash = NJS_WRITABABLE_HASH; + lhq.key_hash = NJS_ATOM_STRING_writable; setval = (prop->writable == 1) ? &njs_value_true : &njs_value_false; - pr = njs_object_prop_alloc(vm, &njs_object_writable_string, setval, 1); + pr = njs_object_prop_alloc(vm, setval, 1); if (njs_slow_path(pr == NULL)) { return NJS_ERROR; } lhq.value = pr; - ret = njs_lvlhsh_insert(&desc->hash, &lhq); + ret = njs_flathsh_unique_insert(&desc->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; @@ -970,11 +911,9 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, } else { - lhq.key = njs_str_value("get"); - lhq.key_hash = NJS_GET_HASH; + lhq.key_hash = NJS_ATOM_STRING_get; - pr = njs_object_prop_alloc(vm, &njs_object_get_string, - &njs_value_undefined, 1); + pr = njs_object_prop_alloc(vm, &njs_value_undefined, 1); if (njs_slow_path(pr == NULL)) { return NJS_ERROR; } @@ -985,17 +924,15 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, lhq.value = pr; - ret = njs_lvlhsh_insert(&desc->hash, &lhq); + ret = njs_flathsh_unique_insert(&desc->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; } - lhq.key = njs_str_value("set"); - lhq.key_hash = NJS_SET_HASH; + lhq.key_hash = NJS_ATOM_STRING_set; - pr = njs_object_prop_alloc(vm, &njs_object_set_string, - &njs_value_undefined, 1); + pr = njs_object_prop_alloc(vm, &njs_value_undefined, 1); if (njs_slow_path(pr == NULL)) { return NJS_ERROR; } @@ -1006,44 +943,42 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, lhq.value = pr; - ret = njs_lvlhsh_insert(&desc->hash, &lhq); + ret = njs_flathsh_unique_insert(&desc->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; } } - lhq.key = njs_str_value("enumerable"); - lhq.key_hash = NJS_ENUMERABLE_HASH; + lhq.key_hash = NJS_ATOM_STRING_enumerable; setval = (prop->enumerable == 1) ? &njs_value_true : &njs_value_false; - pr = njs_object_prop_alloc(vm, &njs_object_enumerable_string, setval, 1); + pr = njs_object_prop_alloc(vm, setval, 1); if (njs_slow_path(pr == NULL)) { return NJS_ERROR; } lhq.value = pr; - ret = njs_lvlhsh_insert(&desc->hash, &lhq); + ret = njs_flathsh_unique_insert(&desc->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; } - lhq.key = njs_str_value("configurable"); - lhq.key_hash = NJS_CONFIGURABLE_HASH; + lhq.key_hash = NJS_ATOM_STRING_configurable; setval = (prop->configurable == 1) ? &njs_value_true : &njs_value_false; - pr = njs_object_prop_alloc(vm, &njs_object_configurable_string, setval, 1); + pr = njs_object_prop_alloc(vm, setval, 1); if (njs_slow_path(pr == NULL)) { return NJS_ERROR; } lhq.value = pr; - ret = njs_lvlhsh_insert(&desc->hash, &lhq); + ret = njs_flathsh_unique_insert(&desc->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; @@ -1080,12 +1015,13 @@ njs_prop_type_string(njs_object_prop_type_t type) njs_int_t njs_object_prop_init(njs_vm_t *vm, const njs_object_init_t* init, - const njs_object_prop_t *base, njs_value_t *value, njs_value_t *retval) + njs_object_prop_t *base, uint32_t atom_id, njs_value_t *value, + njs_value_t *retval) { - njs_int_t ret; - njs_object_t *object; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_object_t *object; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; object = njs_object_alloc(vm); if (object == NULL) { @@ -1110,14 +1046,13 @@ njs_object_prop_init(njs_vm_t *vm, const njs_object_init_t* init, prop->type = NJS_PROPERTY; njs_set_object(njs_prop_value(prop), object); - lhq.proto = &njs_object_hash_proto; - njs_string_get(&prop->name, &lhq.key); - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); lhq.value = prop; + lhq.key_hash = atom_id; lhq.replace = 1; lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(njs_object_hash(value), &lhq); + ret = njs_flathsh_unique_insert(njs_object_hash(value), &lhq); if (njs_fast_path(ret == NJS_OK)) { njs_value_assign(retval, njs_prop_value(prop)); return NJS_OK; diff --git a/src/njs_object_prop_declare.h b/src/njs_object_prop_declare.h index ecc0801c..f2f7a5eb 100644 --- a/src/njs_object_prop_declare.h +++ b/src/njs_object_prop_declare.h @@ -9,23 +9,14 @@ #define NJS_DECLARE_PROP_VALUE(_name, _v, _fl) \ { \ - .type = NJS_PROPERTY, \ - .name = njs_string(_name), \ - .u.value = _v, \ - .enumerable = !!(_fl & NJS_OBJECT_PROP_ENUMERABLE), \ - .configurable = !!(_fl & NJS_OBJECT_PROP_CONFIGURABLE), \ - .writable = !!(_fl & NJS_OBJECT_PROP_WRITABLE), \ - } - - -#define NJS_DECLARE_PROP_LVALUE(_name, _v, _fl) \ - { \ - .type = NJS_PROPERTY, \ - .name = njs_long_string(_name), \ - .u.value = _v, \ - .enumerable = !!(_fl & NJS_OBJECT_PROP_ENUMERABLE), \ - .configurable = !!(_fl & NJS_OBJECT_PROP_CONFIGURABLE), \ - .writable = !!(_fl & NJS_OBJECT_PROP_WRITABLE), \ + .atom_id = NJS_ATOM_ ## _name, \ + .desc = { \ + .type = NJS_PROPERTY, \ + .u.value = _v, \ + .enumerable = !!(_fl & NJS_OBJECT_PROP_ENUMERABLE), \ + .configurable = !!(_fl & NJS_OBJECT_PROP_CONFIGURABLE), \ + .writable = !!(_fl & NJS_OBJECT_PROP_WRITABLE), \ + }, \ } @@ -35,39 +26,39 @@ NJS_OBJECT_PROP_VALUE_CW) -#define NJS_DECLARE_PROP_LNATIVE(_name, _native, _nargs, _magic) \ - NJS_DECLARE_PROP_LVALUE(_name, \ - njs_native_function2(_native, _nargs, _magic), \ - NJS_OBJECT_PROP_VALUE_CW) - - -#define NJS_DECLARE_PROP_HANDLER(_name, _native, _m16, _m32, _fl) \ +#define NJS_DECLARE_PROP_HANDLER(_name, _native, _m16, _fl) \ { \ - .type = NJS_PROPERTY_HANDLER, \ - .name = njs_string(_name), \ - .u.value = njs_prop_handler2(_native, _m16, _m32), \ - .enumerable = !!(_fl & NJS_OBJECT_PROP_ENUMERABLE), \ - .configurable = !!(_fl & NJS_OBJECT_PROP_CONFIGURABLE), \ - .writable = !!(_fl & NJS_OBJECT_PROP_WRITABLE), \ + .atom_id = NJS_ATOM_ ## _name, \ + .desc = { \ + .type = NJS_PROPERTY_HANDLER, \ + .u.value = njs_prop_handler2(_native, _m16), \ + .enumerable = !!(_fl & NJS_OBJECT_PROP_ENUMERABLE), \ + .configurable = !!(_fl & NJS_OBJECT_PROP_CONFIGURABLE), \ + .writable = !!(_fl & NJS_OBJECT_PROP_WRITABLE), \ + }, \ } #define NJS_DECLARE_PROP_GETTER(_name, _native, _magic) \ { \ - .type = NJS_ACCESSOR, \ - .name = njs_string(_name), \ - .u.accessor = njs_getter(_native, _magic), \ - .writable = NJS_ATTRIBUTE_UNSET, \ - .configurable = 1, \ + .atom_id = NJS_ATOM_ ## _name, \ + .desc = { \ + .type = NJS_ACCESSOR, \ + .u.accessor = njs_getter(_native, _magic), \ + .writable = NJS_ATTRIBUTE_UNSET, \ + .configurable = 1, \ + }, \ } #define NJS_DECLARE_PROP_NAME(_name) \ - NJS_DECLARE_PROP_VALUE("name", njs_string(_name), NJS_OBJECT_PROP_VALUE_C) + NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval(_name), \ + NJS_OBJECT_PROP_VALUE_C) #define NJS_DECLARE_PROP_LENGTH(_v) \ - NJS_DECLARE_PROP_VALUE("length", njs_value(NJS_NUMBER, !!(_v), _v), \ + NJS_DECLARE_PROP_VALUE(STRING_length, \ + njs_value(NJS_NUMBER, !!(_v), _v), \ NJS_OBJECT_PROP_VALUE_C) diff --git a/src/njs_parser.c b/src/njs_parser.c index 7fe596c2..a3564396 100644 --- a/src/njs_parser.c +++ b/src/njs_parser.c @@ -451,7 +451,7 @@ static njs_int_t njs_parser_export_sink(njs_parser_t *parser); static njs_parser_node_t *njs_parser_return_set(njs_parser_t *parser, njs_parser_node_t *expr); static njs_parser_node_t *njs_parser_variable_node(njs_parser_t *parser, - uintptr_t unique_id, njs_variable_type_t type, njs_variable_t **retvar); + uintptr_t atom_id, njs_variable_type_t type, njs_variable_t **retvar); static njs_parser_node_t *njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token); @@ -529,7 +529,7 @@ njs_parser_reject(njs_parser_t *parser) njs_int_t njs_parser_init(njs_vm_t *vm, njs_parser_t *parser, njs_parser_scope_t *scope, - njs_str_t *file, u_char *start, u_char *end, njs_uint_t runtime) + njs_str_t *file, u_char *start, u_char *end) { njs_lexer_t *lexer; @@ -542,17 +542,15 @@ njs_parser_init(njs_vm_t *vm, njs_parser_t *parser, njs_parser_scope_t *scope, parser->use_lhs = 0; - return njs_lexer_init(vm, lexer, file, start, end, runtime, 0); + return njs_lexer_init(vm, lexer, file, start, end); } njs_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser) { - njs_int_t ret; - njs_str_t str; - njs_lexer_token_t *token; - const njs_lexer_keyword_entry_t *keyword; + njs_int_t ret; + njs_lexer_token_t *token; parser->vm = vm; @@ -572,16 +570,6 @@ njs_parser(njs_vm_t *vm, njs_parser_t *parser) parser->ret = NJS_OK; } - /* Add this as first variable. */ - njs_string_get(&njs_string_undefined, &str); - - keyword = njs_lexer_keyword(str.start, str.length); - if (njs_slow_path(keyword == NULL)) { - return NJS_ERROR; - } - - parser->undefined_id = (uintptr_t) keyword->value; - njs_queue_init(&parser->stack); parser->target = NULL; @@ -665,11 +653,8 @@ static njs_int_t njs_parser_scope_begin(njs_parser_t *parser, njs_scope_t type, njs_bool_t init_this) { - njs_variable_t *var; - njs_parser_scope_t *scope, *parent; - const njs_lexer_keyword_entry_t *keyword; - - static const njs_str_t njs_this_str = njs_str("this"); + njs_variable_t *var; + njs_parser_scope_t *scope, *parent; scope = njs_mp_zalloc(parser->vm->mem_pool, sizeof(njs_parser_scope_t)); if (njs_slow_path(scope == NULL)) { @@ -689,13 +674,7 @@ njs_parser_scope_begin(njs_parser_t *parser, njs_scope_t type, if (type == NJS_SCOPE_FUNCTION || type == NJS_SCOPE_GLOBAL) { if (init_this) { /* Add this as first variable. */ - keyword = njs_lexer_keyword(njs_this_str.start, - njs_this_str.length); - if (njs_slow_path(keyword == NULL)) { - return NJS_ERROR; - } - - var = njs_variable_add(parser, scope, (uintptr_t) keyword->value, + var = njs_variable_add(parser, scope, NJS_ATOM_STRING_this, NJS_VARIABLE_VAR); if (njs_slow_path(var == NULL)) { return NJS_ERROR; @@ -1004,6 +983,13 @@ njs_parser_primary_expression_test(njs_parser_t *parser, } njs_set_number(&node->u.value, token->number); + + if (njs_number_is_integer_index(token->number) + && token->number < 0x80000000) + { + node->u.value.atom_id = njs_number_atom((uint32_t) token->number); + } + node->token_line = token->line; parser->node = node; @@ -1207,6 +1193,8 @@ reference: return NJS_ERROR; } + node->u.value.atom_id = token->atom_id; + node->token_line = token->line; parser->node = node; @@ -1230,8 +1218,6 @@ njs_parser_regexp_literal(njs_parser_t *parser, njs_lexer_token_t *token, njs_regex_flags_t flags; njs_regexp_pattern_t *pattern; - static const njs_value_t string_message = njs_string("message"); - value = &parser->node->u.value; lexer = parser->lexer; @@ -1302,13 +1288,12 @@ njs_parser_regexp_literal(njs_parser_t *parser, njs_lexer_token_t *token, if (njs_slow_path(pattern == NULL)) { retval = njs_vm_exception(parser->vm); ret = njs_value_property(parser->vm, &retval, - njs_value_arg(&string_message), - &retval); + NJS_ATOM_STRING_message, &retval); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - njs_string_get(&retval, &text); + njs_string_get(parser->vm, &retval, &text); njs_parser_syntax_error(parser, "%V", &text); @@ -2087,7 +2072,7 @@ njs_parser_property_definition_after(njs_parser_t *parser, if (property->index != NJS_TOKEN_OPEN_BRACKET && njs_is_string(&property->u.value)) { - njs_string_get(&property->u.value, &name); + njs_string_get(parser->vm, &property->u.value, &name); if (njs_slow_path(njs_strstr_eq(&name, &proto_string))) { if (temp->token_type == NJS_TOKEN_PROTO_INIT) { @@ -5092,7 +5077,7 @@ njs_parser_variable_declaration(njs_parser_t *parser, return NJS_DONE; } - name = njs_parser_variable_node(parser, token->unique_id, parser->var_type, + name = njs_parser_variable_node(parser, token->atom_id, parser->var_type, &var); if (name == NULL) { return NJS_ERROR; @@ -5879,8 +5864,7 @@ njs_parser_for_var_binding_or_var_list(njs_parser_t *parser, return NJS_ERROR; } - var = njs_parser_variable_node(parser, token->unique_id, - type, NULL); + var = njs_parser_variable_node(parser, token->atom_id, type, NULL); if (var == NULL) { return NJS_ERROR; } @@ -6257,8 +6241,8 @@ njs_parser_break_continue(njs_parser_t *parser, njs_lexer_token_t *token, return njs_parser_stack_pop(parser); } - if (njs_label_find(parser->vm, parser->scope, - token->unique_id) == NULL) + if (njs_label_find(parser->vm, parser->scope, token->atom_id) + == NULL) { njs_parser_syntax_error(parser, "Undefined label \"%V\"", &token->text); @@ -6671,19 +6655,19 @@ static njs_int_t njs_parser_labelled_statement(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { - uintptr_t unique_id; - njs_variable_t *label; + uintptr_t atom_id; + njs_variable_t *label; - unique_id = token->unique_id; + atom_id = token->atom_id; - label = njs_label_find(parser->vm, parser->scope, unique_id); + label = njs_label_find(parser->vm, parser->scope, atom_id); if (label != NULL) { njs_parser_syntax_error(parser, "Label \"%V\" " "has already been declared", &token->text); return NJS_DONE; } - label = njs_label_add(parser->vm, parser->scope, unique_id); + label = njs_label_add(parser->vm, parser->scope, atom_id); if (label == NULL) { return NJS_ERROR; } @@ -6706,7 +6690,7 @@ njs_parser_labelled_statement(njs_parser_t *parser, njs_lexer_token_t *token, njs_parser_next(parser, njs_parser_statement_wo_node); } - return njs_parser_after(parser, current, (void *) unique_id, 1, + return njs_parser_after(parser, current, (void *) atom_id, 1, njs_parser_labelled_statement_after); } @@ -6715,10 +6699,11 @@ static njs_int_t njs_parser_labelled_statement_after(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { - njs_int_t ret; - uintptr_t unique_id; - njs_parser_node_t *node; - const njs_lexer_entry_t *entry; + njs_int_t ret; + njs_str_t str; + uintptr_t atom_id; + njs_value_t entry; + njs_parser_node_t *node; node = parser->node; if (node == NULL) { @@ -6732,15 +6717,17 @@ njs_parser_labelled_statement_after(njs_parser_t *parser, parser->node = node; } - unique_id = (uintptr_t) parser->target; - entry = (const njs_lexer_entry_t *) unique_id; + atom_id = (uint32_t) (uintptr_t) parser->target; + + njs_atom_to_value(parser->vm, &entry, atom_id); + njs_string_get(parser->vm, &entry, &str); - ret = njs_name_copy(parser->vm, &parser->node->name, &entry->name); + ret = njs_name_copy(parser->vm, &parser->node->name, &str); if (ret != NJS_OK) { return NJS_ERROR; } - ret = njs_label_remove(parser->vm, parser->scope, unique_id); + ret = njs_label_remove(parser->vm, parser->scope, atom_id); if (ret != NJS_OK) { return NJS_ERROR; } @@ -6907,7 +6894,7 @@ njs_parser_catch_or_finally(njs_parser_t *parser, njs_lexer_token_t *token, try->right = catch; if (njs_lexer_token_is_binding_identifier(token)) { - node = njs_parser_variable_node(parser, token->unique_id, + node = njs_parser_variable_node(parser, token->atom_id, NJS_VARIABLE_CATCH, NULL); if (node == NULL) { return NJS_ERROR; @@ -7075,7 +7062,7 @@ njs_parser_function_declaration(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { njs_int_t ret; - uintptr_t unique_id; + uintptr_t atom_id; njs_bool_t async; njs_variable_t *var; njs_parser_node_t *node; @@ -7091,7 +7078,7 @@ njs_parser_function_declaration(njs_parser_t *parser, njs_lexer_token_t *token, } node = parser->node; - unique_id = token->unique_id; + atom_id = token->atom_id; njs_lexer_consume_token(parser->lexer, 1); @@ -7106,7 +7093,7 @@ njs_parser_function_declaration(njs_parser_t *parser, njs_lexer_token_t *token, njs_lexer_consume_token(parser->lexer, 1); - var = njs_variable_function_add(parser, parser->scope, unique_id, + var = njs_variable_function_add(parser, parser->scope, atom_id, NJS_VARIABLE_FUNCTION); if (var == NULL) { return NJS_ERROR; @@ -7114,7 +7101,7 @@ njs_parser_function_declaration(njs_parser_t *parser, njs_lexer_token_t *token, node->u.value.data.u.lambda = njs_variable_lambda(var); - node->left = (njs_parser_node_t *) unique_id; + node->left = (njs_parser_node_t *) atom_id; parser->node = node; @@ -7138,16 +7125,16 @@ njs_parser_function_declaration_after(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { njs_int_t ret; - uintptr_t unique_id; + uintptr_t atom_id; - unique_id = (uintptr_t) parser->node->left; + atom_id = (uint32_t) (uintptr_t) parser->node->left; parser->node->left = NULL; njs_value_null_set(&parser->node->u.value); ret = njs_parser_variable_reference(parser, parser->scope, parser->node, - unique_id, NJS_DECLARATION); + atom_id, NJS_DECLARATION); if (ret != NJS_OK) { return NJS_ERROR; } @@ -7170,18 +7157,12 @@ njs_parser_function_parse(njs_parser_t *parser, njs_lexer_token_t *token, } -static const njs_lexer_entry_t njs_parser_empty_entry = -{ - .name = njs_str("") -}; - - static njs_int_t njs_parser_function_expression(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { njs_int_t ret; - uintptr_t unique_id; + uintptr_t atom_id; njs_bool_t async; njs_variable_t *var; njs_function_lambda_t *lambda; @@ -7197,7 +7178,7 @@ njs_parser_function_expression(njs_parser_t *parser, njs_lexer_token_t *token, var = NULL; if (njs_lexer_token_is_binding_identifier(token)) { - unique_id = token->unique_id; + atom_id = token->atom_id; njs_lexer_consume_token(parser->lexer, 1); @@ -7207,7 +7188,7 @@ njs_parser_function_expression(njs_parser_t *parser, njs_lexer_token_t *token, } } else { - unique_id = (uintptr_t) &njs_parser_empty_entry; + atom_id = NJS_ATOM_STRING_empty; } if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) { @@ -7222,7 +7203,7 @@ njs_parser_function_expression(njs_parser_t *parser, njs_lexer_token_t *token, } var = njs_variable_scope_add(parser, parser->scope, parser->scope, - unique_id, NJS_VARIABLE_FUNCTION, 1); + atom_id, NJS_VARIABLE_FUNCTION, 1); if (var == NULL) { return NJS_ERROR; } @@ -7230,7 +7211,7 @@ njs_parser_function_expression(njs_parser_t *parser, njs_lexer_token_t *token, var->self = 1; ret = njs_parser_variable_reference(parser, parser->scope, - parser->node->left, unique_id, + parser->node->left, atom_id, NJS_DECLARATION); if (ret != NJS_OK) { return NJS_ERROR; @@ -7330,7 +7311,7 @@ njs_parser_formal_parameters(njs_parser_t *parser, njs_lexer_token_t *token, default: /* SingleNameBinding */ if (njs_lexer_token_is_binding_identifier(token)) { - var_node.key = token->unique_id; + var_node.key = token->atom_id; rb_node = njs_rbtree_find(&parser->scope->variables, &var_node.node); @@ -7347,7 +7328,7 @@ njs_parser_formal_parameters(njs_parser_t *parser, njs_lexer_token_t *token, } else { arg = njs_variable_add(parser, parser->scope, - token->unique_id, NJS_VARIABLE_VAR); + token->atom_id, NJS_VARIABLE_VAR); } if (arg == NULL) { @@ -7410,7 +7391,6 @@ njs_parser_arrow_function(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { njs_int_t ret; - uintptr_t unique_id; njs_bool_t async; njs_variable_t *arg, *var; njs_parser_node_t *node, *name; @@ -7453,16 +7433,15 @@ njs_parser_arrow_function(njs_parser_t *parser, njs_lexer_token_t *token, node->left = name; - unique_id = (uintptr_t) &njs_parser_empty_entry; - var = njs_variable_scope_add(parser, parser->scope, parser->scope, - unique_id, NJS_VARIABLE_FUNCTION, 1); + NJS_ATOM_STRING_empty, NJS_VARIABLE_FUNCTION, + 1); if (var == NULL) { return NJS_ERROR; } ret = njs_parser_variable_reference(parser, parser->scope, node->left, - unique_id, NJS_DECLARATION); + NJS_ATOM_STRING_empty, NJS_DECLARATION); if (ret != NJS_OK) { return NJS_ERROR; } @@ -7490,7 +7469,7 @@ njs_parser_arrow_function(njs_parser_t *parser, njs_lexer_token_t *token, njs_parser_arrow_function_args_after); } else if (njs_lexer_token_is_binding_identifier(token)) { - arg = njs_variable_add(parser, parser->scope, token->unique_id, + arg = njs_variable_add(parser, parser->scope, token->atom_id, NJS_VARIABLE_VAR); if (arg == NULL) { return NJS_ERROR; @@ -8189,7 +8168,7 @@ njs_parser_import(njs_parser_t *parser, njs_lexer_token_t *token, return njs_parser_failed(parser); } - name = njs_parser_variable_node(parser, token->unique_id, NJS_VARIABLE_LET, + name = njs_parser_variable_node(parser, token->atom_id, NJS_VARIABLE_LET, &var); if (name == NULL) { return NJS_ERROR; @@ -8337,14 +8316,14 @@ njs_parser_return_set(njs_parser_t *parser, njs_parser_node_t *expr) static njs_parser_node_t * -njs_parser_variable_node(njs_parser_t *parser, uintptr_t unique_id, +njs_parser_variable_node(njs_parser_t *parser, uintptr_t atom_id, njs_variable_type_t type, njs_variable_t **retvar) { njs_int_t ret; njs_variable_t *var; njs_parser_node_t *node; - var = njs_variable_add(parser, parser->scope, unique_id, type); + var = njs_variable_add(parser, parser->scope, atom_id, type); if (njs_slow_path(var == NULL)) { return NULL; } @@ -8358,7 +8337,7 @@ njs_parser_variable_node(njs_parser_t *parser, uintptr_t unique_id, return NULL; } - ret = njs_parser_variable_reference(parser, parser->scope, node, unique_id, + ret = njs_parser_variable_reference(parser, parser->scope, node, atom_id, NJS_DECLARATION); if (njs_slow_path(ret != NJS_OK)) { return NULL; @@ -8371,14 +8350,11 @@ njs_parser_variable_node(njs_parser_t *parser, uintptr_t unique_id, static njs_parser_node_t * njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token) { - njs_int_t ret; - njs_index_t index; - njs_variable_t *var; - njs_parser_node_t *node; - njs_parser_scope_t *scope; - const njs_lexer_keyword_entry_t *keyword; - - static const njs_str_t njs_undefined_str = njs_str("undefined"); + njs_int_t ret; + njs_index_t index; + njs_variable_t *var; + njs_parser_node_t *node; + njs_parser_scope_t *scope; node = njs_parser_node_new(parser, token->type); if (njs_slow_path(node == NULL)) { @@ -8402,19 +8378,13 @@ njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token) } if (parser->vm->options.module) { - keyword = njs_lexer_keyword(njs_undefined_str.start, - njs_undefined_str.length); - if (njs_slow_path(keyword == NULL)) { - return NULL; - } - - token->unique_id = (uintptr_t) keyword->value; + token->atom_id = NJS_ATOM_STRING_undefined; } else if (!scope->arrow_function) { index = njs_scope_index(scope->type, 0, NJS_LEVEL_LOCAL, NJS_VARIABLE_VAR); - var = njs_variable_scope_add(parser, scope, scope, token->unique_id, + var = njs_variable_scope_add(parser, scope, scope, token->atom_id, NJS_VARIABLE_VAR, index); if (njs_slow_path(var == NULL)) { return NULL; @@ -8425,7 +8395,7 @@ njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token) node->token_line = token->line; ret = njs_parser_variable_reference(parser, parser->scope, node, - token->unique_id, NJS_REFERENCE); + token->atom_id, NJS_REFERENCE); if (njs_slow_path(ret != NJS_OK)) { return NULL; } @@ -8450,12 +8420,12 @@ njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token) node->token_line = token->line; ret = njs_parser_variable_reference(parser, parser->scope, node, - token->unique_id, NJS_REFERENCE); + token->atom_id, NJS_REFERENCE); if (njs_slow_path(ret != NJS_OK)) { return NULL; } - var = njs_variable_add(parser, scope, token->unique_id, + var = njs_variable_add(parser, scope, token->atom_id, NJS_VARIABLE_VAR); if (njs_slow_path(var == NULL)) { return NULL; @@ -8478,7 +8448,7 @@ njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token) node->token_line = token->line; ret = njs_parser_variable_reference(parser, parser->scope, node, - token->unique_id, NJS_REFERENCE); + token->atom_id, NJS_REFERENCE); if (njs_slow_path(ret != NJS_OK)) { return NULL; } @@ -8735,6 +8705,7 @@ njs_parser_string_create(njs_vm_t *vm, njs_lexer_token_t *token, njs_value_t *value) { size_t length; + njs_int_t ret; njs_str_t dst; length = njs_decode_utf8_length(&token->text, &dst.length); @@ -8746,10 +8717,15 @@ njs_parser_string_create(njs_vm_t *vm, njs_lexer_token_t *token, njs_decode_utf8(&dst, &token->text); if (length > NJS_STRING_MAP_STRIDE && dst.length != length) { - njs_string_utf8_offset_map_init(value->long_string.data->start, + njs_string_utf8_offset_map_init(value->string.data->start, dst.length); } + ret = njs_atom_atomize_key(vm, value); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_TOKEN_ERROR; + } + return NJS_OK; } @@ -8994,6 +8970,11 @@ next_char: njs_string_utf8_offset_map_init(start, size); } + ret = njs_atom_atomize_key(parser->vm, value); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_TOKEN_ERROR; + } + return NJS_TOKEN_STRING; } @@ -9183,7 +9164,7 @@ njs_parser_has_side_effect(njs_parser_node_t *node) njs_int_t njs_parser_variable_reference(njs_parser_t *parser, njs_parser_scope_t *scope, - njs_parser_node_t *node, uintptr_t unique_id, njs_reference_type_t type) + njs_parser_node_t *node, uintptr_t atom_id, njs_reference_type_t type) { njs_rbtree_node_t *rb_node; njs_variable_reference_t *vr; @@ -9191,10 +9172,10 @@ njs_parser_variable_reference(njs_parser_t *parser, njs_parser_scope_t *scope, vr = &node->u.reference; - vr->unique_id = unique_id; + vr->atom_id = atom_id; vr->type = type; - parse_node.key = unique_id; + parse_node.key = atom_id; rb_node = njs_rbtree_find(&scope->references, &parse_node.node); if (rb_node != NULL) { @@ -9207,7 +9188,7 @@ njs_parser_variable_reference(njs_parser_t *parser, njs_parser_scope_t *scope, return NJS_ERROR; } - rb_parse_node->key = unique_id; + rb_parse_node->key = atom_id; rb_parse_node->index = NJS_INDEX_NONE; njs_rbtree_insert(&scope->references, &rb_parse_node->node); @@ -9241,9 +9222,6 @@ njs_parser_error(njs_vm_t *vm, njs_object_type_t type, njs_str_t *file, njs_int_t ret; njs_value_t value, error; - static const njs_value_t file_name = njs_string("fileName"); - static const njs_value_t line_number = njs_string("lineNumber"); - if (njs_slow_path(vm->top_frame == NULL)) { njs_vm_runtime_init(vm); } @@ -9269,13 +9247,12 @@ njs_parser_error(njs_vm_t *vm, njs_object_type_t type, njs_str_t *file, njs_error_new(vm, &error, njs_vm_proto(vm, type), msg, p - msg); njs_set_number(&value, line); - njs_value_property_set(vm, &error, njs_value_arg(&line_number), &value); + njs_value_property_set(vm, &error, NJS_ATOM_STRING_lineNumber, &value); if (file->length != 0) { ret = njs_string_create(vm, &value, file->start, file->length); if (ret == NJS_OK) { - njs_value_property_set(vm, &error, njs_value_arg(&file_name), - &value); + njs_value_property_set(vm, &error, NJS_ATOM_STRING_fileName, &value); } } @@ -9440,7 +9417,7 @@ njs_parser_serialize_tree(njs_chb_t *chain, njs_parser_node_t *node, njs_number(&node->u.value)); } else { - njs_string_get(&node->u.value, &str); + njs_string_get_unsafe(&node->u.value, &str); njs_chb_append_literal(chain, " \"value\": \""); njs_chb_append_str(chain, &str); njs_chb_append_literal(chain, "\""); diff --git a/src/njs_parser.h b/src/njs_parser.h index db4db02d..2f7cff79 100644 --- a/src/njs_parser.h +++ b/src/njs_parser.h @@ -80,7 +80,6 @@ struct njs_parser_s { njs_parser_scope_t *scope; njs_variable_type_t var_type; njs_int_t ret; - uintptr_t undefined_id; uint8_t use_lhs; @@ -125,8 +124,7 @@ njs_int_t njs_parser_failed_state(njs_parser_t *parser, intptr_t njs_parser_scope_rbtree_compare(njs_rbtree_node_t *node1, njs_rbtree_node_t *node2); njs_int_t njs_parser_init(njs_vm_t *vm, njs_parser_t *parser, - njs_parser_scope_t *scope, njs_str_t *file, u_char *start, u_char *end, - njs_uint_t runtime); + njs_parser_scope_t *scope, njs_str_t *file, u_char *start, u_char *end); njs_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser); njs_bool_t njs_variable_closure_test(njs_parser_scope_t *root, @@ -135,7 +133,7 @@ njs_variable_t *njs_variable_resolve(njs_vm_t *vm, njs_parser_node_t *node); njs_index_t njs_variable_index(njs_vm_t *vm, njs_parser_node_t *node); njs_bool_t njs_parser_has_side_effect(njs_parser_node_t *node); njs_int_t njs_parser_variable_reference(njs_parser_t *parser, - njs_parser_scope_t *scope, njs_parser_node_t *node, uintptr_t unique_id, + njs_parser_scope_t *scope, njs_parser_node_t *node, uintptr_t atom_id, njs_reference_type_t type); njs_token_type_t njs_parser_unexpected_token(njs_vm_t *vm, njs_parser_t *parser, njs_str_t *name, njs_token_type_t type); diff --git a/src/njs_promise.c b/src/njs_promise.c index 79b93a11..f8951cca 100644 --- a/src/njs_promise.c +++ b/src/njs_promise.c @@ -105,11 +105,6 @@ static njs_int_t njs_promise_perform_race_handler(njs_vm_t *vm, njs_value_t *retval); -static const njs_value_t string_resolve = njs_string("resolve"); -static const njs_value_t string_any_rejected = - njs_long_string("All promises were rejected"); - - static njs_promise_t * njs_promise_alloc(njs_vm_t *vm) { @@ -391,15 +386,12 @@ njs_promise_value_constructor(njs_vm_t *vm, njs_value_t *value, { njs_int_t ret; - static const njs_value_t string_constructor = njs_string("constructor"); - if (njs_is_function(value)) { *dst = *value; return NJS_OK; } - ret = njs_value_property(vm, value, njs_value_arg(&string_constructor), - dst); + ret = njs_value_property(vm, value, NJS_ATOM_STRING_constructor, dst); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -552,10 +544,7 @@ njs_promise_invoke_then(njs_vm_t *vm, njs_value_t *promise, njs_value_t *args, njs_int_t ret; njs_value_t function; - static const njs_value_t string_then = njs_string("then"); - - ret = njs_value_property(vm, promise, njs_value_arg(&string_then), - &function); + ret = njs_value_property(vm, promise, NJS_ATOM_STRING_then, &function); if (njs_slow_path(ret != NJS_OK)) { if (ret == NJS_DECLINED) { goto failed; @@ -588,8 +577,6 @@ njs_promise_resolve_function(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_native_frame_t *active_frame; njs_promise_context_t *context; - static const njs_value_t string_then = njs_string("then"); - active_frame = vm->top_frame; context = active_frame->function->context; promise = njs_promise(&context->promise); @@ -603,7 +590,7 @@ njs_promise_resolve_function(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, resolution = njs_arg(args, nargs, 1); - if (njs_values_same(resolution, &context->promise)) { + if (njs_values_same(vm, resolution, &context->promise)) { njs_error_fmt_new(vm, &error, NJS_OBJ_TYPE_TYPE_ERROR, "promise self resolution"); if (njs_slow_path(!njs_is_error(&error))) { @@ -619,8 +606,7 @@ njs_promise_resolve_function(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto fulfill; } - ret = njs_value_property(vm, resolution, njs_value_arg(&string_then), - &then); + ret = njs_value_property(vm, resolution, NJS_ATOM_STRING_then, &then); if (njs_slow_path(ret == NJS_ERROR)) { if (njs_slow_path(njs_is_memory_error(vm, &vm->exception))) { return NJS_ERROR; @@ -693,16 +679,13 @@ njs_promise_resolve(njs_vm_t *vm, njs_value_t *constructor, njs_value_t *x, njs_value_t value; njs_promise_capability_t *capability; - static const njs_value_t string_constructor = njs_string("constructor"); - if (njs_is_promise(x)) { - ret = njs_value_property(vm, x, njs_value_arg(&string_constructor), - &value); + ret = njs_value_property(vm, x, NJS_ATOM_STRING_constructor, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } - if (njs_values_same(&value, constructor)) { + if (njs_values_same(vm, &value, constructor)) { njs_value_assign(retval, x); return NJS_OK; } @@ -1173,7 +1156,7 @@ njs_promise_all(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - ret = njs_value_property(vm, promise_ctor, njs_value_arg(&string_resolve), + ret = njs_value_property(vm, promise_ctor, NJS_ATOM_STRING_resolve, &resolve); if (njs_slow_path(ret == NJS_ERROR)) { return ret; @@ -1213,7 +1196,7 @@ njs_promise_perform_all(njs_vm_t *vm, njs_value_t *iterator, { int64_t length; njs_int_t ret; - njs_value_t argument; + njs_value_t argument, message; njs_object_t *error; if (njs_slow_path(!njs_is_object(pargs->constructor))) { @@ -1253,11 +1236,13 @@ njs_promise_perform_all(njs_vm_t *vm, njs_value_t *iterator, njs_mp_free(vm->mem_pool, pargs->remaining); njs_set_array(&argument, pargs->args.data); + njs_atom_to_value(vm, &message, + NJS_ATOM_STRING_All_promises_were_rejected); if (handler == njs_promise_perform_any_handler) { error = njs_error_alloc(vm, njs_vm_proto(vm, NJS_OBJ_TYPE_AGGREGATE_ERROR), - NULL, &string_any_rejected, &argument); + NULL, &message, &argument); if (njs_slow_path(error == NULL)) { return NJS_ERROR; } @@ -1467,17 +1452,12 @@ njs_promise_all_settled_element_functions(njs_vm_t *vm, njs_value_t *retval) { njs_int_t ret; + uint32_t set_atom_id; + njs_value_t status; njs_value_t obj_value, arr_value; njs_object_t *obj; - const njs_value_t *status, *set; njs_promise_all_context_t *context; - static const njs_value_t string_status = njs_string("status"); - static const njs_value_t string_fulfilled = njs_string("fulfilled"); - static const njs_value_t string_value = njs_string("value"); - static const njs_value_t string_rejected = njs_string("rejected"); - static const njs_value_t string_reason = njs_string("reason"); - context = vm->top_frame->function->context; if (context->already_called) { @@ -1495,21 +1475,21 @@ njs_promise_all_settled_element_functions(njs_vm_t *vm, njs_set_object(&obj_value, obj); if (rejected) { - status = &string_rejected; - set = &string_reason; + njs_atom_to_value(vm, &status, NJS_ATOM_STRING_rejected); + set_atom_id = NJS_ATOM_STRING_reason; } else { - status = &string_fulfilled; - set = &string_value; + njs_atom_to_value(vm, &status, NJS_ATOM_STRING_fulfilled); + set_atom_id = NJS_ATOM_STRING_value; } - ret = njs_value_property_set(vm, &obj_value, njs_value_arg(&string_status), - njs_value_arg(status)); + ret = njs_value_property_set(vm, &obj_value, NJS_ATOM_STRING_status, + njs_value_arg(&status)); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } - ret = njs_value_property_set(vm, &obj_value, njs_value_arg(set), + ret = njs_value_property_set(vm, &obj_value, set_atom_id, njs_arg(args, nargs, 1)); if (njs_slow_path(ret == NJS_ERROR)) { return ret; @@ -1609,7 +1589,7 @@ njs_promise_any_reject_element_functions(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { njs_int_t ret; - njs_value_t argument, arr_value; + njs_value_t argument, message, arr_value; njs_object_t *error; njs_promise_all_context_t *context; @@ -1633,9 +1613,12 @@ njs_promise_any_reject_element_functions(njs_vm_t *vm, njs_value_t *args, if (--(*context->remaining_elements) == 0) { njs_mp_free(vm->mem_pool, context->remaining_elements); + njs_atom_to_value(vm, &message, + NJS_ATOM_STRING_All_promises_were_rejected); + error = njs_error_alloc(vm, njs_vm_proto(vm, NJS_OBJ_TYPE_AGGREGATE_ERROR), - NULL, &string_any_rejected, &arr_value); + NULL, &message, &arr_value); if (njs_slow_path(error == NULL)) { return NJS_ERROR; } @@ -1670,7 +1653,7 @@ njs_promise_race(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - ret = njs_value_property(vm, promise_ctor, njs_value_arg(&string_resolve), + ret = njs_value_property(vm, promise_ctor, NJS_ATOM_STRING_resolve, &resolve); if (njs_slow_path(ret == NJS_ERROR)) { return ret; @@ -1748,34 +1731,32 @@ njs_promise_species(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_object_prop_t njs_promise_constructor_properties[] = +static const njs_object_prop_init_t njs_promise_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("Promise"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_NATIVE("resolve", njs_promise_object_resolve, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_resolve, njs_promise_object_resolve, 1, + 0), - NJS_DECLARE_PROP_NATIVE("reject", njs_promise_object_reject, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_reject, njs_promise_object_reject, 1, 0), - NJS_DECLARE_PROP_NATIVE("all", njs_promise_all, 1, NJS_PROMISE_ALL), + NJS_DECLARE_PROP_NATIVE(STRING_all, njs_promise_all, 1, + NJS_PROMISE_ALL), - NJS_DECLARE_PROP_NATIVE("allSettled", njs_promise_all, 1, + NJS_DECLARE_PROP_NATIVE(STRING_allSettled, njs_promise_all, 1, NJS_PROMISE_ALL_SETTLED), - NJS_DECLARE_PROP_NATIVE("any", njs_promise_all, 1, NJS_PROMISE_ANY), + NJS_DECLARE_PROP_NATIVE(STRING_any, njs_promise_all, 1, + NJS_PROMISE_ANY), - NJS_DECLARE_PROP_NATIVE("race", njs_promise_race, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_race, njs_promise_race, 1, 0), - { - .type = NJS_ACCESSOR, - .name = njs_wellknown_symbol(NJS_SYMBOL_SPECIES), - .u.accessor = njs_getter(njs_promise_species, 0), - .writable = NJS_ATTRIBUTE_UNSET, - .configurable = 1, - }, + NJS_DECLARE_PROP_GETTER(SYMBOL_species, njs_promise_species, 0), }; @@ -1785,24 +1766,22 @@ const njs_object_init_t njs_promise_constructor_init = { }; -static const njs_object_prop_t njs_promise_prototype_properties[] = +static const njs_object_prop_init_t njs_promise_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.value = njs_string("Promise"), - .configurable = 1, - }, + NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, njs_ascii_strval("Promise"), + NJS_OBJECT_PROP_VALUE_C), - NJS_DECLARE_PROP_NATIVE("then", njs_promise_prototype_then, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_then, njs_promise_prototype_then, 2, 0), - NJS_DECLARE_PROP_NATIVE("catch", njs_promise_prototype_catch, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_catch, njs_promise_prototype_catch, 1, + 0), - NJS_DECLARE_PROP_NATIVE("finally", njs_promise_prototype_finally, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_finally, njs_promise_prototype_finally, + 1, 0), }; diff --git a/src/njs_regexp.c b/src/njs_regexp.c index 479f0b75..4f1bb180 100644 --- a/src/njs_regexp.c +++ b/src/njs_regexp.c @@ -32,9 +32,6 @@ static njs_array_t *njs_regexp_exec_result(njs_vm_t *vm, njs_value_t *r, njs_utf8_t utf8, njs_string_prop_t *string, njs_regex_match_data_t *data); -const njs_value_t njs_string_lindex = njs_string("lastIndex"); - - njs_int_t njs_regexp_init(njs_vm_t *vm) { @@ -134,9 +131,6 @@ njs_regexp_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, if (njs_slow_path(ret != NJS_OK)) { return ret; } - - } else { - pattern = njs_value_arg(&njs_string_empty); } re_flags = 0; @@ -150,7 +144,7 @@ njs_regexp_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - njs_string_get(flags, &string); + njs_string_get(vm, flags, &string); start = string.start; @@ -163,7 +157,12 @@ njs_regexp_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - njs_string_get(pattern, &string); + if (njs_is_defined(pattern)) { + njs_string_get(vm, pattern, &string); + + } else { + string = njs_str_value(""); + } return njs_regexp_create(vm, retval, string.start, string.length, re_flags); @@ -513,7 +512,7 @@ njs_regexp_alloc(njs_vm_t *vm, njs_regexp_pattern_t *pattern) regexp->object.error_data = 0; njs_set_number(®exp->last_index, 0); regexp->pattern = pattern; - njs_string_short_set(®exp->string, 0, 0); + njs_set_empty_string(vm, ®exp->string); return regexp; } @@ -525,7 +524,8 @@ njs_regexp_alloc(njs_vm_t *vm, njs_regexp_pattern_t *pattern) static njs_int_t njs_regexp_prototype_last_index(njs_vm_t *vm, njs_object_prop_t *unused, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused2, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { njs_regexp_t *regexp; @@ -557,11 +557,6 @@ njs_regexp_prototype_flags(njs_vm_t *vm, njs_value_t *args, njs_value_t *this, value; u_char dst[4]; - static const njs_value_t string_global = njs_string("global"); - static const njs_value_t string_ignore_case = njs_string("ignoreCase"); - static const njs_value_t string_multiline = njs_string("multiline"); - static const njs_value_t string_sticky = njs_string("sticky"); - this = njs_argument(args, 0); if (njs_slow_path(!njs_is_object(this))) { njs_type_error(vm, "\"this\" argument is not an object"); @@ -570,8 +565,7 @@ njs_regexp_prototype_flags(njs_vm_t *vm, njs_value_t *args, p = &dst[0]; - ret = njs_value_property(vm, this, njs_value_arg(&string_global), - &value); + ret = njs_value_property(vm, this, NJS_ATOM_STRING_global, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -580,8 +574,7 @@ njs_regexp_prototype_flags(njs_vm_t *vm, njs_value_t *args, *p++ = 'g'; } - ret = njs_value_property(vm, this, njs_value_arg(&string_ignore_case), - &value); + ret = njs_value_property(vm, this, NJS_ATOM_STRING_ignoreCase, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -590,8 +583,7 @@ njs_regexp_prototype_flags(njs_vm_t *vm, njs_value_t *args, *p++ = 'i'; } - ret = njs_value_property(vm, this, njs_value_arg(&string_multiline), - &value); + ret = njs_value_property(vm, this, NJS_ATOM_STRING_multiline, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -600,8 +592,7 @@ njs_regexp_prototype_flags(njs_vm_t *vm, njs_value_t *args, *p++ = 'm'; } - ret = njs_value_property(vm, this, njs_value_arg(&string_sticky), - &value); + ret = njs_value_property(vm, this, NJS_ATOM_STRING_sticky, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -681,7 +672,7 @@ njs_regexp_prototype_source(njs_vm_t *vm, njs_value_t *args, if (njs_slow_path(!njs_is_regexp(this))) { if (njs_object(this) == njs_vm_proto(vm, NJS_OBJ_TYPE_REGEXP)) { - njs_value_assign(retval, &njs_string_empty_regexp); + njs_atom_to_value(vm, retval, NJS_ATOM_STRING_spec_EMPTY_REGEXP); return NJS_OK; } @@ -708,9 +699,6 @@ njs_regexp_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_value_t *r, source, flags; njs_string_prop_t source_string, flags_string; - static const njs_value_t string_source = njs_string("source"); - static const njs_value_t string_flags = njs_string("flags"); - r = njs_argument(args, 0); if (njs_slow_path(!njs_is_object(r))) { @@ -718,8 +706,7 @@ njs_regexp_prototype_to_string(njs_vm_t *vm, njs_value_t *args, return NJS_ERROR; } - ret = njs_value_property(vm, r, njs_value_arg(&string_source), - &source); + ret = njs_value_property(vm, r, NJS_ATOM_STRING_source, &source); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -729,8 +716,7 @@ njs_regexp_prototype_to_string(njs_vm_t *vm, njs_value_t *args, return NJS_ERROR; } - ret = njs_value_property(vm, r, njs_value_arg(&string_flags), - &flags); + ret = njs_value_property(vm, r, NJS_ATOM_STRING_flags, &flags); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -740,8 +726,8 @@ njs_regexp_prototype_to_string(njs_vm_t *vm, njs_value_t *args, return NJS_ERROR; } - (void) njs_string_prop(&source_string, &source); - (void) njs_string_prop(&flags_string, &flags); + (void) njs_string_prop(vm, &source_string, &source); + (void) njs_string_prop(vm, &flags_string, &flags); size = source_string.size + flags_string.size + njs_length("//"); length = source_string.length + flags_string.length + njs_length("//"); @@ -879,8 +865,7 @@ njs_regexp_builtin_exec(njs_vm_t *vm, njs_value_t *r, njs_value_t *s, regexp->string = *s; pattern = regexp->pattern; - ret = njs_value_property(vm, r, njs_value_arg(&njs_string_lindex), - &value); + ret = njs_value_property(vm, r, NJS_ATOM_STRING_lastIndex, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -894,7 +879,7 @@ njs_regexp_builtin_exec(njs_vm_t *vm, njs_value_t *r, njs_value_t *s, last_index = 0; } - length = njs_string_prop(&string, s); + length = njs_string_prop(vm, &string, s); if (njs_slow_path((size_t) last_index > length)) { goto not_found; @@ -952,8 +937,7 @@ njs_regexp_builtin_exec(njs_vm_t *vm, njs_value_t *r, njs_value_t *s, } njs_set_number(&value, index); - ret = njs_value_property_set(vm, r, - njs_value_arg(&njs_string_lindex), + ret = njs_value_property_set(vm, r, NJS_ATOM_STRING_lastIndex, &value); if (njs_slow_path(ret != NJS_OK)) { njs_regex_match_data_free(match_data, vm->regex_generic_ctx); @@ -989,8 +973,7 @@ not_found: if (pattern->global || pattern->sticky) { njs_set_number(&value, 0); - ret = njs_value_property_set(vm, r, njs_value_arg(&njs_string_lindex), - &value); + ret = njs_value_property_set(vm, r, NJS_ATOM_STRING_lastIndex, &value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -1024,13 +1007,9 @@ njs_regexp_exec_result(njs_vm_t *vm, njs_value_t *r, njs_utf8_t utf8, njs_regexp_t *regexp; njs_object_prop_t *prop; njs_regexp_group_t *group; - njs_lvlhsh_query_t lhq; + njs_flathsh_query_t lhq; njs_regexp_pattern_t *pattern; - static const njs_value_t string_index = njs_string("index"); - static const njs_value_t string_input = njs_string("input"); - static const njs_value_t string_groups = njs_string("groups"); - regexp = njs_regexp(r); pattern = regexp->pattern; array = njs_array_alloc(vm, 0, pattern->ncaptures, 0); @@ -1059,7 +1038,7 @@ njs_regexp_exec_result(njs_vm_t *vm, njs_value_t *r, njs_utf8_t utf8, } /* FIXME: implement fast CreateDataPropertyOrThrow(). */ - prop = njs_object_prop_alloc(vm, &string_index, &njs_value_undefined, 1); + prop = njs_object_prop_alloc(vm, &njs_value_undefined, 1); if (njs_slow_path(prop == NULL)) { goto fail; } @@ -1075,42 +1054,39 @@ njs_regexp_exec_result(njs_vm_t *vm, njs_value_t *r, njs_utf8_t utf8, njs_set_number(&prop->u.value, index); - lhq.key_hash = NJS_INDEX_HASH; - lhq.key = njs_str_value("index"); + lhq.key_hash = NJS_ATOM_STRING_index; lhq.replace = 0; lhq.value = prop; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(&array->object.hash, &lhq); + ret = njs_flathsh_unique_insert(&array->object.hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { goto insert_fail; } - prop = njs_object_prop_alloc(vm, &string_input, ®exp->string, 1); + prop = njs_object_prop_alloc(vm, ®exp->string, 1); if (njs_slow_path(prop == NULL)) { goto fail; } - lhq.key_hash = NJS_INPUT_HASH; - lhq.key = njs_str_value("input"); + lhq.key_hash = NJS_ATOM_STRING_input; lhq.value = prop; - ret = njs_lvlhsh_insert(&array->object.hash, &lhq); + ret = njs_flathsh_unique_insert(&array->object.hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { goto insert_fail; } - prop = njs_object_prop_alloc(vm, &string_groups, &njs_value_undefined, 1); + prop = njs_object_prop_alloc(vm, &njs_value_undefined, 1); if (njs_slow_path(prop == NULL)) { goto fail; } - lhq.key_hash = NJS_GROUPS_HASH; - lhq.key = njs_str_value("groups"); + lhq.key_hash = NJS_ATOM_STRING_groups; lhq.value = prop; - ret = njs_lvlhsh_insert(&array->object.hash, &lhq); + ret = njs_flathsh_unique_insert(&array->object.hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { goto insert_fail; } @@ -1128,23 +1104,21 @@ njs_regexp_exec_result(njs_vm_t *vm, njs_value_t *r, njs_utf8_t utf8, do { group = &pattern->groups[i]; - ret = njs_string_create(vm, &name, group->name.start, - group->name.length); + ret = njs_atom_string_create(vm, &name, group->name.start, + group->name.length); if (njs_slow_path(ret != NJS_OK)) { goto fail; } - prop = njs_object_prop_alloc(vm, &name, - &array->start[group->capture], 1); + prop = njs_object_prop_alloc(vm, &array->start[group->capture], 1); if (njs_slow_path(prop == NULL)) { goto fail; } - lhq.key_hash = group->hash; - lhq.key = group->name; + lhq.key_hash = name.atom_id; lhq.value = prop; - ret = njs_lvlhsh_insert(&groups->hash, &lhq); + ret = njs_flathsh_unique_insert(&groups->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { goto insert_fail; } @@ -1174,38 +1148,39 @@ done: static void njs_regexp_exec_result_free(njs_vm_t *vm, njs_array_t *result) { - njs_uint_t n; - njs_value_t *start; - njs_flathsh_t *hash; - njs_object_prop_t *prop; - njs_lvlhsh_each_t lhe; - njs_lvlhsh_query_t lhq; + njs_uint_t n; + njs_value_t *start; + njs_flathsh_t *hash; + njs_object_prop_t *prop; + njs_flathsh_elt_t *elt; + njs_flathsh_each_t lhe; + njs_flathsh_query_t lhq; if (result->object.fast_array) { start = result->start; for (n = 0; n < result->length; n++) { - if (start[n].short_string.size == NJS_STRING_LONG) { - njs_mp_free(vm->mem_pool, start[n].long_string.data); + if (start[n].type == NJS_STRING) { + njs_mp_free(vm->mem_pool, start[n].string.data); } } } - njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + njs_flathsh_each_init(&lhe, &njs_object_hash_proto); hash = &result->object.hash; for ( ;; ) { - prop = njs_flathsh_each(hash, &lhe); - - if (prop == NULL) { + elt = njs_flathsh_each(hash, &lhe); + if (elt == NULL) { break; } + prop = elt->value; + njs_mp_free(vm->mem_pool, prop); } - lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; @@ -1257,9 +1232,7 @@ njs_regexp_exec(njs_vm_t *vm, njs_value_t *r, njs_value_t *s, unsigned flags, njs_value_t exec; njs_value_t arguments[2]; - static const njs_value_t string_exec = njs_string("exec"); - - ret = njs_value_property(vm, r, njs_value_arg(&string_exec), &exec); + ret = njs_value_property(vm, r, NJS_ATOM_STRING_exec, &exec); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -1324,10 +1297,6 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args, njs_function_t *func_replace; njs_string_prop_t s; - static const njs_value_t string_global = njs_string("global"); - static const njs_value_t string_groups = njs_string("groups"); - static const njs_value_t string_index = njs_string("index"); - rx = njs_argument(args, 0); if (njs_slow_path(!njs_is_object(rx))) { @@ -1342,7 +1311,7 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args, return ret; } - length = njs_string_prop(&s, string); + length = njs_string_prop(vm, &s, string); rep.start = NULL; rep.length = 0; @@ -1357,7 +1326,7 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args, } } - ret = njs_value_property(vm, rx, njs_value_arg(&string_global), &value); + ret = njs_value_property(vm, rx, NJS_ATOM_STRING_global, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -1366,8 +1335,7 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args, if (global) { njs_set_number(&value, 0); - ret = njs_value_property_set(vm, rx, njs_value_arg(&njs_string_lindex), - &value); + ret = njs_value_property_set(vm, rx, NJS_ATOM_STRING_lastIndex, &value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -1418,12 +1386,13 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args, goto exception; } - if (njs_string_length(&value) != 0) { + njs_string_get(vm, &value, &m); + + if (m.length != 0) { continue; } - ret = njs_value_property(vm, rx, njs_value_arg(&njs_string_lindex), - &value); + ret = njs_value_property(vm, rx, NJS_ATOM_STRING_lastIndex, &value); if (njs_slow_path(ret == NJS_ERROR)) { goto exception; } @@ -1434,8 +1403,7 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args, } njs_set_number(&value, last_index + 1); - ret = njs_value_property_set(vm, rx, njs_value_arg(&njs_string_lindex), - &value); + ret = njs_value_property_set(vm, rx, NJS_ATOM_STRING_lastIndex, &value); if (njs_slow_path(ret != NJS_OK)) { goto exception; } @@ -1462,7 +1430,7 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args, goto exception; } - ret = njs_value_property(vm, r, njs_value_arg(&string_index), &value); + ret = njs_value_property(vm, r, NJS_ATOM_STRING_index, &value); if (njs_slow_path(ret == NJS_ERROR)) { goto exception; } @@ -1505,7 +1473,7 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args, } } - ret = njs_value_property(vm, r, njs_value_arg(&string_groups), &groups); + ret = njs_value_property(vm, r, NJS_ATOM_STRING_groups, &groups); if (njs_slow_path(ret == NJS_ERROR)) { goto exception; } @@ -1558,10 +1526,10 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args, if (p >= next) { njs_chb_append(&chain, next, p - next); - njs_string_get(retval, &rep); + njs_string_get(vm, retval, &rep); njs_chb_append_str(&chain, &rep); - njs_string_get(&matched, &m); + njs_string_get(vm, &matched, &m); next = p + m.length; } @@ -1616,9 +1584,6 @@ njs_regexp_prototype_symbol_split(njs_vm_t *vm, njs_value_t *args, njs_string_prop_t s, sv; njs_value_t arguments[2]; - static const njs_value_t string_lindex = njs_string("lastIndex"); - static const njs_value_t string_flags = njs_string("flags"); - rx = njs_argument(args, 0); if (njs_slow_path(!njs_is_object(rx))) { @@ -1640,7 +1605,7 @@ njs_regexp_prototype_symbol_split(njs_vm_t *vm, njs_value_t *args, return ret; } - ret = njs_value_property(vm, rx, njs_value_arg(&string_flags), retval); + ret = njs_value_property(vm, rx, NJS_ATOM_STRING_flags, retval); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -1650,7 +1615,7 @@ njs_regexp_prototype_symbol_split(njs_vm_t *vm, njs_value_t *args, return ret; } - (void) njs_string_prop(&s, retval); + (void) njs_string_prop(vm, &s, retval); sticky = memchr(s.start, 'y', s.size) != NULL; @@ -1705,7 +1670,7 @@ njs_regexp_prototype_symbol_split(njs_vm_t *vm, njs_value_t *args, goto done; } - length = njs_string_prop(&s, string); + length = njs_string_prop(vm, &s, string); if (njs_slow_path(s.size == 0)) { ret = njs_regexp_exec(vm, rx, string, NJS_REGEXP_FLAG_TEST, &z); @@ -1731,8 +1696,7 @@ njs_regexp_prototype_symbol_split(njs_vm_t *vm, njs_value_t *args, while (q < length) { njs_set_number(&setval, q); - ret = njs_value_property_set(vm, rx, njs_value_arg(&string_lindex), - &setval); + ret = njs_value_property_set(vm, rx, NJS_ATOM_STRING_lastIndex, &setval); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -1747,8 +1711,7 @@ njs_regexp_prototype_symbol_split(njs_vm_t *vm, njs_value_t *args, continue; } - ret = njs_value_property(vm, rx, njs_value_arg(&string_lindex), - retval); + ret = njs_value_property(vm, rx, NJS_ATOM_STRING_lastIndex, retval); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -1808,7 +1771,7 @@ njs_regexp_prototype_symbol_split(njs_vm_t *vm, njs_value_t *args, return NJS_ERROR; } - (void) njs_string_prop(&sv, retval); + (void) njs_string_prop(vm, &sv, retval); ret = njs_array_string_add(vm, array, sv.start, sv.size, sv.length); @@ -1869,13 +1832,14 @@ done: } -static const njs_object_prop_t njs_regexp_constructor_properties[] = +static const njs_object_prop_init_t njs_regexp_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(2), NJS_DECLARE_PROP_NAME("RegExp"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -1885,56 +1849,48 @@ const njs_object_init_t njs_regexp_constructor_init = { }; -static const njs_object_prop_t njs_regexp_prototype_properties[] = +static const njs_object_prop_init_t njs_regexp_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_GETTER("flags", njs_regexp_prototype_flags, 0), + NJS_DECLARE_PROP_GETTER(STRING_flags, njs_regexp_prototype_flags, 0), - NJS_DECLARE_PROP_GETTER("global", njs_regexp_prototype_flag, + NJS_DECLARE_PROP_GETTER(STRING_global, njs_regexp_prototype_flag, NJS_REGEX_GLOBAL), - NJS_DECLARE_PROP_GETTER("ignoreCase", njs_regexp_prototype_flag, + NJS_DECLARE_PROP_GETTER(STRING_ignoreCase, njs_regexp_prototype_flag, NJS_REGEX_IGNORE_CASE), - NJS_DECLARE_PROP_GETTER("multiline", njs_regexp_prototype_flag, + NJS_DECLARE_PROP_GETTER(STRING_multiline, njs_regexp_prototype_flag, NJS_REGEX_MULTILINE), - NJS_DECLARE_PROP_GETTER("source", njs_regexp_prototype_source, 0), + NJS_DECLARE_PROP_GETTER(STRING_source, njs_regexp_prototype_source, 0), - NJS_DECLARE_PROP_GETTER("sticky", njs_regexp_prototype_flag, + NJS_DECLARE_PROP_GETTER(STRING_sticky, njs_regexp_prototype_flag, NJS_REGEX_STICKY), - NJS_DECLARE_PROP_NATIVE("toString", njs_regexp_prototype_to_string, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toString, + njs_regexp_prototype_to_string, 0, 0), - NJS_DECLARE_PROP_NATIVE("test", njs_regexp_prototype_test, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_test, njs_regexp_prototype_test, 1, 0), - NJS_DECLARE_PROP_NATIVE("exec", njs_regexp_prototype_exec, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_exec, njs_regexp_prototype_exec, 1, 0), - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_REPLACE), - .u.value = njs_native_function(njs_regexp_prototype_symbol_replace, 2), - .writable = 1, - .configurable = 1, - }, + NJS_DECLARE_PROP_NATIVE(SYMBOL_replace, + njs_regexp_prototype_symbol_replace, 2, 0), - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_SPLIT), - .u.value = njs_native_function(njs_regexp_prototype_symbol_split, 2), - .writable = 1, - .configurable = 1, - }, + NJS_DECLARE_PROP_NATIVE(SYMBOL_split, + njs_regexp_prototype_symbol_split, 2, 0), }; -const njs_object_prop_t njs_regexp_instance_properties[] = +const njs_object_prop_init_t njs_regexp_instance_properties[] = { - NJS_DECLARE_PROP_HANDLER("lastIndex", njs_regexp_prototype_last_index, - 0, 0, NJS_OBJECT_PROP_VALUE_W), + NJS_DECLARE_PROP_HANDLER(STRING_lastIndex, + njs_regexp_prototype_last_index, 0, + NJS_OBJECT_PROP_VALUE_W), }; diff --git a/src/njs_scope.c b/src/njs_scope.c index 36ba0ec5..304e4e33 100644 --- a/src/njs_scope.c +++ b/src/njs_scope.c @@ -127,7 +127,8 @@ njs_scope_values_hash_test(njs_lvlhsh_query_t *lhq, void *data) value = data; if (njs_is_string(value)) { - njs_string_get(value, &string); + /* parser strings are always initialized. */ + njs_string_get_unsafe(value, &string); } else { string.start = (u_char *) value; @@ -167,24 +168,23 @@ njs_scope_value_index(njs_vm_t *vm, const njs_value_t *src, njs_uint_t runtime, uint32_t value_size, size, length; njs_int_t ret; njs_str_t str; - njs_bool_t long_string; + njs_bool_t is_string; njs_value_t *value; njs_string_t *string; njs_lvlhsh_t *values_hash; njs_lvlhsh_query_t lhq; - long_string = 0; + is_string = 0; value_size = sizeof(njs_value_t); if (njs_is_string(src)) { - njs_string_get(src, &str); + /* parser strings are always initialized. */ + njs_string_get_unsafe(src, &str); size = (uint32_t) str.length; start = str.start; - if (src->short_string.size == NJS_STRING_LONG) { - long_string = 1; - } + is_string = 1; } else { size = value_size; @@ -207,8 +207,8 @@ njs_scope_value_index(njs_vm_t *vm, const njs_value_t *src, njs_uint_t runtime, *index = (njs_index_t *) ((u_char *) value + sizeof(njs_value_t)); } else { - if (long_string) { - length = src->long_string.data->length; + if (is_string) { + length = src->string.data->length; if (size != length && length > NJS_STRING_MAP_STRIDE) { size = njs_string_map_offset(size) @@ -227,14 +227,15 @@ njs_scope_value_index(njs_vm_t *vm, const njs_value_t *src, njs_uint_t runtime, *value = *src; - if (long_string) { + if (is_string) { string = (njs_string_t *) ((u_char *) value + sizeof(njs_value_t) + sizeof(njs_index_t)); - value->long_string.data = string; + value->string.data = string; string->start = (u_char *) string + sizeof(njs_string_t); - string->length = src->long_string.data->length; + string->length = src->string.data->length; + string->size = src->string.data->size; memcpy(string->start, start, size); } diff --git a/src/njs_string.c b/src/njs_string.c index 6a91cb4c..c38f455b 100644 --- a/src/njs_string.c +++ b/src/njs_string.c @@ -160,23 +160,8 @@ njs_string_alloc(njs_vm_t *vm, njs_value_t *value, uint64_t size, } value->type = NJS_STRING; - njs_string_truth(value, size); - - if (size <= NJS_STRING_SHORT) { - value->short_string.size = size; - value->short_string.length = length; - - return value->short_string.start; - } - - /* - * Setting UTF-8 length is not required here, it just allows - * to store the constant in whole byte instead of bit twiddling. - */ - value->short_string.size = NJS_STRING_LONG; - value->short_string.length = 0; - value->long_string.external = 0; - value->long_string.size = size; + value->truth = size != 0; + value->atom_id = NJS_ATOM_STRING_unknown; if (size != length && length > NJS_STRING_MAP_STRIDE) { map_offset = njs_string_map_offset(size); @@ -190,9 +175,10 @@ njs_string_alloc(njs_vm_t *vm, njs_value_t *value, uint64_t size, string = njs_mp_alloc(vm->mem_pool, sizeof(njs_string_t) + total); if (njs_fast_path(string != NULL)) { - value->long_string.data = string; + value->string.data = string; string->start = (u_char *) string + sizeof(njs_string_t); + string->size = size; string->length = length; if (map_offset != 0) { @@ -209,42 +195,23 @@ njs_string_alloc(njs_vm_t *vm, njs_value_t *value, uint64_t size, } -uint32_t -njs_string_length(njs_value_t *string) -{ - uint32_t length, size; - - if (string->short_string.size != NJS_STRING_LONG) { - size = string->short_string.size; - length = string->short_string.length; - - } else { - size = string->long_string.size; - length = string->long_string.data->length; - } - - return (length == 0) ? size : length; -} - - size_t -njs_string_prop(njs_string_prop_t *string, const njs_value_t *value) +njs_string_prop(njs_vm_t *vm, njs_string_prop_t *string, + const njs_value_t *value) { - size_t size; - uintptr_t length; - - size = value->short_string.size; + size_t size, length; + njs_value_t s; - if (size != NJS_STRING_LONG) { - string->start = (u_char *) value->short_string.start; - length = value->short_string.length; - - } else { - string->start = (u_char *) value->long_string.data->start; - size = value->long_string.size; - length = value->long_string.data->length; + if (njs_slow_path(value->string.data == NULL)) { + njs_assert(value->atom_id != NJS_ATOM_STRING_unknown); + (void) njs_atom_to_value(vm, &s, value->atom_id); + value = &s; } + string->start = (u_char *) value->string.data->start; + size = value->string.data->size; + length = value->string.data->length; + string->size = size; string->length = length; @@ -255,32 +222,8 @@ njs_string_prop(njs_string_prop_t *string, const njs_value_t *value) void njs_string_truncate(njs_value_t *value, uint32_t size, uint32_t length) { - u_char *dst, *src; - uint32_t n; - - if (size <= NJS_STRING_SHORT) { - if (value->short_string.size == NJS_STRING_LONG) { - dst = value->short_string.start; - src = value->long_string.data->start; - - n = size; - - while (n != 0) { - /* The maximum size is just 14 bytes. */ - njs_pragma_loop_disable_vectorization; - - *dst++ = *src++; - n--; - } - } - - value->short_string.size = size; - value->short_string.length = length; - - } else { - value->long_string.size = size; - value->long_string.data->length = length; - } + value->string.data->size = size; + value->string.data->length = length; } @@ -430,7 +373,7 @@ njs_string_base64(njs_vm_t *vm, njs_value_t *retval, const njs_str_t *src) length = njs_encode_base64_length(src, &dst.length); if (njs_slow_path(dst.length == 0)) { - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -452,7 +395,7 @@ njs_string_base64url(njs_vm_t *vm, njs_value_t *retval, const njs_str_t *src) njs_str_t dst; if (njs_slow_path(src->length == 0)) { - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -488,21 +431,21 @@ njs_string_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { njs_int_t ret; - njs_value_t *value; + njs_value_t value; njs_object_value_t *object; if (nargs == 1) { - value = njs_value_arg(&njs_string_empty); + njs_set_empty_string(vm, &value); } else { - value = &args[1]; + value = args[1]; - if (njs_slow_path(!njs_is_string(value))) { - if (!vm->top_frame->ctor && njs_is_symbol(value)) { - return njs_symbol_descriptive_string(vm, retval, value); + if (njs_slow_path(!njs_is_string(&value))) { + if (!vm->top_frame->ctor && njs_is_symbol(&value)) { + return njs_symbol_descriptive_string(vm, retval, &value); } - ret = njs_value_to_string(vm, value, value); + ret = njs_value_to_string(vm, &value, &value); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -510,7 +453,7 @@ njs_string_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (vm->top_frame->ctor) { - object = njs_object_value_alloc(vm, NJS_OBJ_TYPE_STRING, 0, value); + object = njs_object_value_alloc(vm, NJS_OBJ_TYPE_STRING, 0, &value); if (njs_slow_path(object == NULL)) { return NJS_ERROR; } @@ -518,28 +461,31 @@ njs_string_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_set_object_value(retval, object); } else { - njs_value_assign(retval, value); + njs_value_assign(retval, &value); } return NJS_OK; } -static const njs_object_prop_t njs_string_constructor_properties[] = +static const njs_object_prop_init_t njs_string_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("String"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_NATIVE("fromCharCode", njs_string_from_char_code, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_fromCharCode, njs_string_from_char_code, + 1, 0), - NJS_DECLARE_PROP_NATIVE("fromCodePoint", njs_string_from_char_code, 1, 1), + NJS_DECLARE_PROP_NATIVE(STRING_fromCodePoint, + njs_string_from_char_code, 1, 1), }; -const njs_object_init_t njs_string_constructor_init = { +static const njs_object_init_t njs_string_constructor_init = { njs_string_constructor_properties, njs_nitems(njs_string_constructor_properties), }; @@ -547,9 +493,9 @@ const njs_object_init_t njs_string_constructor_init = { static njs_int_t njs_string_instance_length(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { - size_t size; uintptr_t length; njs_object_value_t *ov; @@ -568,15 +514,12 @@ njs_string_instance_length(njs_vm_t *vm, njs_object_prop_t *prop, } if (njs_is_string(value)) { - size = value->short_string.size; - length = value->short_string.length; - - if (size == NJS_STRING_LONG) { - size = value->long_string.size; - length = value->long_string.data->length; + if (njs_slow_path(value->string.data == NULL)) { + njs_assert(value->atom_id != NJS_ATOM_STRING_unknown); + njs_atom_to_value(vm, value, value->atom_id); } - length = (length == 0) ? size : length; + length = value->string.data->length; } njs_set_number(retval, length); @@ -586,97 +529,37 @@ njs_string_instance_length(njs_vm_t *vm, njs_object_prop_t *prop, njs_bool_t -njs_string_eq(const njs_value_t *v1, const njs_value_t *v2) +njs_string_eq(njs_vm_t *vm, const njs_value_t *v1, const njs_value_t *v2) { - size_t size, length1, length2; - const u_char *start1, *start2; + njs_str_t s1, s2; - size = v1->short_string.size; + njs_string_get(vm, v1, &s1); + njs_string_get(vm, v2, &s2); - if (size != v2->short_string.size) { + if (s1.length != s2.length) { return 0; } - if (size != NJS_STRING_LONG) { - length1 = v1->short_string.length; - length2 = v2->short_string.length; - - /* - * Using full memcmp() comparison if at least one string - * is a Byte string. - */ - if (length1 != 0 && length2 != 0 && length1 != length2) { - return 0; - } - - start1 = v1->short_string.start; - start2 = v2->short_string.start; - - } else { - size = v1->long_string.size; - - if (size != v2->long_string.size) { - return 0; - } - - length1 = v1->long_string.data->length; - length2 = v2->long_string.data->length; - - /* - * Using full memcmp() comparison if at least one string - * is a Byte string. - */ - if (length1 != 0 && length2 != 0 && length1 != length2) { - return 0; - } - - start1 = v1->long_string.data->start; - start2 = v2->long_string.data->start; - } - - return (memcmp(start1, start2, size) == 0); + return (memcmp(s1.start, s2.start, s1.length) == 0); } njs_int_t -njs_string_cmp(const njs_value_t *v1, const njs_value_t *v2) +njs_string_cmp(njs_vm_t *vm, const njs_value_t *v1, const njs_value_t *v2) { - size_t size, size1, size2; - njs_int_t ret; - const u_char *start1, *start2; - - njs_assert(njs_is_string(v1)); - njs_assert(njs_is_string(v2)); - - size1 = v1->short_string.size; - - if (size1 != NJS_STRING_LONG) { - start1 = v1->short_string.start; - - } else { - size1 = v1->long_string.size; - start1 = v1->long_string.data->start; - } - - size2 = v2->short_string.size; - - if (size2 != NJS_STRING_LONG) { - start2 = v2->short_string.start; - - } else { - size2 = v2->long_string.size; - start2 = v2->long_string.data->start; - } + njs_int_t ret; + njs_str_t s1, s2; - size = njs_min(size1, size2); + njs_string_get(vm, v1, &s1); + njs_string_get(vm, v2, &s2); - ret = memcmp(start1, start2, size); + ret = memcmp(s1.start, s2.start, njs_min(s1.length, s2.length)); if (ret != 0) { return ret; } - return (size1 - size2); + return (s1.length - s2.length); } @@ -748,7 +631,7 @@ njs_string_prototype_concat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, mask = -1; for (i = 0; i < nargs; i++) { - (void) njs_string_prop(&string, &args[i]); + (void) njs_string_prop(vm, &string, &args[i]); size += string.size; length += string.length; @@ -764,7 +647,7 @@ njs_string_prototype_concat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, p = start; for (i = 0; i < nargs; i++) { - (void) njs_string_prop(&string, &args[i]); + (void) njs_string_prop(vm, &string, &args[i]); p = memcpy(p, string.start, string.size); p += string.size; @@ -832,7 +715,7 @@ njs_string_prototype_substring(njs_vm_t *vm, njs_value_t *args, return ret; } - length = njs_string_prop(&string, njs_argument(args, 0)); + length = njs_string_prop(vm, &string, njs_argument(args, 0)); slice.string_length = length; start = 0; @@ -910,7 +793,7 @@ njs_string_prototype_substr(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - length = njs_string_prop(&string, njs_argument(args, 0)); + length = njs_string_prop(vm, &string, njs_argument(args, 0)); slice.string_length = length; start = 0; @@ -988,7 +871,7 @@ njs_string_prototype_char_at(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - slice.string_length = njs_string_prop(&string, njs_argument(args, 0)); + slice.string_length = njs_string_prop(vm, &string, njs_argument(args, 0)); ret = njs_value_to_integer(vm, njs_arg(args, nargs, 1), &start); if (njs_slow_path(ret != NJS_OK)) { @@ -1013,7 +896,7 @@ static njs_int_t njs_string_slice_prop(njs_vm_t *vm, njs_string_prop_t *string, njs_slice_prop_t *slice, njs_value_t *args, njs_uint_t nargs) { - slice->string_length = njs_string_prop(string, &args[0]); + slice->string_length = njs_string_prop(vm, string, &args[0]); return njs_string_slice_args(vm, slice, args, nargs); } @@ -1153,7 +1036,7 @@ njs_string_slice(njs_vm_t *vm, njs_value_t *retval, return njs_string_new(vm, retval, prop.start, prop.size, prop.length); } - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -1177,7 +1060,7 @@ njs_string_prototype_char_code_at(njs_vm_t *vm, njs_value_t *args, return ret; } - length = njs_string_prop(&string, njs_argument(args, 0)); + length = njs_string_prop(vm, &string, njs_argument(args, 0)); ret = njs_value_to_integer(vm, njs_arg(args, nargs, 1), &index); if (njs_slow_path(ret != NJS_OK)) { @@ -1306,7 +1189,7 @@ njs_string_decode_hex(njs_vm_t *vm, njs_value_t *retval, const njs_str_t *src) length = njs_decode_hex_length(src, &size); if (njs_slow_path(size == 0)) { - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -1429,7 +1312,7 @@ njs_string_decode_base64_core(njs_vm_t *vm, njs_value_t *retval, length = njs_decode_base64_length_core(src, basis, &dst.length); if (njs_slow_path(dst.length == 0)) { - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -1660,8 +1543,8 @@ njs_string_prototype_index_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - length = njs_string_prop(&string, this); - (void) njs_string_prop(&s, search); + length = njs_string_prop(vm, &string, this); + (void) njs_string_prop(vm, &s, search); from = njs_min(njs_max(from, 0), length); @@ -1713,11 +1596,11 @@ njs_string_prototype_last_index_of(njs_vm_t *vm, njs_value_t *args, start = INT64_MAX; } - length = njs_string_prop(&string, this); + length = njs_string_prop(vm, &string, this); start = njs_min(njs_max(start, 0), length); - search_length = njs_string_prop(&s, search); + search_length = njs_string_prop(vm, &s, search); index = length - search_length; @@ -1801,7 +1684,7 @@ njs_string_prototype_includes(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - search_length = njs_string_prop(&search, value); + search_length = njs_string_prop(vm, &search, value); if (nargs > 2) { value = njs_argument(args, 2); @@ -1828,7 +1711,7 @@ njs_string_prototype_includes(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_OK; } - length = njs_string_prop(&string, &args[0]); + length = njs_string_prop(vm, &string, &args[0]); if (length - index >= search_length) { end = string.start + string.size; @@ -1879,7 +1762,7 @@ njs_string_prototype_starts_or_ends_with(njs_vm_t *vm, njs_value_t *args, } } - search_length = njs_string_prop(&search, value); + search_length = njs_string_prop(vm, &search, value); value = njs_arg(args, nargs, 2); @@ -1902,7 +1785,7 @@ njs_string_prototype_starts_or_ends_with(njs_vm_t *vm, njs_value_t *args, } if (nargs > 1) { - length = njs_string_prop(&string, &args[0]); + length = njs_string_prop(vm, &string, &args[0]); if (starts) { if (index < 0) { @@ -2072,7 +1955,7 @@ njs_string_prototype_to_lower_case(njs_vm_t *vm, njs_value_t *args, return ret; } - (void) njs_string_prop(&string, njs_argument(args, 0)); + (void) njs_string_prop(vm, &string, njs_argument(args, 0)); if (njs_is_ascii_string(&string)) { @@ -2143,7 +2026,7 @@ njs_string_prototype_to_upper_case(njs_vm_t *vm, njs_value_t *args, return ret; } - (void) njs_string_prop(&string, njs_argument(args, 0)); + (void) njs_string_prop(vm, &string, njs_argument(args, 0)); if (njs_is_ascii_string(&string)) { @@ -2194,8 +2077,8 @@ njs_string_prototype_to_upper_case(njs_vm_t *vm, njs_value_t *args, uint32_t -njs_string_trim(const njs_value_t *value, njs_string_prop_t *string, - unsigned mode) +njs_string_trim(njs_vm_t *vm, const njs_value_t *value, + njs_string_prop_t *string, unsigned mode) { uint32_t cp, trim; const u_char *p, *prev, *start, *end; @@ -2203,7 +2086,7 @@ njs_string_trim(const njs_value_t *value, njs_string_prop_t *string, trim = 0; - njs_string_prop(string, value); + njs_string_prop(vm, string, value); start = string->start; end = string->start + string->size; @@ -2326,7 +2209,7 @@ njs_string_prototype_trim(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - trim = njs_string_trim(value, &string, mode); + trim = njs_string_trim(vm, value, &string, mode); if (trim == 0) { njs_value_assign(retval, value); @@ -2334,7 +2217,7 @@ njs_string_prototype_trim(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (string.size == 0) { - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -2377,10 +2260,10 @@ njs_string_prototype_repeat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - (void) njs_string_prop(&string, this); + (void) njs_string_prop(vm, &string, this); if (njs_slow_path(n == 0 || string.size == 0)) { - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -2422,14 +2305,12 @@ njs_string_prototype_pad(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, const u_char *end; njs_string_prop_t string, pad_string; - static const njs_value_t string_space = njs_string(" "); - ret = njs_string_object_validate(vm, njs_argument(args, 0)); if (njs_slow_path(ret != NJS_OK)) { return ret; } - length = njs_string_prop(&string, njs_argument(args, 0)); + length = njs_string_prop(vm, &string, njs_argument(args, 0)); new_length = 0; @@ -2465,19 +2346,22 @@ njs_string_prototype_pad(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, pad = njs_arg(args, nargs, 2); - if (njs_slow_path(!njs_is_string(pad))) { - if (njs_is_undefined(pad)) { - pad = njs_value_arg(&string_space); - - } else { - ret = njs_value_to_string(vm, pad, pad); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } + if (njs_slow_path(!njs_is_string(pad) && !njs_is_undefined(pad))) { + ret = njs_value_to_string(vm, pad, pad); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; } } - pad_length = njs_string_prop(&pad_string, pad); + if (njs_slow_path(njs_is_undefined(pad))) { + pad_string.start = (u_char *) " "; + pad_string.size = 1; + pad_string.length = 1; + pad_length = 1; + + } else { + pad_length = njs_string_prop(vm, &pad_string, pad); + } if (pad_string.size == 0) { njs_value_assign(retval, njs_argument(args, 0)); @@ -2571,7 +2455,7 @@ njs_string_prototype_search(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - (void) njs_string_prop(&string, value); + (void) njs_string_prop(vm, &string, value); if (string.size != 0) { pattern = njs_regexp_pattern_create(vm, string.start, @@ -2588,7 +2472,7 @@ njs_string_prototype_search(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, index = -1; - (void) njs_string_prop(&string, &args[0]); + (void) njs_string_prop(vm, &string, &args[0]); n = (string.length != 0); @@ -2657,11 +2541,11 @@ njs_string_prototype_match(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - njs_string_get(&args[1], &string); + njs_string_get(vm, &args[1], &string); } } else { - njs_string_get(&args[1], &string); + njs_string_get(vm, &args[1], &string); } /* A void value. */ @@ -2694,7 +2578,7 @@ njs_string_match_multiple(njs_vm_t *vm, njs_value_t *args, njs_set_number(&args[1].data.u.regexp->last_index, 0); njs_set_null(retval); - (void) njs_string_prop(&string, &args[0]); + (void) njs_string_prop(vm, &string, &args[0]); utf8 = NJS_STRING_ASCII; type = NJS_REGEXP_BYTE; @@ -2795,9 +2679,6 @@ njs_string_prototype_split(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_string_prop_t string, split; njs_value_t arguments[3]; - static const njs_value_t split_key = - njs_wellknown_symbol(NJS_SYMBOL_SPLIT); - this = njs_argument(args, 0); if (njs_slow_path(njs_is_null_or_undefined(this))) { @@ -2810,7 +2691,7 @@ njs_string_prototype_split(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, value = njs_lvalue_arg(&limit_lvalue, args, nargs, 2); if (!njs_is_null_or_undefined(separator)) { - ret = njs_value_method(vm, separator, njs_value_arg(&split_key), + ret = njs_value_method(vm, separator, NJS_ATOM_SYMBOL_split, &splitter); if (njs_slow_path(ret != NJS_OK)) { return ret; @@ -2859,8 +2740,8 @@ njs_string_prototype_split(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto single; } - (void) njs_string_prop(&string, this); - (void) njs_string_prop(&split, separator); + (void) njs_string_prop(vm, &string, this); + (void) njs_string_prop(vm, &split, separator); if (njs_slow_path(string.size == 0)) { if (split.size != 0) { @@ -2951,7 +2832,7 @@ njs_string_get_substitution(njs_vm_t *vm, njs_value_t *matched, njs_value_t name, value; njs_string_prop_t s, m; - njs_string_get(replacement, &rep); + njs_string_get(vm, replacement, &rep); p = rep.start; end = rep.start + rep.length; @@ -2981,21 +2862,21 @@ njs_string_get_substitution(njs_vm_t *vm, njs_value_t *matched, break; case '&': - (void) njs_string_prop(&m, matched); + (void) njs_string_prop(vm, &m, matched); njs_chb_append(&chain, m.start, m.size); p += 2; break; case '`': - (void) njs_string_prop(&s, string); + (void) njs_string_prop(vm, &s, string); n = njs_string_offset(&s, pos) - s.start; njs_chb_append(&chain, s.start, n); p += 2; break; case '\'': - length = njs_string_prop(&m, matched); - (void) njs_string_prop(&s, string); + length = njs_string_prop(vm, &m, matched); + (void) njs_string_prop(vm, &s, string); tail = njs_string_offset(&s, pos + length) - s.start; @@ -3021,7 +2902,7 @@ njs_string_get_substitution(njs_vm_t *vm, njs_value_t *matched, p = r + 1; - ret = njs_value_property(vm, groups, &name, &value); + ret = njs_value_property_val(vm, groups, &name, &value); if (njs_slow_path(ret == NJS_ERROR)) { goto exception; } @@ -3032,7 +2913,7 @@ njs_string_get_substitution(njs_vm_t *vm, njs_value_t *matched, goto exception; } - njs_string_get(&value, &str); + njs_string_get(vm, &value, &str); njs_chb_append_str(&chain, &str); } @@ -3062,7 +2943,7 @@ njs_string_get_substitution(njs_vm_t *vm, njs_value_t *matched, p += (c2 != 0) ? 3 : 2; if (njs_is_defined(&captures[n])) { - njs_string_get(&captures[n], &cap); + njs_string_get(vm, &captures[n], &cap); njs_chb_append_str(&chain, &cap); } @@ -3110,10 +2991,6 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_function_t *func_replace; njs_string_prop_t string, s, ret_string; - static const njs_value_t replace_key = - njs_wellknown_symbol(NJS_SYMBOL_REPLACE); - static const njs_value_t string_flags = njs_string("flags"); - this = njs_argument(args, 0); if (njs_slow_path(njs_is_null_or_undefined(this))) { @@ -3126,8 +3003,7 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, replace = njs_lvalue_arg(&replace_lvalue, args, nargs, 2); if (!njs_is_null_or_undefined(search)) { - ret = njs_value_method(vm, search, njs_value_arg(&replace_key), - &replacer); + ret = njs_value_method(vm, search, NJS_ATOM_SYMBOL_replace, &replacer); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -3140,8 +3016,8 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, && njs_function(&replacer)->u.native == njs_regexp_prototype_symbol_replace) { - ret = njs_value_property(vm, search, - njs_value_arg(&string_flags), &value); + ret = njs_value_property(vm, search, NJS_ATOM_STRING_flags, + &value); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -3151,7 +3027,7 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - njs_string_get(&value, &str); + njs_string_get(vm, &value, &str); if (njs_strlchr(str.start, str.start + str.length, 'g') == NULL) @@ -3191,8 +3067,8 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_value_assign(&arguments[2], this); } - (void) njs_string_prop(&string, this); - (void) njs_string_prop(&s, search); + (void) njs_string_prop(vm, &string, this); + (void) njs_string_prop(vm, &s, search); pos = njs_string_index_of(&string, &s, 0); if (pos < 0) { @@ -3227,7 +3103,7 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, end = njs_string_offset(&string, pos); - (void) njs_string_prop(&ret_string, &value); + (void) njs_string_prop(vm, &ret_string, &value); size = string.size + ret_string.size - s.size; length = string.length + ret_string.length - s.length; @@ -3274,7 +3150,7 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } end = njs_string_offset(&string, pos); - (void) njs_string_prop(&ret_string, &value); + (void) njs_string_prop(vm, &ret_string, &value); njs_chb_append(&chain, start, end - start); njs_chb_append(&chain, ret_string.start, ret_string.size); @@ -3332,7 +3208,7 @@ njs_string_prototype_iterator_obj(njs_vm_t *vm, njs_value_t *args, double -njs_string_to_number(const njs_value_t *value) +njs_string_to_number(njs_vm_t *vm, const njs_value_t *value) { double num; njs_bool_t minus; @@ -3341,7 +3217,7 @@ njs_string_to_number(const njs_value_t *value) const size_t infinity = njs_length("Infinity"); - (void) njs_string_trim(value, &string, NJS_TRIM_START); + (void) njs_string_trim(vm, value, &string, NJS_TRIM_START); p = string.start; end = p + string.size; @@ -3413,16 +3289,17 @@ njs_string_to_index(const njs_value_t *value) const u_char *p, *start, *end; u_char buf[128]; - size = value->short_string.size; - - if (size != NJS_STRING_LONG) { - start = value->short_string.start; + if (njs_slow_path(value->type == NJS_SYMBOL)) { + return NAN; + } - } else { - size = value->long_string.size; - start = value->long_string.data->start; + if (njs_atom_is_number(value->atom_id)) { + return njs_atom_number(value->atom_id); } + size = value->string.data->size; + start = value->string.data->start; + p = start; end = p + size; minus = 0; @@ -3493,89 +3370,99 @@ njs_string_to_index(const njs_value_t *value) } -static const njs_object_prop_t njs_string_prototype_properties[] = +static const njs_object_prop_init_t njs_string_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("__proto__", njs_primitive_prototype_get_proto, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING___proto__, + njs_primitive_prototype_get_proto, 0, + NJS_OBJECT_PROP_VALUE_CW), NJS_DECLARE_PROP_LENGTH(0), - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), - - NJS_DECLARE_PROP_NATIVE("valueOf", njs_string_prototype_value_of, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_NATIVE("toString", njs_string_prototype_to_string, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_valueOf, njs_string_prototype_value_of, + 0, 0), - NJS_DECLARE_PROP_NATIVE("concat", njs_string_prototype_concat, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toString, + njs_string_prototype_to_string, 0, 0), - NJS_DECLARE_PROP_NATIVE("slice", njs_string_prototype_slice, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_concat, + njs_string_prototype_concat, 1, 0), - NJS_DECLARE_PROP_NATIVE("substring", njs_string_prototype_substring, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_slice, njs_string_prototype_slice, 2, + 0), - NJS_DECLARE_PROP_NATIVE("substr", njs_string_prototype_substr, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_substring, + njs_string_prototype_substring, 2, 0), - NJS_DECLARE_PROP_NATIVE("charAt", njs_string_prototype_char_at, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_substr, njs_string_prototype_substr, 2, + 0), - NJS_DECLARE_PROP_NATIVE("charCodeAt", njs_string_prototype_char_code_at, 1, + NJS_DECLARE_PROP_NATIVE(STRING_charAt, njs_string_prototype_char_at, 1, 0), - NJS_DECLARE_PROP_NATIVE("codePointAt", njs_string_prototype_char_code_at, - 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_charCodeAt, + njs_string_prototype_char_code_at, 1, 0), - NJS_DECLARE_PROP_NATIVE("indexOf", njs_string_prototype_index_of, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_codePointAt, + njs_string_prototype_char_code_at, 1, 0), - NJS_DECLARE_PROP_NATIVE("lastIndexOf", njs_string_prototype_last_index_of, + NJS_DECLARE_PROP_NATIVE(STRING_indexOf, njs_string_prototype_index_of, 1, 0), - NJS_DECLARE_PROP_NATIVE("includes", njs_string_prototype_includes, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_lastIndexOf, + njs_string_prototype_last_index_of, 1, 0), - NJS_DECLARE_PROP_NATIVE("startsWith", + NJS_DECLARE_PROP_NATIVE(STRING_includes, njs_string_prototype_includes, + 1, 0), + + NJS_DECLARE_PROP_NATIVE(STRING_startsWith, njs_string_prototype_starts_or_ends_with, 1, 1), - NJS_DECLARE_PROP_NATIVE("endsWith", + NJS_DECLARE_PROP_NATIVE(STRING_endsWith, njs_string_prototype_starts_or_ends_with, 1, 0), - NJS_DECLARE_PROP_NATIVE("toLowerCase", njs_string_prototype_to_lower_case, - 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toLowerCase, + njs_string_prototype_to_lower_case, 0, 0), - NJS_DECLARE_PROP_NATIVE("toUpperCase", njs_string_prototype_to_upper_case, - 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toUpperCase, + njs_string_prototype_to_upper_case, 0, 0), - NJS_DECLARE_PROP_NATIVE("trim", njs_string_prototype_trim, 0, + NJS_DECLARE_PROP_NATIVE(STRING_trim, njs_string_prototype_trim, 0, NJS_TRIM_START | NJS_TRIM_END), - NJS_DECLARE_PROP_NATIVE("trimStart", njs_string_prototype_trim, 0, + NJS_DECLARE_PROP_NATIVE(STRING_trimStart, njs_string_prototype_trim, 0, NJS_TRIM_START), - NJS_DECLARE_PROP_NATIVE("trimEnd", njs_string_prototype_trim, 0, + NJS_DECLARE_PROP_NATIVE(STRING_trimEnd, njs_string_prototype_trim, 0, NJS_TRIM_END), - NJS_DECLARE_PROP_NATIVE("repeat", njs_string_prototype_repeat, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_repeat, njs_string_prototype_repeat, 1, + 0), - NJS_DECLARE_PROP_NATIVE("padStart", njs_string_prototype_pad, 1, 1), + NJS_DECLARE_PROP_NATIVE(STRING_padStart, njs_string_prototype_pad, 1, + 1), - NJS_DECLARE_PROP_NATIVE("padEnd", njs_string_prototype_pad, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_padEnd, njs_string_prototype_pad, 1, 0), - NJS_DECLARE_PROP_NATIVE("search", njs_string_prototype_search, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_search, njs_string_prototype_search, 1, + 0), - NJS_DECLARE_PROP_NATIVE("match", njs_string_prototype_match, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_match, njs_string_prototype_match, 1, 0), - NJS_DECLARE_PROP_NATIVE("split", njs_string_prototype_split, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_split, njs_string_prototype_split, 2, 0), - NJS_DECLARE_PROP_NATIVE("replace", njs_string_prototype_replace, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_replace, njs_string_prototype_replace, 2, + 0), - NJS_DECLARE_PROP_NATIVE("replaceAll", njs_string_prototype_replace, 2, 1), + NJS_DECLARE_PROP_NATIVE(STRING_replaceAll, njs_string_prototype_replace, + 2, 1), - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_ITERATOR), - .u.value = njs_native_function2(njs_string_prototype_iterator_obj, 0, - NJS_ENUM_VALUES), - .writable = 1, - .configurable = 1, - }, + NJS_DECLARE_PROP_NATIVE(SYMBOL_iterator, + njs_string_prototype_iterator_obj, 0, + NJS_ENUM_VALUES), }; @@ -3585,9 +3472,10 @@ const njs_object_init_t njs_string_prototype_init = { }; -const njs_object_prop_t njs_string_instance_properties[] = +const njs_object_prop_init_t njs_string_instance_properties[] = { - NJS_DECLARE_PROP_HANDLER("length", njs_string_instance_length, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_length, njs_string_instance_length, 0, + 0), }; @@ -3649,7 +3537,7 @@ njs_string_encode_uri(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, }; if (nargs < 2) { - njs_value_assign(retval, &njs_string_undefined); + njs_atom_to_value(vm, retval, NJS_ATOM_STRING_undefined); return NJS_OK; } @@ -3663,7 +3551,7 @@ njs_string_encode_uri(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_prefetch(escape); - (void) njs_string_prop(&string, value); + (void) njs_string_prop(vm, &string, value); size = 0; src = string.start; @@ -3878,7 +3766,7 @@ njs_string_decode_uri(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, }; if (nargs < 2) { - njs_value_assign(retval, &njs_string_undefined); + njs_atom_to_value(vm, retval, NJS_ATOM_STRING_undefined); return NJS_OK; } @@ -3893,7 +3781,7 @@ njs_string_decode_uri(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_prefetch(reserve); njs_prefetch(&hex['0']); - (void) njs_string_prop(&string, value); + (void) njs_string_prop(vm, &string, value); length = 0; src = string.start; @@ -4023,7 +3911,7 @@ njs_string_btoa(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - len = njs_string_prop(&string, value); + len = njs_string_prop(vm, &string, value); p = string.start; end = string.start + string.size; @@ -4121,7 +4009,7 @@ njs_string_atob(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, /* Forgiving-base64 decode. */ b64 = njs_basis64; - njs_string_get(value, &str); + njs_string_get(vm, value, &str); tmp = njs_mp_alloc(vm->mem_pool, str.length); if (tmp == NULL) { @@ -4208,7 +4096,7 @@ njs_string_atob(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (size == 0) { - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -4237,7 +4125,6 @@ const njs_object_type_init_t njs_string_type_init = { .constructor_props = &njs_string_constructor_init, .prototype_props = &njs_string_prototype_init, .prototype_value = { .object_value = { - .value = njs_string(""), .object = { .type = NJS_OBJECT_VALUE } } }, }; diff --git a/src/njs_string.h b/src/njs_string.h index 686a5a74..1961152f 100644 --- a/src/njs_string.h +++ b/src/njs_string.h @@ -73,6 +73,7 @@ struct njs_string_s { u_char *start; uint32_t length; /* Length in UTF-8 characters. */ + uint32_t size; }; @@ -111,8 +112,8 @@ njs_int_t njs_string_create(njs_vm_t *vm, njs_value_t *value, const u_char *src, njs_int_t njs_string_create_chb(njs_vm_t *vm, njs_value_t *value, njs_chb_t *chain); -uint32_t njs_string_length(njs_value_t *string); -size_t njs_string_prop(njs_string_prop_t *string, const njs_value_t *value); +size_t njs_string_prop(njs_vm_t *vm, njs_string_prop_t *string, + const njs_value_t *value); void njs_encode_hex(njs_str_t *dst, const njs_str_t *src); size_t njs_encode_hex_length(const njs_str_t *src, size_t *out_size); @@ -143,10 +144,11 @@ njs_int_t njs_string_decode_base64(njs_vm_t *vm, njs_value_t *value, njs_int_t njs_string_decode_base64url(njs_vm_t *vm, njs_value_t *value, const njs_str_t *src); void njs_string_truncate(njs_value_t *value, uint32_t size, uint32_t length); -uint32_t njs_string_trim(const njs_value_t *value, njs_string_prop_t *string, - unsigned mode); +uint32_t njs_string_trim(njs_vm_t *vm, const njs_value_t *value, + njs_string_prop_t *string, unsigned mode); void njs_string_copy(njs_value_t *dst, njs_value_t *src); -njs_int_t njs_string_cmp(const njs_value_t *val1, const njs_value_t *val2); +njs_int_t njs_string_cmp(njs_vm_t *vm, const njs_value_t *val1, + const njs_value_t *val2); void njs_string_slice_string_prop(njs_string_prop_t *dst, const njs_string_prop_t *string, const njs_slice_prop_t *slice); njs_int_t njs_string_slice(njs_vm_t *vm, njs_value_t *dst, @@ -172,6 +174,21 @@ njs_int_t njs_string_get_substitution(njs_vm_t *vm, njs_value_t *matched, njs_value_t *groups, njs_value_t *replacement, njs_value_t *retval); +njs_inline njs_int_t +njs_atom_string_create(njs_vm_t *vm, njs_value_t *value, const u_char *src, + size_t size) +{ + njs_int_t ret; + + ret = njs_string_create(vm, value, src, size); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + return njs_atom_atomize_key(vm, value); +} + + njs_inline njs_bool_t njs_is_ascii_string(njs_string_prop_t *string) { diff --git a/src/njs_symbol.c b/src/njs_symbol.c index a284d4e9..46634a61 100644 --- a/src/njs_symbol.c +++ b/src/njs_symbol.c @@ -8,63 +8,9 @@ #include -static const njs_value_t njs_symbol_async_iterator_name = - njs_long_string("Symbol.asyncIterator"); -static const njs_value_t njs_symbol_has_instance_name = - njs_long_string("Symbol.hasInstance"); -static const njs_value_t njs_symbol_is_concat_spreadable_name = - njs_long_string("Symbol.isConcatSpreadable"); -static const njs_value_t njs_symbol_iterator_name = - njs_long_string("Symbol.iterator"); -static const njs_value_t njs_symbol_match_name = - njs_string("Symbol.match"); -static const njs_value_t njs_symbol_match_all_name = - njs_long_string("Symbol.matchAll"); -static const njs_value_t njs_symbol_replace_name = - njs_string("Symbol.replace"); -static const njs_value_t njs_symbol_search_name = - njs_string("Symbol.search"); -static const njs_value_t njs_symbol_species_name = - njs_string("Symbol.species"); -static const njs_value_t njs_symbol_split_name = - njs_string("Symbol.split"); -static const njs_value_t njs_symbol_to_primitive_name = - njs_long_string("Symbol.toPrimitive"); -static const njs_value_t njs_symbol_to_string_tag_name = - njs_long_string("Symbol.toStringTag"); -static const njs_value_t njs_symbol_unscopables_name = - njs_long_string("Symbol.unscopables"); - - -static const njs_value_t *njs_symbol_names[NJS_SYMBOL_KNOWN_MAX] = { - &njs_string_invalid, - &njs_symbol_async_iterator_name, - &njs_symbol_has_instance_name, - &njs_symbol_is_concat_spreadable_name, - &njs_symbol_iterator_name, - &njs_symbol_match_name, - &njs_symbol_match_all_name, - &njs_symbol_replace_name, - &njs_symbol_search_name, - &njs_symbol_species_name, - &njs_symbol_split_name, - &njs_symbol_to_primitive_name, - &njs_symbol_to_string_tag_name, - &njs_symbol_unscopables_name, -}; - - const njs_value_t * njs_symbol_description(const njs_value_t *value) { - uint32_t key; - - key = njs_symbol_key(value); - - if (key < NJS_SYMBOL_KNOWN_MAX) { - return njs_symbol_names[key]; - } - return value->data.u.value != NULL ? value->data.u.value : &njs_value_undefined; } @@ -80,11 +26,14 @@ njs_symbol_descriptive_string(njs_vm_t *vm, njs_value_t *dst, description = njs_symbol_description(value); - if (njs_is_undefined(description)) { - description = &njs_string_empty; - } + if (!njs_is_undefined(description)) { + (void) njs_string_prop(vm, &string, description); - (void) njs_string_prop(&string, description); + } else { + string.start = (u_char *) ""; + string.size = 0; + string.length = 0; + } string.length += njs_length("Symbol()"); @@ -105,7 +54,6 @@ static njs_int_t njs_symbol_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - uint64_t key; njs_int_t ret; njs_value_t *value, *name; @@ -125,13 +73,6 @@ njs_symbol_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - key = ++vm->symbol_generator; - - if (njs_slow_path(key >= UINT32_MAX)) { - njs_internal_error(vm, "Symbol generator overflow"); - return NJS_ERROR; - } - name = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t)); if (njs_slow_path(name == NULL)) { njs_memory_error(vm); @@ -139,7 +80,12 @@ njs_symbol_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } njs_value_assign(name, value); - njs_set_symbol(retval, key, name); + njs_set_symbol(retval, 0, name); + + ret = njs_atom_symbol_add(vm, retval); + if (ret != NJS_OK) { + return NJS_ERROR; + } return NJS_OK; } @@ -149,7 +95,6 @@ static njs_int_t njs_symbol_for(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - uint64_t key; njs_int_t ret; njs_value_t *value, lvalue; njs_rbtree_node_t *rb_node; @@ -171,7 +116,7 @@ njs_symbol_for(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, node = (njs_rb_symbol_node_t *) rb_node; if (njs_is_string(&node->name) - && njs_string_cmp(value, &node->name) == 0) + && njs_string_cmp(vm, value, &node->name) == 0) { njs_set_symbol(retval, node->key, &node->name); return NJS_OK; @@ -180,25 +125,23 @@ njs_symbol_for(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, rb_node = njs_rbtree_node_successor(&vm->global_symbols, rb_node); } - key = ++vm->symbol_generator; - - if (njs_slow_path(key >= UINT32_MAX)) { - njs_internal_error(vm, "Symbol generator overflow"); - return NJS_ERROR; - } - node = njs_mp_alloc(vm->mem_pool, sizeof(njs_rb_symbol_node_t)); if (njs_slow_path(node == NULL)) { njs_memory_error(vm); return NJS_ERROR; } - node->key = key; njs_value_assign(&node->name, value); + njs_set_symbol(retval, 0, &node->name); - njs_rbtree_insert(&vm->global_symbols, &node->node); + ret = njs_atom_symbol_add(vm, retval); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + node->key = retval->atom_id; - njs_set_symbol(retval, key, &node->name); + njs_rbtree_insert(&vm->global_symbols, &node->node); return NJS_OK; } @@ -229,56 +172,60 @@ njs_symbol_key_for(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_object_prop_t njs_symbol_constructor_properties[] = +static const njs_object_prop_init_t njs_symbol_constructor_properties[] = { NJS_DECLARE_PROP_LENGTH(0), NJS_DECLARE_PROP_NAME("Symbol"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_NATIVE("for", njs_symbol_for, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_for, njs_symbol_for, 1, 0), - NJS_DECLARE_PROP_NATIVE("keyFor", njs_symbol_key_for, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_keyFor, njs_symbol_key_for, 1, 0), - NJS_DECLARE_PROP_VALUE("asyncIterator", - njs_wellknown_symbol(NJS_SYMBOL_ASYNC_ITERATOR), 0), + NJS_DECLARE_PROP_VALUE(STRING_asyncIterator, + njs_symval(asyncIterator, "Symbol.asyncIterator"), + 0), - NJS_DECLARE_PROP_VALUE("hasInstance", - njs_wellknown_symbol(NJS_SYMBOL_HAS_INSTANCE), 0), + NJS_DECLARE_PROP_VALUE(STRING_hasInstance, + njs_symval(hasInstance, "Symbol.hasInstance"), + 0), - NJS_DECLARE_PROP_LVALUE("isConcatSpreadable", - njs_wellknown_symbol(NJS_SYMBOL_IS_CONCAT_SPREADABLE), 0), + NJS_DECLARE_PROP_VALUE(STRING_isConcatSpreadable, + njs_symval(isConcatSpreadable, "Symbol.isConcatSpreadable"), + 0), - NJS_DECLARE_PROP_VALUE("iterator", - njs_wellknown_symbol(NJS_SYMBOL_ITERATOR), 0), + NJS_DECLARE_PROP_VALUE(STRING_iterator, + njs_symval(iterator, "Symbol.iterator"), 0), - NJS_DECLARE_PROP_VALUE("match", - njs_wellknown_symbol(NJS_SYMBOL_MATCH), 0), + NJS_DECLARE_PROP_VALUE(STRING_match, njs_symval(match, "Symbol.match"), 0), - NJS_DECLARE_PROP_VALUE("matchAll", - njs_wellknown_symbol(NJS_SYMBOL_MATCH_ALL), 0), + NJS_DECLARE_PROP_VALUE(STRING_matchAll, + njs_symval(matchAll, "Symbol.matchAll"), 0), - NJS_DECLARE_PROP_VALUE("replace", - njs_wellknown_symbol(NJS_SYMBOL_REPLACE), 0), + NJS_DECLARE_PROP_VALUE(STRING_replace, + njs_symval(replace, "Symbol.replace"), 0), - NJS_DECLARE_PROP_VALUE("search", - njs_wellknown_symbol(NJS_SYMBOL_SEARCH), 0), + NJS_DECLARE_PROP_VALUE(STRING_search, + njs_symval(search, "Symbol.search"), 0), - NJS_DECLARE_PROP_VALUE("species", - njs_wellknown_symbol(NJS_SYMBOL_SPECIES), 0), + NJS_DECLARE_PROP_VALUE(STRING_species, + njs_symval(species, "Symbol.species"), 0), - NJS_DECLARE_PROP_VALUE("split", - njs_wellknown_symbol(NJS_SYMBOL_SPLIT), 0), + NJS_DECLARE_PROP_VALUE(STRING_split, njs_symval(split, "Symbol.split"), 0), - NJS_DECLARE_PROP_VALUE("toPrimitive", - njs_wellknown_symbol(NJS_SYMBOL_TO_PRIMITIVE), 0), + NJS_DECLARE_PROP_VALUE(STRING_toPrimitive, + njs_symval(toPrimitive, "Symbol.toPrimitive"), + 0), - NJS_DECLARE_PROP_VALUE("toStringTag", - njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), 0), + NJS_DECLARE_PROP_VALUE(STRING_toStringTag, + njs_symval(toStringTag, "Symbol.toStringTag"), 0), - NJS_DECLARE_PROP_VALUE("unscopables", - njs_wellknown_symbol(NJS_SYMBOL_UNSCOPABLES), 0), + NJS_DECLARE_PROP_VALUE(STRING_unscopables, + njs_symval(unscopables, "Symbol.unscopables"), + 0), }; @@ -347,27 +294,27 @@ njs_symbol_prototype_description(njs_vm_t *vm, njs_value_t *args, } -static const njs_object_prop_t njs_symbol_prototype_properties[] = +static const njs_object_prop_init_t njs_symbol_prototype_properties[] = { - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.value = njs_string("Symbol"), - .configurable = 1, - }, + NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, njs_ascii_strval("Symbol"), + NJS_OBJECT_PROP_VALUE_C), - NJS_DECLARE_PROP_HANDLER("__proto__", njs_primitive_prototype_get_proto, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING___proto__, + njs_primitive_prototype_get_proto, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_NATIVE("valueOf", njs_symbol_prototype_value_of, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_valueOf, njs_symbol_prototype_value_of, + 0, 0), - NJS_DECLARE_PROP_NATIVE("toString", njs_symbol_prototype_to_string, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toString, + njs_symbol_prototype_to_string, 0, 0), - NJS_DECLARE_PROP_GETTER("description", njs_symbol_prototype_description, 0), + NJS_DECLARE_PROP_GETTER(STRING_description, + njs_symbol_prototype_description, 0), }; diff --git a/src/njs_typed_array.c b/src/njs_typed_array.c index 5930dcb0..19399e3b 100644 --- a/src/njs_typed_array.c +++ b/src/njs_typed_array.c @@ -433,37 +433,22 @@ njs_typed_array_writable(njs_vm_t *vm, njs_typed_array_t *array) } -static const njs_value_t njs_typed_array_uint8_tag = njs_string("Uint8Array"); -static const njs_value_t njs_typed_array_uint8_clamped_tag = - njs_long_string("Uint8ClampedArray"); -static const njs_value_t njs_typed_array_int8_tag = njs_string("Int8Array"); -static const njs_value_t njs_typed_array_uint16_tag = - njs_string("Uint16Array"); -static const njs_value_t njs_typed_array_int16_tag = njs_string("Int16Array"); -static const njs_value_t njs_typed_array_uint32_tag = - njs_string("Uint32Array"); -static const njs_value_t njs_typed_array_int32_tag = njs_string("Int32Array"); -static const njs_value_t njs_typed_array_float32_tag = - njs_string("Float32Array"); -static const njs_value_t njs_typed_array_float64_tag = - njs_string("Float64Array"); - static njs_int_t njs_typed_array_get_string_tag(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { njs_value_t *this; - static const njs_value_t *tags[NJS_OBJ_TYPE_TYPED_ARRAY_SIZE] = { - &njs_typed_array_uint8_tag, - &njs_typed_array_uint8_clamped_tag, - &njs_typed_array_int8_tag, - &njs_typed_array_uint16_tag, - &njs_typed_array_int16_tag, - &njs_typed_array_uint32_tag, - &njs_typed_array_int32_tag, - &njs_typed_array_float32_tag, - &njs_typed_array_float64_tag, + static const uint32_t tags[NJS_OBJ_TYPE_TYPED_ARRAY_SIZE] = { + NJS_ATOM_STRING_Uint8Array, + NJS_ATOM_STRING_Uint8ClampedArray, + NJS_ATOM_STRING_Int8Array, + NJS_ATOM_STRING_Uint16Array, + NJS_ATOM_STRING_Int16Array, + NJS_ATOM_STRING_Uint32Array, + NJS_ATOM_STRING_Int32Array, + NJS_ATOM_STRING_Float32Array, + NJS_ATOM_STRING_Float64Array, }; this = njs_argument(args, 0); @@ -473,8 +458,8 @@ njs_typed_array_get_string_tag(njs_vm_t *vm, njs_value_t *args, return NJS_OK; } - njs_value_assign(retval, - tags[njs_typed_array_index(njs_typed_array(this)->type)]); + njs_atom_to_value(vm, retval, + tags[njs_typed_array_index(njs_typed_array(this)->type)]); return NJS_OK; } @@ -2062,11 +2047,15 @@ njs_typed_array_to_chain(njs_vm_t *vm, njs_chb_t *chain, uint32_t i; njs_string_prop_t separator; - if (sep == NULL) { - sep = njs_value_arg(&njs_string_comma); + if (sep != NULL && njs_is_string(sep)) { + (void) njs_string_prop(vm, &separator, sep); + + } else { + separator.start = (u_char *) ","; + separator.size = 1; + separator.length = 1; } - (void) njs_string_prop(&separator, sep); length = njs_typed_array_length(array); @@ -2110,10 +2099,7 @@ njs_typed_array_prototype_join(njs_vm_t *vm, njs_value_t *args, separator = njs_arg(args, nargs, 1); if (njs_slow_path(!njs_is_string(separator))) { - if (njs_is_undefined(separator)) { - separator = njs_value_arg(&njs_string_comma); - - } else { + if (njs_is_defined(separator)) { ret = njs_value_to_string(vm, separator, separator); if (njs_slow_path(ret != NJS_OK)) { return ret; @@ -2122,7 +2108,7 @@ njs_typed_array_prototype_join(njs_vm_t *vm, njs_value_t *args, } if (length == 0) { - njs_value_assign(retval, &njs_string_empty); + njs_set_empty_string(vm, retval); return NJS_OK; } @@ -2176,26 +2162,20 @@ njs_typed_array_constructor_intrinsic(njs_vm_t *vm, njs_value_t *args, } -static const njs_object_prop_t njs_typed_array_constructor_props[] = +static const njs_object_prop_init_t njs_typed_array_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(0), NJS_DECLARE_PROP_NAME("TypedArray"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - { - .type = NJS_ACCESSOR, - .name = njs_wellknown_symbol(NJS_SYMBOL_SPECIES), - .u.accessor = njs_getter(njs_typed_array_get_this, 0), - .writable = NJS_ATTRIBUTE_UNSET, - .configurable = 1, - .enumerable = 0, - }, + NJS_DECLARE_PROP_GETTER(SYMBOL_species, njs_typed_array_get_this, 0), - NJS_DECLARE_PROP_NATIVE("of", njs_typed_array_of, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_of, njs_typed_array_of, 0, 0), - NJS_DECLARE_PROP_NATIVE("from", njs_typed_array_from, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_from, njs_typed_array_from, 1, 0), }; @@ -2205,118 +2185,120 @@ static const njs_object_init_t njs_typed_array_constructor_init = { }; -static const njs_object_prop_t njs_typed_array_prototype_properties[] = +static const njs_object_prop_init_t njs_typed_array_prototype_properties[] = { - { - .type = NJS_ACCESSOR, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.accessor = njs_getter(njs_typed_array_get_string_tag, 0), - .writable = NJS_ATTRIBUTE_UNSET, - .configurable = 1, - .enumerable = 0, - }, + NJS_DECLARE_PROP_GETTER(SYMBOL_toStringTag, + njs_typed_array_get_string_tag, 0), - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_GETTER("buffer", njs_typed_array_prototype_buffer, 0), + NJS_DECLARE_PROP_GETTER(STRING_buffer, njs_typed_array_prototype_buffer, + 0), - NJS_DECLARE_PROP_GETTER("byteLength", + NJS_DECLARE_PROP_GETTER(STRING_byteLength, njs_typed_array_prototype_byte_length, 0), - NJS_DECLARE_PROP_GETTER("byteOffset", + NJS_DECLARE_PROP_GETTER(STRING_byteOffset, njs_typed_array_prototype_byte_offset, 0), - NJS_DECLARE_PROP_GETTER("length", njs_typed_array_prototype_length, 0), + NJS_DECLARE_PROP_GETTER(STRING_length, njs_typed_array_prototype_length, + 0), - NJS_DECLARE_PROP_NATIVE("copyWithin", + NJS_DECLARE_PROP_NATIVE(STRING_copyWithin, njs_typed_array_prototype_copy_within, 2, 0), - NJS_DECLARE_PROP_NATIVE("entries", + NJS_DECLARE_PROP_NATIVE(STRING_entries, njs_typed_array_prototype_iterator_obj, 0, NJS_ENUM_BOTH), - NJS_DECLARE_PROP_NATIVE("every", + NJS_DECLARE_PROP_NATIVE(STRING_every, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_EVERY), - NJS_DECLARE_PROP_NATIVE("filter", + NJS_DECLARE_PROP_NATIVE(STRING_filter, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_FILTER), - NJS_DECLARE_PROP_NATIVE("find", + NJS_DECLARE_PROP_NATIVE(STRING_find, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_FIND), - NJS_DECLARE_PROP_NATIVE("findIndex", + NJS_DECLARE_PROP_NATIVE(STRING_findIndex, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_FIND_INDEX), - NJS_DECLARE_PROP_NATIVE("forEach", + NJS_DECLARE_PROP_NATIVE(STRING_forEach, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_FOR_EACH), - NJS_DECLARE_PROP_NATIVE("includes", - njs_typed_array_prototype_index_of, 1, 1), + NJS_DECLARE_PROP_NATIVE(STRING_includes, + njs_typed_array_prototype_index_of, 1, 1), - NJS_DECLARE_PROP_NATIVE("indexOf", - njs_typed_array_prototype_index_of, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_indexOf, + njs_typed_array_prototype_index_of, 1, 0), - NJS_DECLARE_PROP_NATIVE("join", njs_typed_array_prototype_join, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_join, + njs_typed_array_prototype_join, 1, 0), - NJS_DECLARE_PROP_NATIVE("fill", njs_typed_array_prototype_fill, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_fill, + njs_typed_array_prototype_fill, 1, 0), - NJS_DECLARE_PROP_NATIVE("keys", njs_typed_array_prototype_iterator_obj, 0, + NJS_DECLARE_PROP_NATIVE(STRING_keys, + njs_typed_array_prototype_iterator_obj, 0, NJS_ENUM_KEYS), - NJS_DECLARE_PROP_NATIVE("lastIndexOf", + NJS_DECLARE_PROP_NATIVE(STRING_lastIndexOf, njs_typed_array_prototype_index_of, 1, 2), - NJS_DECLARE_PROP_NATIVE("map", + NJS_DECLARE_PROP_NATIVE(STRING_map, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_MAP), - NJS_DECLARE_PROP_NATIVE("reduce", njs_typed_array_prototype_reduce, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_reduce, + njs_typed_array_prototype_reduce, 1, 0), - NJS_DECLARE_PROP_NATIVE("reduceRight", njs_typed_array_prototype_reduce, - 1, 1), + NJS_DECLARE_PROP_NATIVE(STRING_reduceRight, + njs_typed_array_prototype_reduce, 1, 1), - NJS_DECLARE_PROP_NATIVE("reverse", njs_typed_array_prototype_reverse, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_reverse, + njs_typed_array_prototype_reverse, 0, 0), - NJS_DECLARE_PROP_NATIVE("set", njs_typed_array_prototype_set, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_set, + njs_typed_array_prototype_set, 2, 0), - NJS_DECLARE_PROP_NATIVE("slice", njs_typed_array_prototype_slice, 2, 1), + NJS_DECLARE_PROP_NATIVE(STRING_slice, + njs_typed_array_prototype_slice, 2, 1), - NJS_DECLARE_PROP_NATIVE("some", + NJS_DECLARE_PROP_NATIVE(STRING_some, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_SOME), - NJS_DECLARE_PROP_NATIVE("sort", njs_typed_array_prototype_sort, 1, 0), + NJS_DECLARE_PROP_NATIVE(STRING_sort, + njs_typed_array_prototype_sort, 1, 0), - NJS_DECLARE_PROP_NATIVE("subarray", njs_typed_array_prototype_slice, 2, 0), + NJS_DECLARE_PROP_NATIVE(STRING_subarray, + njs_typed_array_prototype_slice, 2, 0), - NJS_DECLARE_PROP_NATIVE("toReversed", njs_typed_array_prototype_reverse, 0, - 1), + NJS_DECLARE_PROP_NATIVE(STRING_toReversed, + njs_typed_array_prototype_reverse, 0, 1), - NJS_DECLARE_PROP_NATIVE("toSorted", njs_typed_array_prototype_sort, 1, 1), + NJS_DECLARE_PROP_NATIVE(STRING_toSorted, + njs_typed_array_prototype_sort, 1, 1), - NJS_DECLARE_PROP_NATIVE("toString", njs_array_prototype_to_string, 0, 0), + NJS_DECLARE_PROP_NATIVE(STRING_toString, njs_array_prototype_to_string, + 0, 0), - NJS_DECLARE_PROP_NATIVE("values", njs_typed_array_prototype_iterator_obj, - 0, NJS_ENUM_VALUES), + NJS_DECLARE_PROP_NATIVE(STRING_values, + njs_typed_array_prototype_iterator_obj, 0, + NJS_ENUM_VALUES), - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_ITERATOR), - .u.value = njs_native_function2(njs_typed_array_prototype_iterator_obj, - 0, NJS_ENUM_VALUES), - .writable = 1, - .configurable = 1, - }, + NJS_DECLARE_PROP_NATIVE(SYMBOL_iterator, + njs_typed_array_prototype_iterator_obj, 0, + NJS_ENUM_VALUES), }; - static const njs_object_init_t njs_typed_array_prototype_init = { njs_typed_array_prototype_properties, njs_nitems(njs_typed_array_prototype_properties), @@ -2413,13 +2395,14 @@ memory_error: } -static const njs_object_prop_t njs_data_view_constructor_props[] = +static const njs_object_prop_init_t njs_data_view_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("DataView"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), }; @@ -2658,74 +2641,71 @@ njs_data_view_prototype_set(njs_vm_t *vm, njs_value_t *args, } -static const njs_object_prop_t njs_data_view_prototype_properties[] = +static const njs_object_prop_init_t njs_data_view_prototype_properties[] = { - { - .type = NJS_PROPERTY, - .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG), - .u.value = njs_string("DataView"), - .configurable = 1, - }, + NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, njs_ascii_strval("DataView"), + NJS_OBJECT_PROP_VALUE_C), - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_GETTER("buffer", njs_typed_array_prototype_buffer, 0), + NJS_DECLARE_PROP_GETTER(STRING_buffer, njs_typed_array_prototype_buffer, + 0), - NJS_DECLARE_PROP_GETTER("byteLength", + NJS_DECLARE_PROP_GETTER(STRING_byteLength, njs_typed_array_prototype_byte_length, 0), - NJS_DECLARE_PROP_GETTER("byteOffset", + NJS_DECLARE_PROP_GETTER(STRING_byteOffset, njs_typed_array_prototype_byte_offset, 0), - NJS_DECLARE_PROP_NATIVE("getUint8", njs_data_view_prototype_get, 1, + NJS_DECLARE_PROP_NATIVE(STRING_getUint8, njs_data_view_prototype_get, 1, NJS_OBJ_TYPE_UINT8_ARRAY), - NJS_DECLARE_PROP_NATIVE("getInt8", njs_data_view_prototype_get, 1, + NJS_DECLARE_PROP_NATIVE(STRING_getInt8, njs_data_view_prototype_get, 1, NJS_OBJ_TYPE_INT8_ARRAY), - NJS_DECLARE_PROP_NATIVE("getUint16", njs_data_view_prototype_get, 1, - NJS_OBJ_TYPE_UINT16_ARRAY), + NJS_DECLARE_PROP_NATIVE(STRING_getUint16, njs_data_view_prototype_get, + 1, NJS_OBJ_TYPE_UINT16_ARRAY), - NJS_DECLARE_PROP_NATIVE("getInt16", njs_data_view_prototype_get, 1, + NJS_DECLARE_PROP_NATIVE(STRING_getInt16, njs_data_view_prototype_get, 1, NJS_OBJ_TYPE_INT16_ARRAY), - NJS_DECLARE_PROP_NATIVE("getUint32", njs_data_view_prototype_get, 1, - NJS_OBJ_TYPE_UINT32_ARRAY), + NJS_DECLARE_PROP_NATIVE(STRING_getUint32, njs_data_view_prototype_get, + 1, NJS_OBJ_TYPE_UINT32_ARRAY), - NJS_DECLARE_PROP_NATIVE("getInt32", njs_data_view_prototype_get, 1, + NJS_DECLARE_PROP_NATIVE(STRING_getInt32, njs_data_view_prototype_get, 1, NJS_OBJ_TYPE_INT32_ARRAY), - NJS_DECLARE_PROP_NATIVE("getFloat32", njs_data_view_prototype_get, 1, - NJS_OBJ_TYPE_FLOAT32_ARRAY), + NJS_DECLARE_PROP_NATIVE(STRING_getFloat32, njs_data_view_prototype_get, + 1, NJS_OBJ_TYPE_FLOAT32_ARRAY), - NJS_DECLARE_PROP_NATIVE("getFloat64", njs_data_view_prototype_get, 1, - NJS_OBJ_TYPE_FLOAT64_ARRAY), + NJS_DECLARE_PROP_NATIVE(STRING_getFloat64, njs_data_view_prototype_get, + 1, NJS_OBJ_TYPE_FLOAT64_ARRAY), - NJS_DECLARE_PROP_NATIVE("setUint8", njs_data_view_prototype_set, 2, + NJS_DECLARE_PROP_NATIVE(STRING_setUint8, njs_data_view_prototype_set, 2, NJS_OBJ_TYPE_UINT8_ARRAY), - NJS_DECLARE_PROP_NATIVE("setInt8", njs_data_view_prototype_set, 2, + NJS_DECLARE_PROP_NATIVE(STRING_setInt8, njs_data_view_prototype_set, 2, NJS_OBJ_TYPE_INT8_ARRAY), - NJS_DECLARE_PROP_NATIVE("setUint16", njs_data_view_prototype_set, 2, - NJS_OBJ_TYPE_UINT16_ARRAY), + NJS_DECLARE_PROP_NATIVE(STRING_setUint16, njs_data_view_prototype_set, + 2, NJS_OBJ_TYPE_UINT16_ARRAY), - NJS_DECLARE_PROP_NATIVE("setInt16", njs_data_view_prototype_set, 2, + NJS_DECLARE_PROP_NATIVE(STRING_setInt16, njs_data_view_prototype_set, 2, NJS_OBJ_TYPE_INT16_ARRAY), - NJS_DECLARE_PROP_NATIVE("setUint32", njs_data_view_prototype_set, 2, - NJS_OBJ_TYPE_UINT32_ARRAY), + NJS_DECLARE_PROP_NATIVE(STRING_setUint32, njs_data_view_prototype_set, + 2, NJS_OBJ_TYPE_UINT32_ARRAY), - NJS_DECLARE_PROP_NATIVE("setInt32", njs_data_view_prototype_set, 2, + NJS_DECLARE_PROP_NATIVE(STRING_setInt32, njs_data_view_prototype_set, 2, NJS_OBJ_TYPE_INT32_ARRAY), - NJS_DECLARE_PROP_NATIVE("setFloat32", njs_data_view_prototype_set, 2, - NJS_OBJ_TYPE_FLOAT32_ARRAY), + NJS_DECLARE_PROP_NATIVE(STRING_setFloat32, njs_data_view_prototype_set, + 2, NJS_OBJ_TYPE_FLOAT32_ARRAY), - NJS_DECLARE_PROP_NATIVE("setFloat64", njs_data_view_prototype_set, 2, - NJS_OBJ_TYPE_FLOAT64_ARRAY), + NJS_DECLARE_PROP_NATIVE(STRING_setFloat64, njs_data_view_prototype_set, + 2, NJS_OBJ_TYPE_FLOAT64_ARRAY), }; @@ -2743,16 +2723,17 @@ const njs_object_type_init_t njs_data_view_type_init = { }; -static const njs_object_prop_t njs_typed_array_u8_constructor_props[] = +static const njs_object_prop_init_t njs_typed_array_u8_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Uint8Array"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 1), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 1), 0), }; @@ -2762,14 +2743,14 @@ static const njs_object_init_t njs_typed_array_u8_constructor_init = { }; -static const njs_object_prop_t njs_typed_array_u8_prototype_properties[] = +static const njs_object_prop_init_t njs_typed_array_u8_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 1), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 1), 0), }; @@ -2788,21 +2769,18 @@ const njs_object_type_init_t njs_typed_array_u8_type_init = { }; -static const njs_object_prop_t njs_typed_array_u8c_constructor_props[] = +static const njs_object_prop_init_t njs_typed_array_u8c_constructor_props[] = { - { - .type = NJS_PROPERTY, - .name = njs_string("name"), - .u.value = njs_long_string("Uint8ClampedArray"), - .configurable = 1, - }, + NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval("Uint8ClampedArray"), + NJS_OBJECT_PROP_VALUE_C), NJS_DECLARE_PROP_LENGTH(3), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 1), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 1), 0), }; @@ -2812,14 +2790,14 @@ static const njs_object_init_t njs_typed_array_u8c_constructor_init = { }; -static const njs_object_prop_t njs_typed_array_u8c_prototype_properties[] = +static const njs_object_prop_init_t njs_typed_array_u8c_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 1), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 1), 0), }; @@ -2838,16 +2816,17 @@ const njs_object_type_init_t njs_typed_array_u8clamped_type_init = { }; -static const njs_object_prop_t njs_typed_array_i8_constructor_props[] = +static const njs_object_prop_init_t njs_typed_array_i8_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Int8Array"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 1), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 1), 0), }; @@ -2857,14 +2836,14 @@ static const njs_object_init_t njs_typed_array_i8_constructor_init = { }; -static const njs_object_prop_t njs_typed_array_i8_prototype_properties[] = +static const njs_object_prop_init_t njs_typed_array_i8_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 1), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 1), 0), }; @@ -2883,16 +2862,17 @@ const njs_object_type_init_t njs_typed_array_i8_type_init = { }; -static const njs_object_prop_t njs_typed_array_u16_constructor_props[] = +static const njs_object_prop_init_t njs_typed_array_u16_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Uint16Array"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 2), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 2), 0), }; @@ -2902,14 +2882,14 @@ static const njs_object_init_t njs_typed_array_u16_constructor_init = { }; -static const njs_object_prop_t njs_typed_array_u16_prototype_properties[] = +static const njs_object_prop_init_t njs_typed_array_u16_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 2), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 2), 0), }; @@ -2928,16 +2908,17 @@ const njs_object_type_init_t njs_typed_array_u16_type_init = { }; -static const njs_object_prop_t njs_typed_array_i16_constructor_props[] = +static const njs_object_prop_init_t njs_typed_array_i16_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Int16Array"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 2), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 2), 0), }; @@ -2947,14 +2928,14 @@ static const njs_object_init_t njs_typed_array_i16_constructor_init = { }; -static const njs_object_prop_t njs_typed_array_i16_prototype_properties[] = +static const njs_object_prop_init_t njs_typed_array_i16_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 2), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 2), 0), }; @@ -2973,16 +2954,17 @@ const njs_object_type_init_t njs_typed_array_i16_type_init = { }; -static const njs_object_prop_t njs_typed_array_u32_constructor_props[] = +static const njs_object_prop_init_t njs_typed_array_u32_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Uint32Array"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 4), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 4), 0), }; @@ -2992,14 +2974,14 @@ static const njs_object_init_t njs_typed_array_u32_constructor_init = { }; -static const njs_object_prop_t njs_typed_array_u32_prototype_properties[] = +static const njs_object_prop_init_t njs_typed_array_u32_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 4), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 4), 0), }; @@ -3018,16 +3000,17 @@ const njs_object_type_init_t njs_typed_array_u32_type_init = { }; -static const njs_object_prop_t njs_typed_array_i32_constructor_props[] = +static const njs_object_prop_init_t njs_typed_array_i32_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Int32Array"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 4), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 4), 0), }; @@ -3037,14 +3020,14 @@ static const njs_object_init_t njs_typed_array_i32_constructor_init = { }; -static const njs_object_prop_t njs_typed_array_i32_prototype_properties[] = +static const njs_object_prop_init_t njs_typed_array_i32_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 4), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 4), 0), }; @@ -3063,16 +3046,17 @@ const njs_object_type_init_t njs_typed_array_i32_type_init = { }; -static const njs_object_prop_t njs_typed_array_f32_constructor_props[] = +static const njs_object_prop_init_t njs_typed_array_f32_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Float32Array"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, + 0, 0), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 4), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 4), 0), }; @@ -3082,14 +3066,14 @@ static const njs_object_init_t njs_typed_array_f32_constructor_init = { }; -static const njs_object_prop_t njs_typed_array_f32_prototype_properties[] = +static const njs_object_prop_init_t njs_typed_array_f32_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 4), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 4), 0), }; @@ -3108,16 +3092,17 @@ const njs_object_type_init_t njs_typed_array_f32_type_init = { }; -static const njs_object_prop_t njs_typed_array_f64_constructor_props[] = +static const njs_object_prop_init_t njs_typed_array_f64_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Float64Array"), - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), + NJS_DECLARE_PROP_HANDLER(STRING_prototype, + njs_object_prototype_create, 0, 0), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 8), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 8), 0), }; @@ -3127,14 +3112,14 @@ static const njs_object_init_t njs_typed_array_f64_constructor_init = { }; -static const njs_object_prop_t njs_typed_array_f64_prototype_properties[] = +static const njs_object_prop_init_t njs_typed_array_f64_prototype_properties[] = { - NJS_DECLARE_PROP_HANDLER("constructor", - njs_object_prototype_create_constructor, - 0, 0, NJS_OBJECT_PROP_VALUE_CW), + NJS_DECLARE_PROP_HANDLER(STRING_constructor, + njs_object_prototype_create_constructor, 0, + NJS_OBJECT_PROP_VALUE_CW), - NJS_DECLARE_PROP_LVALUE("BYTES_PER_ELEMENT", njs_value(NJS_NUMBER, 1, 8), - 0), + NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, + njs_value(NJS_NUMBER, 1, 8), 0), }; diff --git a/src/njs_value.c b/src/njs_value.c index a575f9af..dcdab5a2 100644 --- a/src/njs_value.c +++ b/src/njs_value.c @@ -9,10 +9,10 @@ static njs_int_t njs_object_property_query(njs_vm_t *vm, - njs_property_query_t *pq, njs_object_t *object, - const njs_value_t *key); + njs_property_query_t *pq, njs_object_t *object, uint32_t atom_id); static njs_int_t njs_array_property_query(njs_vm_t *vm, - njs_property_query_t *pq, njs_array_t *array, uint32_t index); + njs_property_query_t *pq, njs_array_t *array, uint32_t index, + uint32_t atom_id); static njs_int_t njs_typed_array_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_typed_array_t *array, uint32_t index); static njs_int_t njs_string_property_query(njs_vm_t *vm, @@ -29,35 +29,6 @@ const njs_value_t njs_value_zero = njs_value(NJS_NUMBER, 0, 0.0); const njs_value_t njs_value_nan = njs_value(NJS_NUMBER, 0, NAN); const njs_value_t njs_value_invalid = njs_value(NJS_INVALID, 0, 0.0); -const njs_value_t njs_string_empty = njs_string(""); -const njs_value_t njs_string_empty_regexp = - njs_string("(?:)"); -const njs_value_t njs_string_comma = njs_string(","); -const njs_value_t njs_string_null = njs_string("null"); -const njs_value_t njs_string_undefined = njs_string("undefined"); -const njs_value_t njs_string_boolean = njs_string("boolean"); -const njs_value_t njs_string_false = njs_string("false"); -const njs_value_t njs_string_true = njs_string("true"); -const njs_value_t njs_string_number = njs_string("number"); -const njs_value_t njs_string_minus_zero = njs_string("-0"); -const njs_value_t njs_string_minus_infinity = - njs_string("-Infinity"); -const njs_value_t njs_string_plus_infinity = - njs_string("Infinity"); -const njs_value_t njs_string_nan = njs_string("NaN"); -const njs_value_t njs_string_symbol = njs_string("symbol"); -const njs_value_t njs_string_string = njs_string("string"); -const njs_value_t njs_string_name = njs_string("name"); -const njs_value_t njs_string_data = njs_string("data"); -const njs_value_t njs_string_type = njs_string("type"); -const njs_value_t njs_string_external = njs_string("external"); -const njs_value_t njs_string_invalid = njs_string("invalid"); -const njs_value_t njs_string_object = njs_string("object"); -const njs_value_t njs_string_function = njs_string("function"); -const njs_value_t njs_string_anonymous = njs_string("anonymous"); -const njs_value_t njs_string_memory_error = njs_string("MemoryError"); - - /* * A hint value is 0 for numbers and 1 for strings. The value chooses * method calls order specified by ECMAScript 5.1: "valueOf", "toString" @@ -68,22 +39,16 @@ njs_int_t njs_value_to_primitive(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value, njs_uint_t hint) { - njs_int_t ret; - njs_uint_t tries; - njs_value_t method, retval; - njs_lvlhsh_query_t lhq; - - static const uint32_t hashes[] = { - NJS_VALUE_OF_HASH, - NJS_TO_STRING_HASH, - }; - - static const njs_str_t names[] = { - njs_str("valueOf"), - njs_str("toString"), + njs_int_t ret; + njs_uint_t tries; + njs_value_t method, retval; + njs_flathsh_query_t lhq; + + static const uint32_t atoms[] = { + NJS_ATOM_STRING_valueOf, + NJS_ATOM_STRING_toString, }; - if (njs_is_primitive(value)) { *dst = *value; return NJS_OK; @@ -98,8 +63,7 @@ njs_value_to_primitive(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value, if (njs_is_object(value) && tries < 2) { hint ^= tries++; - lhq.key_hash = hashes[hint]; - lhq.key = names[hint]; + lhq.key_hash = atoms[hint]; ret = njs_object_property(vm, njs_object(value), &lhq, &method); @@ -207,7 +171,7 @@ njs_value_own_enumerate(njs_vm_t *vm, njs_value_t *value, uint32_t flags) dst = values->start; while (k < end) { - ret = njs_value_property(vm, value, k++, dst++); + ret = njs_value_property_val(vm, value, k++, dst++); if (njs_slow_path(ret != NJS_OK)) { return NULL; } @@ -234,7 +198,7 @@ njs_value_own_enumerate(njs_vm_t *vm, njs_value_t *value, uint32_t flags) return NULL; } - ret = njs_value_property(vm, value, k, &entry->start[1]); + ret = njs_value_property_val(vm, value, k, &entry->start[1]); if (njs_slow_path(ret != NJS_OK)) { return NULL; } @@ -265,14 +229,11 @@ njs_value_of(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval) njs_int_t ret; - static const njs_value_t value_of = njs_string("valueOf"); - if (njs_slow_path(!njs_is_object(value))) { return NJS_DECLINED; } - ret = njs_value_property(vm, value, njs_value_arg(&value_of), - retval); + ret = njs_value_property(vm, value, NJS_ATOM_STRING_valueOf, retval); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -292,7 +253,7 @@ njs_value_length(njs_vm_t *vm, njs_value_t *value, int64_t *length) njs_string_prop_t string_prop; if (njs_is_string(value)) { - *length = njs_string_prop(&string_prop, value); + *length = njs_string_prop(vm, &string_prop, value); } else if (njs_is_primitive(value)) { *length = 0; @@ -595,15 +556,15 @@ njs_value_is_data_view(const njs_value_t *value) njs_int_t njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *value, - njs_value_t *key) + uint32_t atom_id) { - double num; uint32_t index; njs_int_t ret; + njs_value_t key; njs_object_t *obj; njs_function_t *function; - njs_assert(njs_is_index_or_key(key)); + njs_assert(atom_id != NJS_ATOM_STRING_unknown); switch (value->type) { case NJS_BOOLEAN: @@ -614,11 +575,9 @@ njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *value, break; case NJS_STRING: - if (njs_fast_path(!njs_is_null_or_undefined_or_boolean(key))) { - num = njs_key_to_index(key); - if (njs_fast_path(njs_key_is_integer_index(num, key))) { - return njs_string_property_query(vm, pq, value, num); - } + if (njs_atom_is_number(atom_id)) { + return njs_string_property_query(vm, pq, value, + njs_atom_number(atom_id)); } obj = &vm->string_object; @@ -648,10 +607,10 @@ njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *value, case NJS_UNDEFINED: case NJS_NULL: default: - ret = njs_primitive_value_to_string(vm, &pq->key, key); + ret = njs_atom_to_value(vm, &key, atom_id); if (njs_fast_path(ret == NJS_OK)) { - njs_string_get(&pq->key, &pq->lhq.key); + njs_string_get(vm, &key, &pq->lhq.key); njs_type_error(vm, "cannot get property \"%V\" of %s", &pq->lhq.key, njs_is_null(value) ? "null" : "undefined"); @@ -664,41 +623,24 @@ njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *value, return NJS_ERROR; } - ret = njs_primitive_value_to_key(vm, &pq->key, key); - - if (njs_fast_path(ret == NJS_OK)) { + ret = njs_object_property_query(vm, pq, obj, atom_id); - if (njs_is_symbol(key)) { - pq->lhq.key_hash = njs_symbol_key(key); - pq->lhq.key.start = NULL; - - } else { - njs_string_get(&pq->key, &pq->lhq.key); - - if (pq->lhq.key_hash == 0) { - pq->lhq.key_hash = njs_djb_hash(pq->lhq.key.start, - pq->lhq.key.length); - } - } - - ret = njs_object_property_query(vm, pq, obj, key); - - if (njs_slow_path(ret == NJS_DECLINED && obj->slots != NULL)) { - return njs_external_property_query(vm, pq, value); - } + if (njs_slow_path(ret == NJS_DECLINED && obj->slots != NULL)) { + return njs_external_property_query(vm, pq, value); } return ret; } -static njs_int_t +njs_inline njs_int_t njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, - njs_object_t *object, const njs_value_t *key) + njs_object_t *object, uint32_t atom_id) { double num; njs_int_t ret; njs_bool_t own; + njs_value_t key; njs_array_t *array; njs_object_t *proto; njs_object_prop_t *prop; @@ -716,10 +658,24 @@ njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, switch (proto->type) { case NJS_ARRAY: array = (njs_array_t *) proto; - num = njs_key_to_index(key); - if (njs_fast_path(njs_key_is_integer_index(num, key))) { - ret = njs_array_property_query(vm, pq, array, num); + if (njs_fast_path(njs_atom_is_number(atom_id))) { + ret = njs_array_property_query(vm, pq, array, + njs_atom_number(atom_id), atom_id); + if (njs_fast_path(ret != NJS_DECLINED)) { + return (ret == NJS_DONE) ? NJS_DECLINED : ret; + } + } + + ret = njs_atom_to_value(vm, &key, atom_id); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + num = njs_key_to_index(&key); + + if (njs_key_is_integer_index(num, &key)) { + ret = njs_array_property_query(vm, pq, array, num, atom_id); if (njs_fast_path(ret != NJS_DECLINED)) { return (ret == NJS_DONE) ? NJS_DECLINED : ret; } @@ -728,12 +684,19 @@ njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, break; case NJS_TYPED_ARRAY: - num = njs_key_to_index(key); - if (njs_fast_path(njs_key_is_integer_index(num, key))) { + if (njs_fast_path(njs_atom_is_number(atom_id))) { tarray = (njs_typed_array_t *) proto; - return njs_typed_array_property_query(vm, pq, tarray, num); + return njs_typed_array_property_query(vm, pq, tarray, + njs_atom_number(atom_id)); } + ret = njs_atom_to_value(vm, &key, atom_id); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + num = njs_key_to_index(&key); + if (!isnan(num)) { return NJS_DECLINED; } @@ -746,10 +709,10 @@ njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, break; } - num = njs_key_to_index(key); - if (njs_fast_path(njs_key_is_integer_index(num, key))) { + if (njs_fast_path(njs_atom_is_number(atom_id))) { ov = (njs_object_value_t *) proto; - ret = njs_string_property_query(vm, pq, &ov->value, num); + ret = njs_string_property_query(vm, pq, &ov->value, + njs_atom_number(atom_id)); if (njs_fast_path(ret != NJS_DECLINED)) { return ret; } @@ -761,7 +724,9 @@ njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, break; } - ret = njs_lvlhsh_find(&proto->hash, &pq->lhq); + pq->lhq.key_hash = atom_id; + + ret = njs_flathsh_unique_find(&proto->hash, &pq->lhq); if (ret == NJS_OK) { prop = pq->lhq.value; @@ -775,8 +740,7 @@ njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, } } else { - ret = njs_lvlhsh_find(&proto->shared_hash, &pq->lhq); - + ret = njs_flathsh_unique_find(&proto->shared_hash, &pq->lhq); if (ret == NJS_OK) { return njs_prop_private_copy(vm, pq, proto); } @@ -797,7 +761,7 @@ njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, static njs_int_t njs_array_property_query(njs_vm_t *vm, njs_property_query_t *pq, - njs_array_t *array, uint32_t index) + njs_array_t *array, uint32_t index, uint32_t atom_id) { int64_t length; uint64_t size; @@ -858,7 +822,9 @@ njs_array_property_query(njs_vm_t *vm, njs_property_query_t *pq, } } - ret = njs_lvlhsh_find(&array->object.hash, &pq->lhq); + pq->lhq.key_hash = atom_id; + + ret = njs_flathsh_unique_find(&array->object.hash, &pq->lhq); if (ret == NJS_OK) { prop = pq->lhq.value; @@ -901,8 +867,6 @@ prop: prop->type = resized ? NJS_PROPERTY_PLACE_REF : NJS_PROPERTY_REF; } - njs_set_number(&prop->name, index); - prop->writable = 1; prop->enumerable = 1; prop->configurable = 1; @@ -963,7 +927,7 @@ njs_string_property_query(njs_vm_t *vm, njs_property_query_t *pq, slice.start = index; slice.length = 1; - slice.string_length = njs_string_prop(&string, object); + slice.string_length = njs_string_prop(vm, &string, object); if (slice.start < slice.string_length) { /* @@ -979,12 +943,6 @@ njs_string_property_query(njs_vm_t *vm, njs_property_query_t *pq, pq->lhq.value = prop; - if (pq->query != NJS_PROPERTY_QUERY_GET) { - /* pq->lhq.key is used by NJS_VMCODE_PROPERTY_SET for TypeError */ - njs_uint32_to_string(&pq->key, index); - njs_string_get(&pq->key, &pq->lhq.key); - } - return NJS_OK; } @@ -1018,7 +976,6 @@ njs_external_property_query(njs_vm_t *vm, njs_property_query_t *pq, */ njs_prop_magic32(prop) = slots->magic32; - prop->name = pq->key; pq->lhq.value = prop; @@ -1029,7 +986,8 @@ njs_external_property_query(njs_vm_t *vm, njs_property_query_t *pq, switch (pq->query) { case NJS_PROPERTY_QUERY_GET: - return slots->prop_handler(vm, prop, value, NULL, njs_prop_value(prop)); + return slots->prop_handler(vm, prop, pq->lhq.key_hash, value, NULL, + njs_prop_value(prop)); case NJS_PROPERTY_QUERY_SET: if (slots->writable == 0) { @@ -1054,10 +1012,9 @@ njs_external_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_int_t -njs_value_property(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, +njs_value_property(njs_vm_t *vm, njs_value_t *value, uint32_t atom_id, njs_value_t *retval) { - double num; uint32_t index; njs_int_t ret; njs_array_t *array; @@ -1065,16 +1022,8 @@ njs_value_property(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, njs_typed_array_t *tarray; njs_property_query_t pq; - njs_assert(njs_is_index_or_key(key)); - - if (njs_fast_path(njs_is_number(key))) { - num = njs_number(key); - - if (njs_slow_path(!njs_number_is_integer_index(num))) { - goto slow_path; - } - - index = (uint32_t) num; + if (njs_fast_path(njs_atom_is_number(atom_id))) { + index = njs_atom_number(atom_id); if (njs_is_typed_array(value)) { tarray = njs_typed_array(value); @@ -1116,9 +1065,9 @@ njs_value_property(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, slow_path: - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0, 0); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); - ret = njs_property_query(vm, &pq, value, key); + ret = njs_property_query(vm, &pq, value, atom_id); switch (ret) { @@ -1144,7 +1093,7 @@ slow_path: case NJS_PROPERTY_HANDLER: pq.scratch = *prop; prop = &pq.scratch; - ret = njs_prop_handler(prop)(vm, prop, value, NULL, + ret = njs_prop_handler(prop)(vm, prop, atom_id, value, NULL, njs_prop_value(prop)); if (njs_slow_path(ret != NJS_OK)) { @@ -1185,32 +1134,21 @@ slow_path: njs_int_t -njs_value_property_set(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, +njs_value_property_set(njs_vm_t *vm, njs_value_t *value, uint32_t atom_id, njs_value_t *setval) { - double num; uint32_t index; njs_int_t ret; njs_array_t *array; - njs_value_t retval; - njs_flathsh_elt_t *elt; + njs_value_t retval, key; njs_object_prop_t *prop; njs_typed_array_t *tarray; + njs_flathsh_elt_t *elt; njs_flathsh_descr_t *h; njs_property_query_t pq; - static const njs_str_t length_key = njs_str("length"); - - njs_assert(njs_is_index_or_key(key)); - - if (njs_fast_path(njs_is_number(key))) { - num = njs_number(key); - - if (njs_slow_path(!njs_number_is_integer_index(num))) { - goto slow_path; - } - - index = (uint32_t) num; + if (njs_fast_path(njs_atom_is_number(atom_id))) { + index = njs_atom_number(atom_id); if (njs_is_typed_array(value)) { tarray = njs_typed_array(value); @@ -1249,9 +1187,9 @@ slow_path: return NJS_ERROR; } - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 0, 0); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 0); - ret = njs_property_query(vm, &pq, value, key); + ret = njs_property_query(vm, &pq, value, atom_id); switch (ret) { @@ -1260,7 +1198,7 @@ slow_path: if (njs_is_data_descriptor(prop)) { if (!prop->writable) { - njs_key_string_get(vm, &pq.key, &pq.lhq.key); + njs_atom_string_get(vm, atom_id, &pq.lhq.key); njs_type_error(vm, "Cannot assign to read-only property \"%V\" of %s", &pq.lhq.key, njs_type_string(value->type)); @@ -1273,7 +1211,7 @@ slow_path: value, setval, 1, &retval); } - njs_key_string_get(vm, &pq.key, &pq.lhq.key); + njs_atom_string_get(vm, atom_id, &pq.lhq.key); njs_type_error(vm, "Cannot set property \"%V\" of %s which has only a getter", &pq.lhq.key, njs_type_string(value->type)); @@ -1281,7 +1219,8 @@ slow_path: } if (prop->type == NJS_PROPERTY_HANDLER) { - ret = njs_prop_handler(prop)(vm, prop, value, setval, &retval); + ret = njs_prop_handler(prop)(vm, prop, atom_id, value, + setval, &retval); if (njs_slow_path(ret != NJS_DECLINED)) { return ret; } @@ -1291,10 +1230,8 @@ slow_path: switch (prop->type) { case NJS_PROPERTY: if (njs_is_array(value)) { - if (njs_slow_path(pq.lhq.key_hash == NJS_LENGTH_HASH)) { - if (njs_strstr_eq(&pq.lhq.key, &length_key)) { - return njs_array_length_set(vm, value, prop, setval); - } + if (njs_slow_path(atom_id == NJS_ATOM_STRING_length)) { + return njs_array_length_set(vm, value, prop, setval); } } @@ -1340,7 +1277,7 @@ slow_path: pq.lhq.pool = vm->mem_pool; - int rc = njs_lvlhsh_delete(pq.own_whiteout, &pq.lhq); + int rc = njs_flathsh_unique_delete(pq.own_whiteout, &pq.lhq); if (rc != NJS_OK) { return NJS_ERROR; } @@ -1374,10 +1311,16 @@ slow_path: } if (njs_slow_path(pq.own && njs_is_typed_array(value) - && njs_is_string(key))) + && !njs_atom_is_number(atom_id))) { /* Integer-Indexed Exotic Objects [[DefineOwnProperty]]. */ - if (!isnan(njs_string_to_index(key))) { + + ret = njs_atom_to_value(vm, &key, atom_id); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (!isnan(njs_string_to_index(&key))) { return NJS_OK; } } @@ -1394,16 +1337,17 @@ slow_path: goto fail; } - prop = njs_object_prop_alloc(vm, &pq.key, &njs_value_undefined, 1); + prop = njs_object_prop_alloc(vm, &njs_value_undefined, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } pq.lhq.replace = 0; pq.lhq.value = prop; + pq.lhq.key_hash = atom_id; pq.lhq.pool = vm->mem_pool; - ret = njs_lvlhsh_insert(njs_object_hash(value), &pq.lhq); + ret = njs_flathsh_unique_insert(njs_object_hash(value), &pq.lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; @@ -1417,7 +1361,7 @@ found: fail: - njs_key_string_get(vm, &pq.key, &pq.lhq.key); + njs_atom_string_get(vm, atom_id, &pq.lhq.key); njs_type_error(vm, "Cannot add property \"%V\", object is not extensible", &pq.lhq.key); @@ -1426,30 +1370,21 @@ fail: njs_int_t -njs_value_property_delete(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, +njs_value_property_delete(njs_vm_t *vm, njs_value_t *value, uint32_t atom_id, njs_value_t *removed, njs_bool_t thrw) { - double num; uint32_t index; njs_int_t ret; njs_array_t *array; njs_object_prop_t *prop; njs_property_query_t pq; - njs_assert(njs_is_index_or_key(key)); - - if (njs_fast_path(njs_is_number(key))) { + if (njs_fast_path(njs_atom_is_number(atom_id))) { if (njs_slow_path(!(njs_is_fast_array(value)))) { goto slow_path; } - num = njs_number(key); - - if (njs_slow_path(!njs_number_is_integer_index(num))) { - goto slow_path; - } - - index = (uint32_t) num; + index = (uint32_t) njs_atom_number(atom_id); array = njs_array(value); @@ -1464,9 +1399,9 @@ njs_value_property_delete(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, slow_path: - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_DELETE, 0, 1); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_DELETE, 1); - ret = njs_property_query(vm, &pq, value, key); + ret = njs_property_query(vm, &pq, value, atom_id); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -1475,7 +1410,7 @@ slow_path: if (njs_slow_path(!prop->configurable)) { if (thrw) { - njs_key_string_get(vm, &pq.key, &pq.lhq.key); + njs_atom_string_get(vm, atom_id, &pq.lhq.key); njs_type_error(vm, "Cannot delete property \"%V\" of %s", &pq.lhq.key, njs_type_string(value->type)); return NJS_ERROR; @@ -1487,7 +1422,8 @@ slow_path: switch (prop->type) { case NJS_PROPERTY_HANDLER: if (njs_is_object(value) && njs_object_slots(value) != NULL) { - ret = njs_prop_handler(prop)(vm, prop, value, NULL, NULL); + ret = njs_prop_handler(prop)(vm, prop, atom_id, value, NULL, + NULL); if (njs_slow_path(ret != NJS_DECLINED)) { return ret; } @@ -1550,16 +1486,22 @@ njs_primitive_value_to_string(njs_vm_t *vm, njs_value_t *dst, switch (src->type) { case NJS_NULL: - value = &njs_string_null; - break; + njs_atom_to_value(vm, dst, NJS_ATOM_STRING_null); + return NJS_OK; case NJS_UNDEFINED: - value = &njs_string_undefined; - break; + njs_atom_to_value(vm, dst, NJS_ATOM_STRING_undefined); + return NJS_OK; case NJS_BOOLEAN: - value = njs_is_true(src) ? &njs_string_true : &njs_string_false; - break; + if (njs_is_true(src)) { + njs_atom_to_value(vm, dst, NJS_ATOM_STRING_true); + + } else { + njs_atom_to_value(vm, dst, NJS_ATOM_STRING_false); + } + + return NJS_OK; case NJS_NUMBER: return njs_number_to_string(vm, dst, src); @@ -1616,7 +1558,7 @@ njs_primitive_value_to_chain(njs_vm_t *vm, njs_chb_t *chain, return NJS_ERROR; case NJS_STRING: - (void) njs_string_prop(&string, src); + (void) njs_string_prop(vm, &string, src); njs_chb_append(chain, string.start, string.size); return string.length; @@ -1712,11 +1654,7 @@ njs_value_species_constructor(njs_vm_t *vm, njs_value_t *object, njs_int_t ret; njs_value_t constructor, retval; - static const njs_value_t string_constructor = njs_string("constructor"); - static const njs_value_t string_species = - njs_wellknown_symbol(NJS_SYMBOL_SPECIES); - - ret = njs_value_property(vm, object, njs_value_arg(&string_constructor), + ret = njs_value_property(vm, object, NJS_ATOM_STRING_constructor, &constructor); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; @@ -1731,7 +1669,7 @@ njs_value_species_constructor(njs_vm_t *vm, njs_value_t *object, return NJS_ERROR; } - ret = njs_value_property(vm, &constructor, njs_value_arg(&string_species), + ret = njs_value_property(vm, &constructor, NJS_ATOM_SYMBOL_species, &retval); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; @@ -1759,7 +1697,7 @@ default_constructor: njs_int_t -njs_value_method(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, +njs_value_method(njs_vm_t *vm, njs_value_t *value, uint32_t atom_id, njs_value_t *retval) { njs_int_t ret; @@ -1769,7 +1707,7 @@ njs_value_method(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, return ret; } - ret = njs_value_property(vm, value, key, retval); + ret = njs_value_property(vm, value, atom_id, retval); if (njs_slow_path(ret != NJS_OK)) { return (ret == NJS_DECLINED) ? NJS_OK : ret; } diff --git a/src/njs_value.h b/src/njs_value.h index 3751db71..7bc9eff3 100644 --- a/src/njs_value.h +++ b/src/njs_value.h @@ -91,33 +91,18 @@ typedef struct njs_property_next_s njs_property_next_t; union njs_value_s { - /* - * The njs_value_t size is 16 bytes and must be aligned to 16 bytes - * to provide 4 bits to encode scope in njs_index_t. This space is - * used to store short strings. The maximum size of a short string - * is 14 (NJS_STRING_SHORT). If the short_string.size field is 15 - * (NJS_STRING_LONG) then the size is in the long_string.size field - * and the long_string.data field points to a long string. - * - * The number of the string types is limited to 2 types to minimize - * overhead of processing string fields. It is also possible to add - * strings with size from 14 to 254 which size and length are stored in - * the string_size and string_length byte wide fields. This will lessen - * the maximum size of short string to 13. - */ struct { - njs_value_type_t type:8; /* 6 bits */ + uint32_t magic32; + njs_value_type_t type:8; /* 5 bits */ + /* * The truth field is set during value assignment and then can be * quickly tested by logical and conditional operations regardless - * of value type. The truth field coincides with short_string.size - * and short_string.length so when string size and length are zero - * the string's value is false. + * of value type. */ uint8_t truth; uint16_t magic16; - uint32_t magic32; union { double number; @@ -139,30 +124,19 @@ union njs_value_s { } data; struct { - njs_value_type_t type:8; /* 6 bits */ - -#define NJS_STRING_SHORT 14 -#define NJS_STRING_LONG 15 - - uint8_t size:4; - uint8_t length:4; - - u_char start[NJS_STRING_SHORT]; - } short_string; - - struct { - njs_value_type_t type:8; /* 6 bits */ + uint32_t atom_id; + njs_value_type_t type:8; /* 5 bits */ uint8_t truth; - - /* 0xff if data is external string. */ - uint8_t external; - uint8_t _spare; - - uint32_t size; + uint8_t token_type; + uint8_t token_id; njs_string_t *data; - } long_string; + } string; - njs_value_type_t type:8; /* 6 bits */ + struct { + uint32_t atom_id; + njs_value_type_t type:8; /* 5 bits */ + uint8_t truth; + }; }; @@ -177,16 +151,16 @@ typedef struct { njs_exotic_keys_t keys; /* A shared hash of njs_object_prop_t for externals. */ - njs_lvlhsh_t external_shared_hash; + njs_flathsh_t external_shared_hash; } njs_exotic_slots_t; struct njs_object_s { /* A private hash of njs_object_prop_t. */ - njs_lvlhsh_t hash; + njs_flathsh_t hash; /* A shared hash of njs_object_prop_t. */ - njs_lvlhsh_t shared_hash; + njs_flathsh_t shared_hash; njs_object_t *__proto__; njs_exotic_slots_t *slots; @@ -315,10 +289,11 @@ struct njs_object_type_init_s { typedef enum { NJS_PROPERTY = 0, NJS_ACCESSOR, + NJS_PROPERTY_HANDLER, + NJS_PROPERTY_REF, NJS_PROPERTY_PLACE_REF, NJS_PROPERTY_TYPED_ARRAY_REF, - NJS_PROPERTY_HANDLER, NJS_WHITEOUT, } njs_object_prop_type_t; @@ -345,8 +320,6 @@ typedef enum { struct njs_object_prop_s { - njs_value_t name; - union { njs_value_t value; struct { @@ -374,23 +347,28 @@ struct njs_object_prop_s { }; +struct njs_object_prop_init_s { + struct njs_object_prop_s desc; + uint32_t atom_id; +}; + + typedef struct { - njs_lvlhsh_query_t lhq; + njs_flathsh_query_t lhq; uint8_t query; /* scratch is used to get the value of an NJS_PROPERTY_HANDLER property. */ njs_object_prop_t scratch; - njs_value_t key; - njs_lvlhsh_t *own_whiteout; + njs_flathsh_t *own_whiteout; uint8_t temp; uint8_t own; } njs_property_query_t; -#define njs_value(_type, _truth, _number) { \ +#define njs_value(_type, _truth, _number) (njs_value_t) { \ .data = { \ .type = _type, \ .truth = _truth, \ @@ -399,37 +377,26 @@ typedef struct { } -#define njs_wellknown_symbol(key) { \ +#define njs_symval(_sym_id, _s) { \ .data = { \ .type = NJS_SYMBOL, \ .truth = 1, \ - .magic32 = key, \ - .u = { .value = NULL } \ - } \ -} - - -#define njs_string(s) { \ - .short_string = { \ - .type = NJS_STRING, \ - .size = njs_length(s), \ - .length = njs_length(s), \ - .start = s, \ + .magic32 = NJS_ATOM_SYMBOL_ ## _sym_id, \ + .u = { .value = (njs_value_t *) &njs_ascii_strval(_s) } \ } \ } -/* NJS_STRING_LONG is set for both big and little endian platforms. */ - -#define njs_long_string(s) { \ - .long_string = { \ +#define njs_ascii_strval(_s) (njs_value_t) { \ + .string = { \ + .atom_id = NJS_ATOM_STRING_unknown, \ .type = NJS_STRING, \ - .truth = (NJS_STRING_LONG << 4) | NJS_STRING_LONG, \ - .size = njs_length(s), \ + .truth = njs_length(_s) ? 1 : 0, \ .data = & (njs_string_t) { \ - .start = (u_char *) s, \ - .length = njs_length(s), \ - } \ + .start = (u_char *) _s, \ + .length = njs_length(_s), \ + .size = njs_length(_s), \ + }, \ } \ } @@ -446,7 +413,7 @@ typedef struct { } -#define _njs_native_function(_func, _args, _ctor, _magic) { \ +#define _njs_native_function(_func, _args, _ctor, _magic) (njs_value_t) { \ .data = { \ .type = NJS_FUNCTION, \ .truth = 1, \ @@ -464,30 +431,28 @@ typedef struct { _njs_native_function(_function, _args_count, 0, _magic) -#define njs_getter(_function, _magic) \ - { \ - .getter = & (njs_function_t) _njs_function(_function, 0, 0, _magic), \ - .setter = NULL, \ - } +#define njs_getter(_function, _magic) { \ + .getter = & (njs_function_t) _njs_function(_function, 0, 0, _magic), \ + .setter = NULL, \ +} -#define njs_accessor(_getter, _m1, _setter, _m2) \ - { \ - .getter = & (njs_function_t) _njs_function(_getter, 0, 0, _m1), \ - .setter = & (njs_function_t) _njs_function(_setter, 0, 0, _m2), \ - } +#define njs_accessor(_getter, _m1, _setter, _m2) { \ + .getter = & (njs_function_t) _njs_function(_getter, 0, 0, _m1), \ + .setter = & (njs_function_t) _njs_function(_setter, 0, 0, _m2), \ +} #define njs_native_ctor(_function, _args_count, _magic) \ _njs_function(_function, _args_count, 1, _magic) -#define njs_prop_handler2(_handler, _magic16, _magic32) { \ +#define njs_prop_handler2(_handler, _magic16) (njs_value_t) { \ .data = { \ .type = NJS_INVALID, \ .truth = 1, \ .magic16 = _magic16, \ - .magic32 = _magic32, \ + .magic32 = 2, \ .u = { .prop_handler = _handler } \ } \ } @@ -551,50 +516,32 @@ typedef struct { (njs_is_number(value) || njs_is_key(value)) -/* - * The truth field coincides with short_string.size and short_string.length - * so when string size and length are zero the string's value is false and - * otherwise is true. - */ -#define njs_string_truth(value, size) - - -#define njs_string_get(value, str) \ +#define njs_string_get_unsafe(value, str) \ do { \ - if ((value)->short_string.size != NJS_STRING_LONG) { \ - (str)->length = (value)->short_string.size; \ - (str)->start = (u_char *) (value)->short_string.start; \ - \ - } else { \ - (str)->length = (value)->long_string.size; \ - (str)->start = (u_char *) (value)->long_string.data->start; \ - } \ + njs_assert((value)->string.data != NULL); \ + (str)->length = (value)->string.data->size; \ + (str)->start = (u_char *) (value)->string.data->start; \ } while (0) -#define njs_string_short_start(value) \ - (value)->short_string.start - - -#define njs_string_short_set(value, _size, _length) \ - do { \ - (value)->type = NJS_STRING; \ - njs_string_truth(value, _size); \ - (value)->short_string.size = _size; \ - (value)->short_string.length = _length; \ - } while (0) - - -#define njs_string_length_set(value, _length) \ +#define njs_string_get(vm, value, str) \ do { \ - if ((value)->short_string.size != NJS_STRING_LONG) { \ - (value)->short_string.length = length; \ + njs_value_t _dst; \ + \ + njs_assert(njs_is_string(value)); \ + \ + if (njs_slow_path((value)->string.data == NULL)) { \ + njs_assert((value)->atom_id != 0 /* NJS_ATOM_STRING_unknown */); \ + njs_atom_to_value(vm, &_dst, (value)->atom_id); \ + njs_assert(njs_is_string(&_dst)); \ + njs_string_get_unsafe(&_dst, str); \ \ } else { \ - (value)->long_string.data->length = length; \ + njs_string_get_unsafe(value, str); \ } \ } while (0) + #define njs_is_primitive(value) \ ((value)->type <= NJS_STRING) @@ -828,32 +775,6 @@ extern const njs_value_t njs_value_zero; extern const njs_value_t njs_value_nan; extern const njs_value_t njs_value_invalid; -extern const njs_value_t njs_string_empty; -extern const njs_value_t njs_string_empty_regexp; -extern const njs_value_t njs_string_comma; -extern const njs_value_t njs_string_null; -extern const njs_value_t njs_string_undefined; -extern const njs_value_t njs_string_boolean; -extern const njs_value_t njs_string_false; -extern const njs_value_t njs_string_true; -extern const njs_value_t njs_string_number; -extern const njs_value_t njs_string_minus_zero; -extern const njs_value_t njs_string_minus_infinity; -extern const njs_value_t njs_string_plus_infinity; -extern const njs_value_t njs_string_nan; -extern const njs_value_t njs_string_symbol; -extern const njs_value_t njs_string_string; -extern const njs_value_t njs_string_data; -extern const njs_value_t njs_string_type; -extern const njs_value_t njs_string_name; -extern const njs_value_t njs_string_external; -extern const njs_value_t njs_string_invalid; -extern const njs_value_t njs_string_object; -extern const njs_value_t njs_string_function; -extern const njs_value_t njs_string_anonymous; -extern const njs_value_t njs_string_memory_error; - - njs_inline void njs_set_boolean(njs_value_t *value, unsigned yn) { @@ -872,15 +793,21 @@ njs_set_number(njs_value_t *value, double num) value->data.u.number = num; value->type = NJS_NUMBER; value->data.truth = njs_is_number_true(num); + value->atom_id = 0 /* NJS_ATOM_STRING_unknown */; } +#define njs_set_empty_string(vm, value) \ + njs_atom_to_value(vm, value, NJS_ATOM_STRING_empty) + + njs_inline void njs_set_int32(njs_value_t *value, int32_t num) { value->data.u.number = num; value->type = NJS_NUMBER; value->data.truth = (num != 0); + value->atom_id = 0 /* NJS_ATOM_STRING_unknown */; } @@ -890,6 +817,7 @@ njs_set_uint32(njs_value_t *value, uint32_t num) value->data.u.number = num; value->type = NJS_NUMBER; value->data.truth = (num != 0); + value->atom_id = 0 /* NJS_ATOM_STRING_unknown */; } @@ -1030,20 +958,18 @@ njs_int_t njs_primitive_value_to_string(njs_vm_t *vm, njs_value_t *dst, const njs_value_t *src); njs_int_t njs_primitive_value_to_chain(njs_vm_t *vm, njs_chb_t *chain, const njs_value_t *src); -double njs_string_to_number(const njs_value_t *value); +double njs_string_to_number(njs_vm_t *vm, const njs_value_t *value); njs_int_t njs_int64_to_string(njs_vm_t *vm, njs_value_t *value, int64_t i64); -njs_bool_t njs_string_eq(const njs_value_t *v1, const njs_value_t *v2); +njs_bool_t njs_string_eq(njs_vm_t *vm, const njs_value_t *v1, + const njs_value_t *v2); njs_int_t njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, - njs_value_t *value, njs_value_t *key); - -njs_int_t njs_value_property(njs_vm_t *vm, njs_value_t *value, - njs_value_t *key, njs_value_t *retval); + njs_value_t *value, uint32_t atom_id); njs_int_t njs_value_property_set(njs_vm_t *vm, njs_value_t *value, - njs_value_t *key, njs_value_t *setval); + uint32_t atom_id, njs_value_t *setval); njs_int_t njs_value_property_delete(njs_vm_t *vm, njs_value_t *value, - njs_value_t *key, njs_value_t *removed, njs_bool_t thrw); + uint32_t atom_id, njs_value_t *removed, njs_bool_t thrw); njs_int_t njs_value_to_object(njs_vm_t *vm, njs_value_t *value); void njs_symbol_conversion_failed(njs_vm_t *vm, njs_bool_t to_string); @@ -1053,16 +979,15 @@ njs_int_t njs_value_construct(njs_vm_t *vm, njs_value_t *constructor, njs_int_t njs_value_species_constructor(njs_vm_t *vm, njs_value_t *object, njs_value_t *default_constructor, njs_value_t *dst); -njs_int_t njs_value_method(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, +njs_int_t njs_value_method(njs_vm_t *vm, njs_value_t *value, uint32_t atom_id, njs_value_t *retval); njs_inline void njs_property_query_init(njs_property_query_t *pq, njs_prop_query_t query, - uint32_t hash, uint8_t own) + uint8_t own) { pq->query = query; - pq->lhq.key_hash = hash; pq->own = own; if (query == NJS_PROPERTY_QUERY_SET) { @@ -1073,15 +998,36 @@ njs_property_query_init(njs_property_query_t *pq, njs_prop_query_t query, } +njs_inline njs_int_t +njs_property_query_val(njs_vm_t *vm, njs_property_query_t *pq, + njs_value_t *value, njs_value_t *key) +{ + njs_int_t ret; + + if (njs_value_atom(key) == 0 /* NJS_ATOM_STRING_unknown */) { + ret = njs_atom_atomize_key(vm, key); + if (ret != NJS_OK) { + return ret; + } + } + + return njs_property_query(vm, pq, value, key->atom_id); +} + + njs_inline njs_int_t njs_value_property_i64(njs_vm_t *vm, njs_value_t *value, int64_t index, njs_value_t *retval) { njs_value_t key; + if (index < 0x80000000) { + return njs_value_property(vm, value, njs_number_atom(index), retval); + } + njs_set_number(&key, index); - return njs_value_property(vm, value, &key, retval); + return njs_value_property_val(vm, value, &key, retval); } @@ -1091,9 +1037,31 @@ njs_value_property_i64_set(njs_vm_t *vm, njs_value_t *value, int64_t index, { njs_value_t key; + if (index < 0x80000000) { + return njs_value_property_set(vm, value, njs_number_atom(index), + setval); + } + njs_set_number(&key, index); - return njs_value_property_set(vm, value, &key, setval); + return njs_value_property_val_set(vm, value, &key, setval); +} + + +njs_inline njs_int_t +njs_value_property_val_delete(njs_vm_t *vm, njs_value_t *value, + njs_value_t *key, njs_value_t *removed, njs_bool_t thrw) +{ + njs_int_t ret; + + if (njs_value_atom(key) == 0 /* NJS_ATOM_STRING_unknown */) { + ret = njs_atom_atomize_key(vm, key); + if (ret != NJS_OK) { + return ret; + } + } + + return njs_value_property_delete(vm, value, key->atom_id, removed, thrw); } @@ -1103,17 +1071,23 @@ njs_value_property_i64_delete(njs_vm_t *vm, njs_value_t *value, int64_t index, { njs_value_t key; + if (index < 0x80000000) { + return njs_value_property_delete(vm, value, njs_number_atom(index), + removed, 1); + } + njs_set_number(&key, index); - return njs_value_property_delete(vm, value, &key, removed, 1); + return njs_value_property_val_delete(vm, value, &key, removed, 1); } njs_inline njs_bool_t -njs_values_same_non_numeric(const njs_value_t *val1, const njs_value_t *val2) +njs_values_same_non_numeric(njs_vm_t *vm, const njs_value_t *val1, + const njs_value_t *val2) { if (njs_is_string(val1)) { - return njs_string_eq(val1, val2); + return njs_string_eq(vm, val1, val2); } if (njs_is_symbol(val1)) { @@ -1125,7 +1099,8 @@ njs_values_same_non_numeric(const njs_value_t *val1, const njs_value_t *val2) njs_inline njs_bool_t -njs_values_strict_equal(const njs_value_t *val1, const njs_value_t *val2) +njs_values_strict_equal(njs_vm_t *vm, const njs_value_t *val1, + const njs_value_t *val2) { if (val1->type != val2->type) { return 0; @@ -1141,12 +1116,12 @@ njs_values_strict_equal(const njs_value_t *val1, const njs_value_t *val2) return (njs_number(val1) == njs_number(val2)); } - return njs_values_same_non_numeric(val1, val2); + return njs_values_same_non_numeric(vm, val1, val2); } njs_inline njs_bool_t -njs_values_same(const njs_value_t *val1, const njs_value_t *val2) +njs_values_same(njs_vm_t *vm, const njs_value_t *val1, const njs_value_t *val2) { double num1, num2; @@ -1177,12 +1152,13 @@ njs_values_same(const njs_value_t *val1, const njs_value_t *val2) return num1 == num2; } - return njs_values_same_non_numeric(val1, val2); + return njs_values_same_non_numeric(vm, val1, val2); } njs_inline njs_bool_t -njs_values_same_zero(const njs_value_t *val1, const njs_value_t *val2) +njs_values_same_zero(njs_vm_t *vm, const njs_value_t *val1, + const njs_value_t *val2) { double num1, num2; @@ -1207,7 +1183,7 @@ njs_values_same_zero(const njs_value_t *val1, const njs_value_t *val2) return num1 == num2; } - return njs_values_same_non_numeric(val1, val2); + return njs_values_same_non_numeric(vm, val1, val2); } diff --git a/src/njs_value_conversion.h b/src/njs_value_conversion.h index 24483aa2..80c08b45 100644 --- a/src/njs_value_conversion.h +++ b/src/njs_value_conversion.h @@ -33,7 +33,7 @@ njs_value_to_number(njs_vm_t *vm, njs_value_t *value, double *dst) *dst = NAN; if (njs_is_string(value)) { - *dst = njs_string_to_number(value); + *dst = njs_string_to_number(vm, value); } return NJS_OK; diff --git a/src/njs_variable.c b/src/njs_variable.c index 85fd235a..78bd2afb 100644 --- a/src/njs_variable.c +++ b/src/njs_variable.c @@ -12,31 +12,31 @@ static njs_declaration_t *njs_variable_scope_function_add(njs_parser_t *parser, njs_parser_scope_t *scope); static njs_parser_scope_t *njs_variable_scope_find(njs_parser_t *parser, - njs_parser_scope_t *scope, uintptr_t unique_id, njs_variable_type_t type); -static njs_variable_t *njs_variable_alloc(njs_vm_t *vm, uintptr_t unique_id, + njs_parser_scope_t *scope, uintptr_t atom_id, njs_variable_type_t type); +static njs_variable_t *njs_variable_alloc(njs_vm_t *vm, uintptr_t atom_id, njs_variable_type_t type); njs_variable_t * njs_variable_add(njs_parser_t *parser, njs_parser_scope_t *scope, - uintptr_t unique_id, njs_variable_type_t type) + uintptr_t atom_id, njs_variable_type_t type) { njs_parser_scope_t *root; - root = njs_variable_scope_find(parser, scope, unique_id, type); + root = njs_variable_scope_find(parser, scope, atom_id, type); if (njs_slow_path(root == NULL)) { njs_parser_ref_error(parser, "scope not found"); return NULL; } - return njs_variable_scope_add(parser, root, scope, unique_id, type, + return njs_variable_scope_add(parser, root, scope, atom_id, type, NJS_INDEX_NONE); } njs_variable_t * njs_variable_function_add(njs_parser_t *parser, njs_parser_scope_t *scope, - uintptr_t unique_id, njs_variable_type_t type) + uintptr_t atom_id, njs_variable_type_t type) { njs_bool_t ctor; njs_variable_t *var; @@ -44,13 +44,13 @@ njs_variable_function_add(njs_parser_t *parser, njs_parser_scope_t *scope, njs_parser_scope_t *root; njs_function_lambda_t *lambda; - root = njs_variable_scope_find(parser, scope, unique_id, type); + root = njs_variable_scope_find(parser, scope, atom_id, type); if (njs_slow_path(root == NULL)) { njs_parser_ref_error(parser, "scope not found"); return NULL; } - var = njs_variable_scope_add(parser, root, scope, unique_id, type, + var = njs_variable_scope_add(parser, root, scope, atom_id, type, NJS_INDEX_ERROR); if (njs_slow_path(var == NULL)) { return NULL; @@ -107,7 +107,7 @@ njs_variable_scope_function_add(njs_parser_t *parser, njs_parser_scope_t *scope) static njs_parser_scope_t * -njs_variable_scope(njs_parser_scope_t *scope, uintptr_t unique_id, +njs_variable_scope(njs_parser_scope_t *scope, uintptr_t atom_id, njs_variable_t **retvar, njs_variable_type_t type) { njs_variable_t *var; @@ -116,7 +116,7 @@ njs_variable_scope(njs_parser_scope_t *scope, uintptr_t unique_id, *retvar = NULL; - var_node.key = unique_id; + var_node.key = atom_id; do { node = njs_rbtree_find(&scope->variables, &var_node.node); @@ -146,14 +146,14 @@ njs_variable_scope(njs_parser_scope_t *scope, uintptr_t unique_id, static njs_parser_scope_t * njs_variable_scope_find(njs_parser_t *parser, njs_parser_scope_t *scope, - uintptr_t unique_id, njs_variable_type_t type) + uintptr_t atom_id, njs_variable_type_t type) { - njs_bool_t module; - njs_variable_t *var; - njs_parser_scope_t *root; - const njs_lexer_entry_t *entry; + njs_str_t entry; + njs_bool_t module; + njs_variable_t *var; + njs_parser_scope_t *root; - root = njs_variable_scope(scope, unique_id, &var, type); + root = njs_variable_scope(scope, atom_id, &var, type); if (njs_slow_path(root == NULL)) { return NULL; } @@ -162,7 +162,7 @@ njs_variable_scope_find(njs_parser_t *parser, njs_parser_scope_t *scope, case NJS_VARIABLE_CONST: case NJS_VARIABLE_LET: if (scope->type == NJS_SCOPE_GLOBAL - && parser->undefined_id == unique_id) + && atom_id == NJS_ATOM_STRING_undefined) { goto failed; } @@ -239,17 +239,16 @@ njs_variable_scope_find(njs_parser_t *parser, njs_parser_scope_t *scope, failed: - entry = njs_lexer_entry(unique_id); + njs_lexer_entry(parser->vm, atom_id, &entry); - njs_parser_syntax_error(parser, "\"%V\" has already been declared", - &entry->name); + njs_parser_syntax_error(parser, "\"%V\" has already been declared", &entry); return NULL; } njs_variable_t * njs_variable_scope_add(njs_parser_t *parser, njs_parser_scope_t *scope, - njs_parser_scope_t *original, uintptr_t unique_id, + njs_parser_scope_t *original, uintptr_t atom_id, njs_variable_type_t type, njs_index_t index) { njs_variable_t *var; @@ -257,7 +256,7 @@ njs_variable_scope_add(njs_parser_t *parser, njs_parser_scope_t *scope, njs_parser_scope_t *root; njs_variable_node_t var_node, *var_node_new; - var_node.key = unique_id; + var_node.key = atom_id; node = njs_rbtree_find(&scope->variables, &var_node.node); @@ -265,7 +264,7 @@ njs_variable_scope_add(njs_parser_t *parser, njs_parser_scope_t *scope, return ((njs_variable_node_t *) node)->variable; } - var = njs_variable_alloc(parser->vm, unique_id, type); + var = njs_variable_alloc(parser->vm, atom_id, type); if (njs_slow_path(var == NULL)) { goto memory_error; } @@ -285,7 +284,7 @@ njs_variable_scope_add(njs_parser_t *parser, njs_parser_scope_t *scope, root->items++; } - var_node_new = njs_variable_node_alloc(parser->vm, var, unique_id); + var_node_new = njs_variable_node_alloc(parser->vm, var, atom_id); if (njs_slow_path(var_node_new == NULL)) { goto memory_error; } @@ -303,13 +302,13 @@ memory_error: njs_variable_t * -njs_label_add(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t unique_id) +njs_label_add(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t atom_id) { njs_variable_t *label; njs_rbtree_node_t *node; njs_variable_node_t var_node, *var_node_new; - var_node.key = unique_id; + var_node.key = atom_id; node = njs_rbtree_find(&scope->labels, &var_node.node); @@ -317,12 +316,12 @@ njs_label_add(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t unique_id) return ((njs_variable_node_t *) node)->variable; } - label = njs_variable_alloc(vm, unique_id, NJS_VARIABLE_CONST); + label = njs_variable_alloc(vm, atom_id, NJS_VARIABLE_CONST); if (njs_slow_path(label == NULL)) { goto memory_error; } - var_node_new = njs_variable_node_alloc(vm, label, unique_id); + var_node_new = njs_variable_node_alloc(vm, label, atom_id); if (njs_slow_path(var_node_new == NULL)) { goto memory_error; } @@ -340,12 +339,12 @@ memory_error: njs_int_t -njs_label_remove(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t unique_id) +njs_label_remove(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t atom_id) { njs_rbtree_node_t *node; njs_variable_node_t var_node; - var_node.key = unique_id; + var_node.key = atom_id; node = njs_rbtree_find(&scope->labels, &var_node.node); if (njs_slow_path(node == NULL)) { @@ -391,7 +390,7 @@ njs_variable_resolve(njs_vm_t *vm, njs_parser_node_t *node) ref = &node->u.reference; scope = node->scope; - var_node.key = ref->unique_id; + var_node.key = ref->atom_id; do { rb_node = njs_rbtree_find(&scope->variables, &var_node.node); @@ -420,7 +419,7 @@ njs_variable_closure(njs_vm_t *vm, njs_variable_t *var, #define NJS_VAR_MAX_DEPTH 32 njs_parser_scope_t *list[NJS_VAR_MAX_DEPTH]; - ref_node.key = var->unique_id; + ref_node.key = var->atom_id; p = list; @@ -485,7 +484,7 @@ njs_variable_closure(njs_vm_t *vm, njs_variable_t *var, return NJS_INDEX_ERROR; } - parse_node->key = var->unique_id; + parse_node->key = var->atom_id; njs_rbtree_insert(&scope->references, &parse_node->node); } @@ -524,7 +523,7 @@ njs_variable_reference(njs_vm_t *vm, njs_parser_node_t *node) closure = njs_variable_closure_test(node->scope, ref->variable->scope); ref->scope = node->scope; - ref_node.key = ref->unique_id; + ref_node.key = ref->atom_id; rb_node = njs_rbtree_find(&scope->references, &ref_node.node); if (njs_slow_path(rb_node == NULL)) { @@ -557,12 +556,12 @@ njs_variable_reference(njs_vm_t *vm, njs_parser_node_t *node) njs_variable_t * -njs_label_find(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t unique_id) +njs_label_find(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t atom_id) { njs_rbtree_node_t *node; njs_variable_node_t var_node; - var_node.key = unique_id; + var_node.key = atom_id; do { node = njs_rbtree_find(&scope->labels, &var_node.node); @@ -580,7 +579,7 @@ njs_label_find(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t unique_id) static njs_variable_t * -njs_variable_alloc(njs_vm_t *vm, uintptr_t unique_id, njs_variable_type_t type) +njs_variable_alloc(njs_vm_t *vm, uintptr_t atom_id, njs_variable_type_t type) { njs_variable_t *var; @@ -590,7 +589,7 @@ njs_variable_alloc(njs_vm_t *vm, uintptr_t unique_id, njs_variable_type_t type) return NULL; } - var->unique_id = unique_id; + var->atom_id = atom_id; var->type = type; return var; diff --git a/src/njs_variable.h b/src/njs_variable.h index dfcc99f3..2ed5220a 100644 --- a/src/njs_variable.h +++ b/src/njs_variable.h @@ -18,7 +18,7 @@ typedef enum { typedef struct { - uintptr_t unique_id; + uintptr_t atom_id; njs_variable_type_t type:8; /* 3 bits */ njs_bool_t argument; @@ -45,7 +45,7 @@ typedef enum { typedef struct { njs_reference_type_t type; - uintptr_t unique_id; + uintptr_t atom_id; njs_variable_t *variable; njs_parser_scope_t *scope; njs_bool_t not_defined; @@ -60,19 +60,19 @@ typedef struct { njs_variable_t *njs_variable_add(njs_parser_t *parser, - njs_parser_scope_t *scope, uintptr_t unique_id, njs_variable_type_t type); + njs_parser_scope_t *scope, uintptr_t atom_id, njs_variable_type_t type); njs_variable_t *njs_variable_function_add(njs_parser_t *parser, - njs_parser_scope_t *scope, uintptr_t unique_id, njs_variable_type_t type); + njs_parser_scope_t *scope, uintptr_t atom_id, njs_variable_type_t type); njs_variable_t * njs_label_add(njs_vm_t *vm, njs_parser_scope_t *scope, - uintptr_t unique_id); + uintptr_t atom_id); njs_variable_t *njs_label_find(njs_vm_t *vm, njs_parser_scope_t *scope, - uintptr_t unique_id); + uintptr_t atom_id); njs_int_t njs_label_remove(njs_vm_t *vm, njs_parser_scope_t *scope, - uintptr_t unique_id); + uintptr_t atom_id); njs_variable_t *njs_variable_reference(njs_vm_t *vm, njs_parser_node_t *node); njs_variable_t *njs_variable_scope_add(njs_parser_t *parser, njs_parser_scope_t *scope, njs_parser_scope_t *original, - uintptr_t unique_id, njs_variable_type_t type, njs_index_t index); + uintptr_t atom_id, njs_variable_type_t type, njs_index_t index); njs_int_t njs_name_copy(njs_vm_t *vm, njs_str_t *dst, const njs_str_t *src); diff --git a/src/njs_vm.c b/src/njs_vm.c index 43b2ccc2..008f9d04 100644 --- a/src/njs_vm.c +++ b/src/njs_vm.c @@ -138,8 +138,6 @@ njs_vm_create(njs_vm_opt_t *options) } } - vm->symbol_generator = NJS_SYMBOL_KNOWN_MAX; - if (njs_scope_undefined_index(vm, 0) == NJS_INDEX_ERROR) { return NULL; } @@ -222,7 +220,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end) global_items = (vm->global_scope != NULL) ? vm->global_scope->items : 0; ret = njs_parser_init(vm, &parser, vm->global_scope, &vm->options.file, - *start, end, 0); + *start, end); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -330,7 +328,7 @@ njs_vm_compile_module(njs_vm_t *vm, njs_str_t *name, u_char **start, return NULL; } - ret = njs_parser_init(vm, &parser, NULL, name, *start, end, 1); + ret = njs_parser_init(vm, &parser, NULL, name, *start, end); if (njs_slow_path(ret != NJS_OK)) { return NULL; } @@ -419,6 +417,11 @@ njs_vm_clone(njs_vm_t *vm, njs_external_ptr_t external) nvm->trace.data = nvm; nvm->external = external; + nvm->shared_atom_count = vm->atom_id_generator; + + njs_lvlhsh_init(&nvm->atom_hash); + nvm->atom_hash_current = &nvm->atom_hash; + ret = njs_vm_runtime_init(nvm); if (njs_slow_path(ret != NJS_OK)) { goto fail; @@ -495,7 +498,7 @@ njs_vm_runtime_init(njs_vm_t *vm) } njs_lvlhsh_init(&vm->values_hash); - njs_lvlhsh_init(&vm->keywords_hash); + njs_lvlhsh_init(&vm->modules_hash); njs_rbtree_init(&vm->global_symbols, njs_symbol_rbtree_cmp); @@ -874,12 +877,13 @@ njs_vm_value(njs_vm_t *vm, const njs_str_t *path, njs_value_t *retval) return NJS_ERROR; } - ret = njs_string_create(vm, &key, start, size); + ret = njs_atom_string_create(vm, &key, start, size); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - ret = njs_value_property(vm, &value, &key, njs_value_arg(retval)); + ret = njs_value_property(vm, &value, key.atom_id, + njs_value_arg(retval)); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -900,19 +904,20 @@ static njs_int_t njs_vm_bind2(njs_vm_t *vm, const njs_str_t *var_name, njs_object_prop_t *prop, njs_bool_t shared) { - njs_int_t ret; - njs_object_t *global; - njs_lvlhsh_t *hash; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_value_t prop_name; + njs_object_t *global; + njs_flathsh_t *hash; + njs_flathsh_query_t lhq; - ret = njs_string_create(vm, &prop->name, var_name->start, var_name->length); + ret = njs_atom_string_create(vm, &prop_name, var_name->start, + var_name->length); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } lhq.value = prop; - lhq.key = *var_name; - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); + lhq.key_hash = prop_name.atom_id; lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; @@ -920,7 +925,7 @@ njs_vm_bind2(njs_vm_t *vm, const njs_str_t *var_name, njs_object_prop_t *prop, global = &vm->global_object; hash = shared ? &global->shared_hash : &global->hash; - ret = njs_lvlhsh_insert(hash, &lhq); + ret = njs_flathsh_unique_insert(hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return ret; @@ -936,7 +941,7 @@ njs_vm_bind(njs_vm_t *vm, const njs_str_t *var_name, const njs_value_t *value, { njs_object_prop_t *prop; - prop = njs_object_prop_alloc(vm, &njs_value_undefined, value, 1); + prop = njs_object_prop_alloc(vm, value, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -952,8 +957,7 @@ njs_vm_bind_handler(njs_vm_t *vm, const njs_str_t *var_name, { njs_object_prop_t *prop; - prop = njs_object_prop_alloc(vm, &njs_string_empty, - &njs_value_invalid, 1); + prop = njs_object_prop_alloc(vm, &njs_value_invalid, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -970,9 +974,9 @@ njs_vm_bind_handler(njs_vm_t *vm, const njs_str_t *var_name, void -njs_value_string_get(njs_value_t *value, njs_str_t *dst) +njs_value_string_get(njs_vm_t *vm, njs_value_t *value, njs_str_t *dst) { - njs_string_get(value, dst); + njs_string_get(vm, value, dst); } @@ -1050,13 +1054,21 @@ njs_vm_prop_magic32(njs_object_prop_t *prop) njs_int_t -njs_vm_prop_name(njs_vm_t *vm, njs_object_prop_t *prop, njs_str_t *dst) +njs_vm_prop_name(njs_vm_t *vm, uint32_t atom_id, njs_str_t *dst) { - if (njs_slow_path(!njs_is_string(&prop->name))) { + njs_int_t ret; + njs_value_t prop_name; + + ret = njs_atom_to_value(vm, &prop_name, atom_id); + if (ret != NJS_OK) { return NJS_ERROR; } - njs_string_get(&prop->name, dst); + if (njs_slow_path(!njs_is_string(&prop_name))) { + return NJS_ERROR; + } + + njs_string_get(vm, &prop_name, dst); return NJS_OK; } @@ -1090,7 +1102,7 @@ njs_vm_value_string(njs_vm_t *vm, njs_str_t *dst, njs_value_t *src) && njs_number(src) == 0 && signbit(njs_number(src)))) { - njs_string_get(&njs_string_minus_zero, dst); + *dst = njs_str_value("-0"); return NJS_OK; } @@ -1134,22 +1146,18 @@ njs_value_t * njs_vm_value_enumerate(njs_vm_t *vm, njs_value_t *value, uint32_t flags, njs_value_t *retval) { - njs_int_t ret; - njs_value_t *val; - njs_array_t *keys; - njs_rbtree_t *variables; - njs_rbtree_node_t *rb_node; - njs_variable_node_t *node; - const njs_lexer_entry_t *lex_entry; - - static const njs_str_t njs_this_str = njs_str("this"); + njs_value_t *val; + njs_array_t *keys; + njs_rbtree_t *variables; + njs_rbtree_node_t *rb_node; + njs_variable_node_t *node; keys = njs_value_enumerate(vm, value, flags); if (njs_slow_path(keys == NULL)) { return NULL; } - if (!njs_values_same(value, &vm->global_value) + if (!njs_values_same(vm, value, &vm->global_value) || vm->global_scope == NULL) { goto done; @@ -1163,12 +1171,7 @@ njs_vm_value_enumerate(njs_vm_t *vm, njs_value_t *value, uint32_t flags, while (njs_rbtree_is_there_successor(variables, rb_node)) { node = (njs_variable_node_t *) rb_node; - lex_entry = njs_lexer_entry(node->variable->unique_id); - if (njs_slow_path(lex_entry == NULL)) { - return NULL; - } - - if (njs_strstr_eq(&lex_entry->name, &njs_this_str)) { + if (node->variable->atom_id == NJS_ATOM_STRING_this) { rb_node = njs_rbtree_node_successor(variables, rb_node); continue; } @@ -1178,11 +1181,7 @@ njs_vm_value_enumerate(njs_vm_t *vm, njs_value_t *value, uint32_t flags, return NULL; } - ret = njs_string_create(vm, val, lex_entry->name.start, - lex_entry->name.length); - if (njs_slow_path(ret != NJS_OK)) { - return NULL; - } + njs_atom_to_value(vm, val, node->variable->atom_id); rb_node = njs_rbtree_node_successor(variables, rb_node); } @@ -1215,12 +1214,12 @@ njs_vm_value_own_enumerate(njs_vm_t *vm, njs_value_t *value, uint32_t flags, njs_int_t njs_vm_object_alloc(njs_vm_t *vm, njs_value_t *retval, ...) { - va_list args; - njs_int_t ret; - njs_value_t *name, *value; - njs_object_t *object; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + va_list args; + njs_int_t ret; + njs_value_t *name, *value; + njs_object_t *object; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; object = njs_object_alloc(vm); if (njs_slow_path(object == NULL)) { @@ -1248,21 +1247,25 @@ njs_vm_object_alloc(njs_vm_t *vm, njs_value_t *retval, ...) goto done; } - lhq.replace = 0; - lhq.pool = vm->mem_pool; - lhq.proto = &njs_object_hash_proto; - - njs_string_get(name, &lhq.key); - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); - - prop = njs_object_prop_alloc(vm, name, value, 1); + prop = njs_object_prop_alloc(vm, value, 1); if (njs_slow_path(prop == NULL)) { goto done; } + if (name->atom_id == NJS_ATOM_STRING_unknown) { + ret = njs_atom_atomize_key(vm, name); + if (ret != NJS_OK) { + goto done; + } + } + lhq.value = prop; + lhq.key_hash = name->atom_id; + lhq.replace = 0; + lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(&object->hash, &lhq); + ret = njs_flathsh_unique_insert(&object->hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, NULL); goto done; @@ -1357,7 +1360,7 @@ njs_vm_object_prop(njs_vm_t *vm, njs_value_t *value, const njs_str_t *prop, return NULL; } - ret = njs_value_property(vm, value, &key, njs_value_arg(retval)); + ret = njs_value_property_val(vm, value, &key, njs_value_arg(retval)); if (njs_slow_path(ret != NJS_OK)) { return NULL; } @@ -1378,12 +1381,13 @@ njs_vm_object_prop_set(njs_vm_t *vm, njs_value_t *value, const njs_str_t *prop, return NJS_ERROR; } - ret = njs_vm_value_string_create(vm, &key, prop->start, prop->length); + ret = njs_atom_string_create(vm, &key, prop->start, prop->length); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - ret = njs_value_property_set(vm, value, &key, njs_value_arg(setval)); + ret = njs_value_property_set(vm, value, key.atom_id, + njs_value_arg(setval)); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -1473,8 +1477,6 @@ njs_vm_date_alloc(njs_vm_t *vm, njs_value_t *retval, double time) njs_int_t njs_vm_value_to_string(njs_vm_t *vm, njs_str_t *dst, njs_value_t *src) { - u_char *start; - size_t size; njs_int_t ret; njs_value_t value, stack; @@ -1484,7 +1486,7 @@ njs_vm_value_to_string(njs_vm_t *vm, njs_str_t *dst, njs_value_t *src) if (njs_is_error(src)) { if (njs_is_memory_error(vm, src)) { - njs_string_get(&njs_string_memory_error, dst); + *dst = njs_str_value("MemoryError"); return NJS_OK; } @@ -1503,24 +1505,7 @@ njs_vm_value_to_string(njs_vm_t *vm, njs_str_t *dst, njs_value_t *src) ret = njs_value_to_string(vm, &value, &value); if (njs_fast_path(ret == NJS_OK)) { - size = value.short_string.size; - - if (size != NJS_STRING_LONG) { - start = njs_mp_alloc(vm->mem_pool, size); - if (njs_slow_path(start == NULL)) { - njs_memory_error(vm); - return NJS_ERROR; - } - - memcpy(start, value.short_string.start, size); - - } else { - size = value.long_string.size; - start = value.long_string.data->start; - } - - dst->length = size; - dst->start = start; + njs_string_get(vm, &value, dst); } return ret; @@ -1535,24 +1520,12 @@ njs_vm_value_to_string(njs_vm_t *vm, njs_str_t *dst, njs_value_t *src) const char * njs_vm_value_to_c_string(njs_vm_t *vm, njs_value_t *value) { - u_char *p, *data, *start; + u_char *p, *data; size_t size; njs_assert(njs_is_string(value)); - if (value->short_string.size != NJS_STRING_LONG) { - start = value->short_string.start; - size = value->short_string.size; - - if (size < NJS_STRING_SHORT) { - start[size] = '\0'; - return (const char *) start; - } - - } else { - start = value->long_string.data->start; - size = value->long_string.size; - } + size = value->string.data->size; data = njs_mp_alloc(vm->mem_pool, size + njs_length("\0")); if (njs_slow_path(data == NULL)) { @@ -1560,7 +1533,7 @@ njs_vm_value_to_c_string(njs_vm_t *vm, njs_value_t *value) return NULL; } - p = njs_cpymem(data, start, size); + p = njs_cpymem(data, value->string.data->start, size); *p++ = '\0'; return (const char *) data; @@ -1595,8 +1568,7 @@ njs_value_to_string(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value) njs_int_t njs_vm_value_to_bytes(njs_vm_t *vm, njs_str_t *dst, njs_value_t *src) { - u_char *start; - size_t size, length, offset; + size_t length, offset; njs_int_t ret; njs_value_t value; njs_typed_array_t *array; @@ -1647,24 +1619,8 @@ njs_vm_value_to_bytes(njs_vm_t *vm, njs_str_t *dst, njs_value_t *src) return NJS_ERROR; } - size = value.short_string.size; - - if (size != NJS_STRING_LONG) { - start = njs_mp_alloc(vm->mem_pool, size); - if (njs_slow_path(start == NULL)) { - njs_memory_error(vm); - return NJS_ERROR; - } - - memcpy(start, value.short_string.start, size); - - } else { - size = value.long_string.size; - start = value.long_string.data->start; - } - - dst->length = size; - dst->start = start; + dst->length = value.string.data->size; + dst->start = value.string.data->start; } return ret; @@ -1672,9 +1628,10 @@ njs_vm_value_to_bytes(njs_vm_t *vm, njs_str_t *dst, njs_value_t *src) njs_int_t -njs_vm_string_compare(const njs_value_t *v1, const njs_value_t *v2) +njs_vm_string_compare(njs_vm_t *vm, const njs_value_t *v1, + const njs_value_t *v2) { - return njs_string_cmp(v1, v2); + return njs_string_cmp(vm, v1, v2); } diff --git a/src/njs_vm.h b/src/njs_vm.h index a3f2b5a9..3e21fdf2 100644 --- a/src/njs_vm.h +++ b/src/njs_vm.h @@ -128,7 +128,12 @@ struct njs_vm_s { njs_native_frame_t *top_frame; njs_frame_t *active_frame; - njs_lvlhsh_t keywords_hash; + njs_lvlhsh_t atom_hash_shared; + njs_lvlhsh_t atom_hash; + njs_lvlhsh_t *atom_hash_current; + uint32_t shared_atom_count; + uint32_t atom_id_generator; + njs_lvlhsh_t values_hash; njs_arr_t *modules; @@ -178,7 +183,6 @@ struct njs_vm_s { njs_random_t random; njs_rbtree_t global_symbols; - uint64_t symbol_generator; njs_module_loader_t module_loader; void *module_loader_opaque; @@ -203,21 +207,20 @@ typedef struct { struct njs_vm_shared_s { - njs_lvlhsh_t keywords_hash; njs_lvlhsh_t values_hash; - njs_lvlhsh_t array_instance_hash; - njs_lvlhsh_t string_instance_hash; - njs_lvlhsh_t function_instance_hash; - njs_lvlhsh_t async_function_instance_hash; - njs_lvlhsh_t arrow_instance_hash; - njs_lvlhsh_t arguments_object_instance_hash; - njs_lvlhsh_t regexp_instance_hash; + njs_flathsh_t array_instance_hash; + njs_flathsh_t string_instance_hash; + njs_flathsh_t function_instance_hash; + njs_flathsh_t async_function_instance_hash; + njs_flathsh_t arrow_instance_hash; + njs_flathsh_t arguments_object_instance_hash; + njs_flathsh_t regexp_instance_hash; size_t module_items; njs_lvlhsh_t modules_hash; - njs_lvlhsh_t env_hash; + njs_flathsh_t env_hash; njs_object_t string_object; njs_object_t objects[NJS_OBJECT_MAX]; @@ -261,7 +264,7 @@ extern const njs_str_t njs_entry_native; extern const njs_str_t njs_entry_unknown; extern const njs_str_t njs_entry_anonymous; -extern const njs_lvlhsh_proto_t njs_object_hash_proto; +extern const njs_flathsh_proto_t njs_object_hash_proto; #endif /* _NJS_VM_H_INCLUDED_ */ diff --git a/src/njs_vmcode.c b/src/njs_vmcode.c index dbf7b116..07054f67 100644 --- a/src/njs_vmcode.c +++ b/src/njs_vmcode.c @@ -272,7 +272,22 @@ NEXT_LBL; value2 = &primitive1; } - ret = njs_value_property(vm, value1, value2, retval); + if (value2->atom_id == NJS_ATOM_STRING_unknown) { + num = njs_number(value2); + u32 = (uint32_t) num; + + if (njs_fast_path(u32 == num && (u32 < 0x80000000))) { + value2->atom_id = njs_number_atom(u32); + + } else { + ret = njs_atom_atomize_key(vm, value2); + if (njs_slow_path(ret != NJS_OK)) { + goto error; + } + } + } + + ret = njs_value_property(vm, value1, value2->atom_id, retval); if (njs_slow_path(ret == NJS_ERROR)) { goto error; } @@ -397,7 +412,7 @@ NEXT_LBL; get = (njs_vmcode_prop_get_t *) pc; njs_vmcode_operand(vm, get->value, retval); - ret = njs_value_property(vm, value1, value2, retval); + ret = njs_value_property_val(vm, value1, value2, retval); if (njs_slow_path(ret == NJS_ERROR)) { goto error; } @@ -921,7 +936,7 @@ NEXT_LBL; value2 = &primitive1; } - ret = njs_value_property_delete(vm, value1, value2, NULL, 1); + ret = njs_value_property_val_delete(vm, value1, value2, NULL, 1); if (njs_slow_path(ret == NJS_ERROR)) { goto error; } @@ -951,7 +966,7 @@ NEXT_LBL; njs_vmcode_operand(vm, vmcode->operand3, value2); njs_vmcode_operand(vm, vmcode->operand2, value1); - ret = njs_values_strict_equal(value1, value2); + ret = njs_values_strict_equal(vm, value1, value2); njs_vmcode_operand(vm, vmcode->operand1, retval); njs_set_boolean(retval, ret); @@ -965,7 +980,7 @@ NEXT_LBL; njs_vmcode_operand(vm, vmcode->operand3, value2); njs_vmcode_operand(vm, vmcode->operand2, value1); - ret = njs_values_strict_equal(value1, value2); + ret = njs_values_strict_equal(vm, value1, value2); njs_vmcode_operand(vm, vmcode->operand1, retval); njs_set_boolean(retval, !ret); @@ -1255,7 +1270,22 @@ NEXT_LBL; value2 = &primitive2; } - ret = njs_value_property_set(vm, value1, value2, retval); + if (value2->atom_id == NJS_ATOM_STRING_unknown) { + num = njs_number(value2); + u32 = (uint32_t) num; + + if (njs_fast_path(u32 == num && (u32 < 0x80000000))) { + value2->atom_id = njs_number_atom(u32); + + } else { + ret = njs_atom_atomize_key(vm, value2); + if (njs_slow_path(ret != NJS_OK)) { + goto error; + } + } + } + + ret = njs_value_property_set(vm, value1, value2->atom_id, retval); if (njs_slow_path(ret == NJS_ERROR)) { goto error; } @@ -1280,8 +1310,8 @@ NEXT_LBL; goto error; } - ret = njs_object_prop_define(vm, value1, &name, function, - accessor->type, 0); + ret = njs_object_prop_define_val(vm, value1, &name, function, + accessor->type); if (njs_slow_path(ret != NJS_OK)) { goto error; } @@ -1321,7 +1351,7 @@ NEXT_LBL; njs_vmcode_operand(vm, vmcode->operand3, value2); njs_vmcode_operand(vm, vmcode->operand2, value1); - if (njs_values_strict_equal(value1, value2)) { + if (njs_values_strict_equal(vm, value1, value2)) { equal = (njs_vmcode_equal_jump_t *) pc; ret = equal->offset; @@ -1411,7 +1441,7 @@ NEXT_LBL; value2 = &primitive1; } - ret = njs_value_property(vm, value1, value2, &dst); + ret = njs_value_property_val(vm, value1, value2, &dst); if (njs_slow_path(ret == NJS_ERROR)) { goto error; } @@ -1946,6 +1976,7 @@ njs_vmcode_template_literal(njs_vm_t *vm, njs_value_t *retval) { njs_array_t *array; njs_jump_off_t ret; + njs_value_t arguments[1]; static const njs_function_t concat = { .native = 1, @@ -1956,7 +1987,9 @@ njs_vmcode_template_literal(njs_vm_t *vm, njs_value_t *retval) array = njs_array(retval); - ret = njs_function_call(vm, (njs_function_t *) &concat, &njs_string_empty, + njs_set_empty_string(vm, &arguments[0]); + + ret = njs_function_call(vm, (njs_function_t *) &concat, &arguments[0], array->start, array->length, retval); if (njs_slow_path(ret != NJS_OK)) { return ret; @@ -1991,13 +2024,13 @@ static njs_jump_off_t njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, njs_value_t *init) { - double num; - uint32_t index, size; - njs_int_t ret; - njs_array_t *array; - njs_value_t *val, name; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + double num; + uint32_t index, size; + njs_int_t ret; + njs_array_t *array; + njs_value_t *val, name; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; switch (value->type) { case NJS_ARRAY: @@ -2035,24 +2068,39 @@ njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, break; case NJS_OBJECT: + if (key->type == NJS_STRING) { + if (key->atom_id == NJS_ATOM_STRING_unknown) { + ret = njs_atom_atomize_key(vm, key); + if (ret != NJS_OK) { + return ret; + } + } + } + ret = njs_value_to_key(vm, &name, key); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - njs_object_property_key_set(&lhq, &name, 0); - lhq.proto = &njs_object_hash_proto; - lhq.pool = vm->mem_pool; + if (name.atom_id == NJS_ATOM_STRING_unknown) { + ret = njs_atom_atomize_key(vm, &name); + if (ret != NJS_OK) { + return ret; + } + } - prop = njs_object_prop_alloc(vm, &name, init, 1); + prop = njs_object_prop_alloc(vm, init, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } lhq.value = prop; + lhq.key_hash = name.atom_id; lhq.replace = 1; + lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; - ret = njs_lvlhsh_insert(njs_object_hash(value), &lhq); + ret = njs_flathsh_unique_insert(njs_object_hash(value), &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert/replace failed"); return NJS_ERROR; @@ -2076,20 +2124,19 @@ static njs_jump_off_t njs_vmcode_proto_init(njs_vm_t *vm, njs_value_t *value, njs_value_t *unused, njs_value_t *init) { - njs_object_t *obj; - njs_value_t retval; - njs_jump_off_t ret; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; - - lhq.key = njs_str_value("__proto__"); - lhq.key_hash = NJS___PROTO___HASH; + njs_object_t *obj; + njs_value_t retval; + njs_jump_off_t ret; + njs_object_prop_t *prop; + njs_flathsh_query_t lhq; + + lhq.key_hash = NJS_ATOM_STRING___proto__; lhq.proto = &njs_object_hash_proto; lhq.pool = vm->mem_pool; obj = njs_object(value); - ret = njs_lvlhsh_find(&obj->__proto__->shared_hash, &lhq); + ret = njs_flathsh_unique_find(&obj->__proto__->shared_hash, &lhq); if (njs_slow_path(ret != NJS_OK)) { goto fail; } @@ -2100,7 +2147,7 @@ njs_vmcode_proto_init(njs_vm_t *vm, njs_value_t *value, njs_value_t *unused, goto fail; } - ret = njs_prop_handler(prop)(vm, prop, value, init, &retval); + ret = njs_prop_handler(prop)(vm, prop, lhq.key_hash, value, init, &retval); if (njs_slow_path(ret != NJS_OK)) { goto fail; } @@ -2137,9 +2184,9 @@ njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, key = &primitive; } - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0, 0); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); - ret = njs_property_query(vm, &pq, value, key); + ret = njs_property_query_val(vm, &pq, value, key); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -2190,8 +2237,6 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs_value_t *object, njs_function_t *function; njs_jump_off_t ret; - static const njs_value_t prototype_string = njs_string("prototype"); - if (!njs_is_function(constructor)) { njs_type_error(vm, "right argument is not callable"); return NJS_ERROR; @@ -2206,8 +2251,8 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs_value_t *object, } if (njs_is_object(object)) { - ret = njs_value_property(vm, constructor, - njs_value_arg(&prototype_string), &value); + ret = njs_value_property(vm, constructor, NJS_ATOM_STRING_prototype, + &value); if (njs_slow_path(ret == NJS_ERROR)) { return ret; @@ -2246,37 +2291,37 @@ njs_vmcode_typeof(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval) { /* ECMAScript 5.1: null, array and regexp are objects. */ - static const njs_value_t *types[NJS_VALUE_TYPE_MAX] = { - &njs_string_object, - &njs_string_undefined, - &njs_string_boolean, - &njs_string_number, - &njs_string_symbol, - &njs_string_string, - &njs_string_data, - &njs_string_external, - &njs_string_invalid, - &njs_string_undefined, - &njs_string_undefined, - &njs_string_undefined, - &njs_string_undefined, - &njs_string_undefined, - &njs_string_undefined, - &njs_string_undefined, - - &njs_string_object, - &njs_string_object, - &njs_string_function, - &njs_string_object, - &njs_string_object, - &njs_string_object, - &njs_string_object, - &njs_string_object, - &njs_string_object, - &njs_string_object, + static const uint32_t types[NJS_VALUE_TYPE_MAX] = { + NJS_ATOM_STRING_object, + NJS_ATOM_STRING_undefined, + NJS_ATOM_STRING_boolean, + NJS_ATOM_STRING_number, + NJS_ATOM_STRING_symbol, + NJS_ATOM_STRING_string, + NJS_ATOM_STRING_data, + NJS_ATOM_STRING_external, + NJS_ATOM_STRING_unknown, + NJS_ATOM_STRING_undefined, + NJS_ATOM_STRING_undefined, + NJS_ATOM_STRING_undefined, + NJS_ATOM_STRING_undefined, + NJS_ATOM_STRING_undefined, + NJS_ATOM_STRING_undefined, + NJS_ATOM_STRING_undefined, + + NJS_ATOM_STRING_object, + NJS_ATOM_STRING_object, + NJS_ATOM_STRING_function, + NJS_ATOM_STRING_object, + NJS_ATOM_STRING_object, + NJS_ATOM_STRING_object, + NJS_ATOM_STRING_object, + NJS_ATOM_STRING_object, + NJS_ATOM_STRING_object, + NJS_ATOM_STRING_object, }; - njs_value_assign(retval, types[value->type]); + njs_atom_to_value(vm, retval, types[value->type]); return sizeof(njs_vmcode_2addr_t); } @@ -2314,8 +2359,8 @@ njs_string_concat(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2, size_t size, length; njs_string_prop_t string1, string2; - (void) njs_string_prop(&string1, val1); - (void) njs_string_prop(&string2, val2); + (void) njs_string_prop(vm, &string1, val1); + (void) njs_string_prop(vm, &string2, val2); length = string1.length + string2.length; size = string1.size + string2.size; @@ -2358,7 +2403,7 @@ again: if (val1->type == val2->type) { if (njs_is_string(val1)) { - return njs_string_eq(val1, val2); + return njs_string_eq(vm, val1, val2); } if (njs_is_symbol(val1)) { @@ -2392,7 +2437,7 @@ again: /* If "hv" is a string then "lv" can be a numeric or symbol. */ if (njs_is_string(hv)) { return !njs_is_symbol(lv) - && (njs_number(lv) == njs_string_to_number(hv)); + && (njs_number(lv) == njs_string_to_number(vm, hv)); } /* "hv" is an object and "lv" is either a string or a symbol or a numeric. */ @@ -2429,15 +2474,15 @@ njs_primitive_values_compare(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2) num2 = njs_number(val2); } else { - num2 = njs_string_to_number(val2); + num2 = njs_string_to_number(vm, val2); } } else if (njs_is_numeric(val2)) { - num1 = njs_string_to_number(val1); + num1 = njs_string_to_number(vm, val1); num2 = njs_number(val2); } else { - return (njs_string_cmp(val1, val2) < 0) ? 1 : 0; + return (njs_string_cmp(vm, val1, val2) < 0) ? 1 : 0; } /* NaN and void values are not comparable with anything. */ @@ -2521,8 +2566,6 @@ njs_function_new_object(njs_vm_t *vm, njs_value_t *constructor) njs_function_t *function; njs_jump_off_t ret; - const njs_value_t prototype_string = njs_string("prototype"); - object = njs_object_alloc(vm); if (njs_slow_path(object == NULL)) { return NULL; @@ -2538,8 +2581,7 @@ njs_function_new_object(njs_vm_t *vm, njs_value_t *constructor) constructor = &bound; } - ret = njs_value_property(vm, constructor, njs_value_arg(&prototype_string), - &proto); + ret = njs_value_property(vm, constructor, NJS_ATOM_STRING_prototype, &proto); if (njs_slow_path(ret == NJS_ERROR)) { return NULL; diff --git a/src/test/njs_benchmark.c b/src/test/njs_benchmark.c index 66c4e84b..7f1a7400 100644 --- a/src/test/njs_benchmark.c +++ b/src/test/njs_benchmark.c @@ -728,9 +728,9 @@ njs_benchmark_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_str_t s, mode; njs_opaque_value_t value; - njs_value_string_get(njs_arg(args, nargs, 1), &mode); + njs_value_string_get(vm, njs_arg(args, nargs, 1), &mode); - njs_value_string_get(njs_arg(args, nargs, 2), &s); + njs_value_string_get(vm, njs_arg(args, nargs, 2), &s); if (njs_value_to_integer(vm, njs_arg(args, nargs, 3), &n) != NJS_OK) { return NJS_ERROR; diff --git a/src/test/njs_externals_test.c b/src/test/njs_externals_test.c index 33f0020a..8d71aae7 100644 --- a/src/test/njs_externals_test.c +++ b/src/test/njs_externals_test.c @@ -146,7 +146,7 @@ lvlhsh_unit_test_add(njs_mp_t *pool, njs_unit_test_req_t *r, static njs_int_t -njs_unit_test_r_uri(njs_vm_t *vm, njs_object_prop_t *prop, +njs_unit_test_r_uri(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { char *p; @@ -169,8 +169,8 @@ njs_unit_test_r_uri(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -njs_unit_test_r_a(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *unused, njs_value_t *retval) +njs_unit_test_r_a(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *unused2, njs_value_t *retval) { u_char *p; njs_unit_test_req_t *r; @@ -189,8 +189,8 @@ njs_unit_test_r_a(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -njs_unit_test_r_b(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *unused, njs_value_t *retval) +njs_unit_test_r_b(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *unused2, njs_value_t *retval) { njs_value_number_set(retval, njs_vm_prop_magic32(prop)); @@ -199,8 +199,8 @@ njs_unit_test_r_b(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -njs_unit_test_r_d(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *unused, njs_value_t *retval) +njs_unit_test_r_d(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, + njs_value_t *value, njs_value_t *unused2, njs_value_t *retval) { njs_unit_test_req_t *r; @@ -217,7 +217,7 @@ njs_unit_test_r_d(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -njs_unit_test_r_host(njs_vm_t *vm, njs_object_prop_t *prop, +njs_unit_test_r_host(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { return njs_vm_value_string_create(vm, retval, (u_char *) "АБВГДЕЁЖЗИЙ", 22); @@ -225,7 +225,7 @@ njs_unit_test_r_host(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -njs_unit_test_r_buffer(njs_vm_t *vm, njs_object_prop_t *prop, +njs_unit_test_r_buffer(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { return njs_vm_value_buffer_set(vm, retval, (u_char *) "АБВГДЕЁЖЗИЙ", 22); @@ -233,7 +233,7 @@ njs_unit_test_r_buffer(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t -njs_unit_test_r_vars(njs_vm_t *vm, njs_object_prop_t *self, +njs_unit_test_r_vars(njs_vm_t *vm, njs_object_prop_t *self, uint32_t atom_id, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { njs_int_t ret; @@ -247,7 +247,7 @@ njs_unit_test_r_vars(njs_vm_t *vm, njs_object_prop_t *self, return NJS_DECLINED; } - ret = njs_vm_prop_name(vm, self, &lhq.key); + ret = njs_vm_prop_name(vm, atom_id, &lhq.key); if (ret != NJS_OK) { if (setval == NULL && retval != NULL) { /* Get. */ @@ -314,14 +314,14 @@ njs_unit_test_r_vars(njs_vm_t *vm, njs_object_prop_t *self, static njs_int_t -njs_unit_test_r_header(njs_vm_t *vm, njs_object_prop_t *prop, +njs_unit_test_r_header(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t atom_id, njs_value_t *value, njs_value_t *unused, njs_value_t *retval) { njs_int_t ret; njs_str_t h; njs_chb_t chain; - ret = njs_vm_prop_name(vm, prop, &h); + ret = njs_vm_prop_name(vm, atom_id, &h); if (ret == NJS_OK) { NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); @@ -640,7 +640,7 @@ njs_unit_test_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t -njs_unit_test_error_name(njs_vm_t *vm, njs_object_prop_t *prop, +njs_unit_test_error_name(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { return njs_vm_value_string_create(vm, retval, (u_char *) "ExternalError", @@ -650,7 +650,8 @@ njs_unit_test_error_name(njs_vm_t *vm, njs_object_prop_t *prop, static njs_int_t njs_unit_test_error_message(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) + uint32_t unused, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { return njs_vm_value_string_create(vm, retval, (u_char *) "", 0); } diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 9c935e5b..cc1cc4c9 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -4172,6 +4172,11 @@ static njs_unit_test_t njs_test[] = { njs_str("var a = [ 1, 2, 3 ]; a[4294967296] = 4; a + a[4294967296]"), njs_str("1,2,34") }, + { njs_str("var x = []; var k = 1;" + "for (var i = 0; i < 32; i++) { k = k * 2; x[k - 2] = k; };" + "k = 1; for (i = 0; i < 32; i++) { k = k * 2; if (x[k - 2] != k) { throw 'error'; } }"), + njs_str("undefined") }, + { njs_str("delete[]['4e9']"), njs_str("true") }, @@ -5880,6 +5885,11 @@ static njs_unit_test_t njs_test[] = " return njs.dump(a) === `${v.name} [1,1,1]`})"), njs_str("true") }, + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var a = new v([0]); var desc = Object.getOwnPropertyDescriptor(a, '0');" + " try { Object.defineProperty(a, '1', desc) } catch (e) { return e.name == 'TypeError' }})"), + njs_str("true") }, + { njs_str(NJS_TYPED_ARRAY_LIST ".every(v=>{try {var a = new v([1,1]); Object.defineProperty(a, '1', {configurable:true})} " " catch (e) { return e.message == 'Cannot redefine property: \"1\"'}})"), @@ -14324,6 +14334,9 @@ static njs_unit_test_t njs_test[] = { njs_str("Object.prototype.toString.call()"), njs_str("[object Undefined]") }, + { njs_str("Object.prototype.toString.call().length"), + njs_str("18") }, + { njs_str("Object.prototype.toString.call(undefined)"), njs_str("[object Undefined]") }, From noreply at nginx.com Wed Apr 30 01:50:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 30 Apr 2025 01:50:02 +0000 (UTC) Subject: [njs] Introduced NJS_VMCODE_PROPERTY_ATOM_GET instruction. Message-ID: <20250430015002.A73D947E8A@pubserv1.nginx> details: https://github.com/nginx/njs/commit/c5679450137ada06d678901c0fe264e5f7f5db56 branches: master commit: c5679450137ada06d678901c0fe264e5f7f5db56 user: Dmitry Volyntsev date: Wed, 26 Mar 2025 00:23:23 -0700 description: Introduced NJS_VMCODE_PROPERTY_ATOM_GET instruction. --- src/njs_disassembler.c | 2 ++ src/njs_generator.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- src/njs_parser.c | 2 +- src/njs_vmcode.c | 17 +++++++++++++++++ src/njs_vmcode.h | 1 + 5 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/njs_disassembler.c b/src/njs_disassembler.c index 7c645339..d3300443 100644 --- a/src/njs_disassembler.c +++ b/src/njs_disassembler.c @@ -35,6 +35,8 @@ static njs_code_name_t code_names[] = { { NJS_VMCODE_PROPERTY_GET, sizeof(njs_vmcode_prop_get_t), njs_str("PROP GET ") }, + { NJS_VMCODE_PROPERTY_ATOM_GET, sizeof(njs_vmcode_prop_get_t), + njs_str("PROP ATOM GET ") }, { NJS_VMCODE_GLOBAL_GET, sizeof(njs_vmcode_prop_get_t), njs_str("GLOBAL GET ") }, { NJS_VMCODE_PROPERTY_INIT, sizeof(njs_vmcode_prop_set_t), diff --git a/src/njs_generator.c b/src/njs_generator.c index a2cc4b1c..c3f741d3 100644 --- a/src/njs_generator.c +++ b/src/njs_generator.c @@ -3395,6 +3395,7 @@ njs_generate_operation_assignment_prop(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { njs_index_t index, src, prop_index; + njs_vmcode_t opcode; njs_parser_node_t *lvalue, *object, *property; njs_vmcode_move_t *move; njs_vmcode_3addr_t *to_property_key; @@ -3453,8 +3454,19 @@ njs_generate_operation_assignment_prop(njs_vm_t *vm, njs_generator_t *generator, return NJS_ERROR; } + if (property->token_type == NJS_TOKEN_STRING + || (property->token_type == NJS_TOKEN_NUMBER + && property->u.value.atom_id != NJS_ATOM_STRING_unknown)) + { + opcode = NJS_VMCODE_PROPERTY_ATOM_GET; + + } else { + opcode = NJS_VMCODE_PROPERTY_GET; + } + njs_generate_code(generator, njs_vmcode_prop_get_t, prop_get, - NJS_VMCODE_PROPERTY_GET, property); + opcode, property); + prop_get->value = index; prop_get->object = object->index; prop_get->property = prop_index; @@ -3874,14 +3886,26 @@ njs_generate_3addr_operation_end(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { njs_bool_t swap; + njs_vmcode_t opcode; njs_parser_node_t *left, *right; njs_vmcode_3addr_t *code; left = node->left; right = node->right; + if (node->u.operation == NJS_VMCODE_PROPERTY_GET + && (right->token_type == NJS_TOKEN_STRING + || (right->token_type == NJS_TOKEN_NUMBER + && right->u.value.atom_id != NJS_ATOM_STRING_unknown))) + { + opcode = NJS_VMCODE_PROPERTY_ATOM_GET; + + } else { + opcode = node->u.operation; + } + njs_generate_code(generator, njs_vmcode_3addr_t, code, - node->u.operation, node); + opcode, node); swap = *((njs_bool_t *) generator->context); @@ -4074,7 +4098,8 @@ njs_generate_inc_dec_operation_prop(njs_vm_t *vm, njs_generator_t *generator, njs_int_t ret; njs_bool_t post; njs_index_t index, dest_index, prop_index; - njs_parser_node_t *lvalue; + njs_vmcode_t opcode; + njs_parser_node_t *lvalue, *prop; njs_vmcode_3addr_t *code, *to_property_key; njs_vmcode_prop_get_t *prop_get; njs_vmcode_prop_set_t *prop_set; @@ -4122,8 +4147,21 @@ found: return NJS_ERROR; } + prop = lvalue->right; + + if (prop->token_type == NJS_TOKEN_STRING + || (prop->token_type == NJS_TOKEN_NUMBER + && prop->u.value.atom_id != NJS_ATOM_STRING_unknown)) + { + opcode = NJS_VMCODE_PROPERTY_ATOM_GET; + + } else { + opcode = NJS_VMCODE_PROPERTY_GET; + } + njs_generate_code(generator, njs_vmcode_prop_get_t, prop_get, - NJS_VMCODE_PROPERTY_GET, node); + opcode, node); + prop_get->value = index; prop_get->object = lvalue->left->index; prop_get->property = prop_index; diff --git a/src/njs_parser.c b/src/njs_parser.c index a3564396..50cee672 100644 --- a/src/njs_parser.c +++ b/src/njs_parser.c @@ -2295,7 +2295,7 @@ njs_parser_property(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } - node->u.operation = NJS_VMCODE_PROPERTY_GET; + node->u.operation = NJS_VMCODE_PROPERTY_ATOM_GET; node->token_line = token->line; prop_node = njs_parser_node_string(parser->vm, token, parser); diff --git a/src/njs_vmcode.c b/src/njs_vmcode.c index 07054f67..301a1394 100644 --- a/src/njs_vmcode.c +++ b/src/njs_vmcode.c @@ -182,6 +182,7 @@ njs_vmcode_interpreter(njs_vm_t *vm, u_char *pc, njs_value_t *rval, NJS_GOTO_ROW(NJS_VMCODE_ASSIGNMENT_ERROR), NJS_GOTO_ROW(NJS_VMCODE_ERROR), NJS_GOTO_ROW(NJS_VMCODE_MOVE), + NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_ATOM_GET), NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_GET), NJS_GOTO_ROW(NJS_VMCODE_INCREMENT), NJS_GOTO_ROW(NJS_VMCODE_POST_INCREMENT), @@ -249,6 +250,22 @@ NEXT_LBL; pc += sizeof(njs_vmcode_move_t); NEXT; + CASE (NJS_VMCODE_PROPERTY_ATOM_GET): + njs_vmcode_debug_opcode(); + + njs_vmcode_operand(vm, vmcode->operand3, value2); + njs_vmcode_operand(vm, vmcode->operand2, value1); + get = (njs_vmcode_prop_get_t *) pc; + njs_vmcode_operand(vm, get->value, retval); + + ret = njs_value_property(vm, value1, value2->atom_id, retval); + if (njs_slow_path(ret == NJS_ERROR)) { + goto error; + } + + pc += sizeof(njs_vmcode_prop_get_t); + NEXT; + CASE (NJS_VMCODE_PROPERTY_GET): njs_vmcode_debug_opcode(); diff --git a/src/njs_vmcode.h b/src/njs_vmcode.h index ed9ae1b3..2e56db47 100644 --- a/src/njs_vmcode.h +++ b/src/njs_vmcode.h @@ -63,6 +63,7 @@ enum { NJS_VMCODE_ASSIGNMENT_ERROR, NJS_VMCODE_ERROR, NJS_VMCODE_MOVE, + NJS_VMCODE_PROPERTY_ATOM_GET, NJS_VMCODE_PROPERTY_GET, NJS_VMCODE_INCREMENT, NJS_VMCODE_POST_INCREMENT, From noreply at nginx.com Wed Apr 30 01:50:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 30 Apr 2025 01:50:02 +0000 (UTC) Subject: [njs] Introduced NJS_VMCODE_PROPERTY_ATOM_SET instruction. Message-ID: <20250430015002.AEEC647E8D@pubserv1.nginx> details: https://github.com/nginx/njs/commit/2d4788c2516b23f8ad66fb0bccc29d6af09b2040 branches: master commit: 2d4788c2516b23f8ad66fb0bccc29d6af09b2040 user: Dmitry Volyntsev date: Fri, 21 Mar 2025 22:52:55 -0700 description: Introduced NJS_VMCODE_PROPERTY_ATOM_SET instruction. --- src/njs_disassembler.c | 2 ++ src/njs_generator.c | 66 +++++++++++++++++++++++++++++++++++++++++--------- src/njs_vmcode.c | 16 ++++++++++++ src/njs_vmcode.h | 1 + 4 files changed, 74 insertions(+), 11 deletions(-) diff --git a/src/njs_disassembler.c b/src/njs_disassembler.c index d3300443..c7927bf5 100644 --- a/src/njs_disassembler.c +++ b/src/njs_disassembler.c @@ -45,6 +45,8 @@ static njs_code_name_t code_names[] = { njs_str("PROTO INIT ") }, { NJS_VMCODE_PROPERTY_SET, sizeof(njs_vmcode_prop_set_t), njs_str("PROP SET ") }, + { NJS_VMCODE_PROPERTY_ATOM_SET, sizeof(njs_vmcode_prop_set_t), + njs_str("PROP ATOM SET ") }, { NJS_VMCODE_PROPERTY_IN, sizeof(njs_vmcode_3addr_t), njs_str("PROP IN ") }, { NJS_VMCODE_PROPERTY_DELETE, sizeof(njs_vmcode_3addr_t), diff --git a/src/njs_generator.c b/src/njs_generator.c index c3f741d3..a6209cce 100644 --- a/src/njs_generator.c +++ b/src/njs_generator.c @@ -2296,18 +2296,30 @@ static njs_int_t njs_generate_for_in_set_prop_block(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { - njs_parser_node_t *foreach; - njs_vmcode_prop_set_t *prop_set; - njs_generator_loop_ctx_t *ctx; + njs_vmcode_t opcode; + njs_parser_node_t *foreach, *prop; + njs_vmcode_prop_set_t *prop_set; + njs_generator_loop_ctx_t *ctx; ctx = generator->context; foreach = node->left; + prop = foreach->left->right; + + if (prop->token_type == NJS_TOKEN_STRING + || (prop->token_type == NJS_TOKEN_NUMBER + && prop->u.value.atom_id != NJS_ATOM_STRING_unknown)) + { + opcode = NJS_VMCODE_PROPERTY_ATOM_SET; + + } else { + opcode = NJS_VMCODE_PROPERTY_SET; + } njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, - NJS_VMCODE_PROPERTY_SET, foreach); + opcode, foreach); prop_set->object = foreach->left->left->index; - prop_set->property = foreach->left->right->index; + prop_set->property = prop->index; prop_set->value = ctx->index_next_value; njs_generator_next(generator, njs_generate, node->right); @@ -3024,7 +3036,7 @@ njs_generate_global_property_set(njs_vm_t *vm, njs_generator_t *generator, var = njs_variable_reference(vm, node_dst); if (var == NULL) { njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, - NJS_VMCODE_PROPERTY_SET, node_src); + NJS_VMCODE_PROPERTY_ATOM_SET, node_src); prop_set->value = node_dst->index; prop_set->object = njs_scope_global_this_index(); @@ -3190,6 +3202,7 @@ njs_generate_assignment_end(njs_vm_t *vm, njs_generator_t *generator, { njs_int_t ret; njs_index_t prop_index; + njs_vmcode_t opcode; njs_parser_node_t *lvalue, *expr, *object, *property; njs_vmcode_2addr_t *set_function, *to_prop_key; njs_vmcode_prop_set_t *prop_set; @@ -3246,9 +3259,18 @@ njs_generate_assignment_end(njs_vm_t *vm, njs_generator_t *generator, break; default: - /* NJS_VMCODE_PROPERTY_SET */ + if (property->token_type == NJS_TOKEN_STRING + || (property->token_type == NJS_TOKEN_NUMBER + && property->u.value.atom_id != NJS_ATOM_STRING_unknown)) + { + opcode = NJS_VMCODE_PROPERTY_ATOM_SET; + + } else { + opcode = NJS_VMCODE_PROPERTY_SET; + } + njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, - NJS_VMCODE_PROPERTY_SET, expr); + opcode, expr); } prop_set->value = expr->index; @@ -3486,7 +3508,8 @@ njs_generate_operation_assignment_end(njs_vm_t *vm, njs_generator_t *generator, { njs_int_t ret; njs_index_t prop_index; - njs_parser_node_t *lvalue, *expr; + njs_vmcode_t opcode; + njs_parser_node_t *lvalue, *expr, *prop; njs_vmcode_3addr_t *code; njs_vmcode_prop_set_t *prop_set; @@ -3501,8 +3524,21 @@ njs_generate_operation_assignment_end(njs_vm_t *vm, njs_generator_t *generator, code->src1 = node->index; code->src2 = expr->index; + prop = lvalue->right; + + if (prop->token_type == NJS_TOKEN_STRING + || (prop->token_type == NJS_TOKEN_NUMBER + && prop->u.value.atom_id != NJS_ATOM_STRING_unknown)) + { + opcode = NJS_VMCODE_PROPERTY_ATOM_SET; + + } else { + opcode = NJS_VMCODE_PROPERTY_SET; + } + njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, - NJS_VMCODE_PROPERTY_SET, expr); + opcode, expr); + prop_set->value = node->index; prop_set->object = lvalue->left->index; prop_set->property = prop_index; @@ -4172,8 +4208,16 @@ found: code->src1 = index; code->src2 = index; + if (opcode == NJS_VMCODE_PROPERTY_ATOM_GET) { + opcode = NJS_VMCODE_PROPERTY_ATOM_SET; + + } else { + opcode = NJS_VMCODE_PROPERTY_SET; + } + njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, - NJS_VMCODE_PROPERTY_SET, node); + opcode, node); + prop_set->value = index; prop_set->object = lvalue->left->index; prop_set->property = prop_index; diff --git a/src/njs_vmcode.c b/src/njs_vmcode.c index 301a1394..3826f9eb 100644 --- a/src/njs_vmcode.c +++ b/src/njs_vmcode.c @@ -149,6 +149,7 @@ njs_vmcode_interpreter(njs_vm_t *vm, u_char *pc, njs_value_t *rval, NJS_GOTO_ROW(NJS_VMCODE_PUT_ARG), NJS_GOTO_ROW(NJS_VMCODE_STOP), NJS_GOTO_ROW(NJS_VMCODE_JUMP), + NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_ATOM_SET), NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_SET), NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_ACCESSOR), NJS_GOTO_ROW(NJS_VMCODE_IF_TRUE_JUMP), @@ -1264,6 +1265,21 @@ NEXT_LBL; ret = (njs_jump_off_t) vmcode->operand1; BREAK; + CASE (NJS_VMCODE_PROPERTY_ATOM_SET): + njs_vmcode_debug_opcode(); + + njs_vmcode_operand(vm, vmcode->operand3, value2); + njs_vmcode_operand(vm, vmcode->operand2, value1); + njs_vmcode_operand(vm, vmcode->operand1, retval); + + ret = njs_value_property_set(vm, value1, value2->atom_id, retval); + if (njs_slow_path(ret == NJS_ERROR)) { + goto error; + } + + ret = sizeof(njs_vmcode_prop_set_t); + BREAK; + CASE (NJS_VMCODE_PROPERTY_SET): njs_vmcode_debug_opcode(); diff --git a/src/njs_vmcode.h b/src/njs_vmcode.h index 2e56db47..83507f63 100644 --- a/src/njs_vmcode.h +++ b/src/njs_vmcode.h @@ -30,6 +30,7 @@ enum { NJS_VMCODE_PUT_ARG = 0, NJS_VMCODE_STOP, NJS_VMCODE_JUMP, + NJS_VMCODE_PROPERTY_ATOM_SET, NJS_VMCODE_PROPERTY_SET, NJS_VMCODE_PROPERTY_ACCESSOR, NJS_VMCODE_IF_TRUE_JUMP, From noreply at nginx.com Wed Apr 30 05:51:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 30 Apr 2025 05:51:02 +0000 (UTC) Subject: [njs] Tests: fixed js_body_filter.t tests. Message-ID: <20250430055102.0ADEB47E89@pubserv1.nginx> details: https://github.com/nginx/njs/commit/1496ed3f5820dbaec91fe7fdba2da8ee387bb36b branches: master commit: 1496ed3f5820dbaec91fe7fdba2da8ee387bb36b user: Dmitry Volyntsev date: Mon, 28 Apr 2025 18:28:08 -0700 description: Tests: fixed js_body_filter.t tests. Previously, '|' was used incorrectly in test match pattern. --- nginx/t/js_body_filter.t | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/nginx/t/js_body_filter.t b/nginx/t/js_body_filter.t index 679b6cba..d0c74238 100644 --- a/nginx/t/js_body_filter.t +++ b/nginx/t/js_body_filter.t @@ -151,7 +151,7 @@ $t->write_file('test.js', <= Number(r.args.len)) { - r.sendBuffer(`\${data}|`, flags); + r.sendBuffer(`\${data}#`, flags); if (r.args.dup && !flags.last) { r.sendBuffer(data, flags); @@ -178,14 +178,14 @@ $t->try_run('no njs body filter')->plan(7); ############################################################################### -like(http_get('/append'), qr/AAABBCDDDDXXX/, 'append'); -like(http_get('/buffer_type'), qr/AAABBCDDDD/, 'buffer type'); -like(http_get('/buffer_type_nonutf8'), qr/\xaa\xaa\xbb\xcc\xdd\xdd/, +like(http_get('/append'), qr/AAABBCDDDDXXX$/, 'append'); +like(http_get('/buffer_type'), qr/AAABBCDDDD$/, 'buffer type'); +like(http_get('/buffer_type_nonutf8'), qr/\xaa\xaa\xbb\xcc\xdd\xdd$/, 'buffer type nonutf8'); -like(http_get('/forward'), qr/AAABBCDDDD/, 'forward'); -like(http_get('/filter?len=3'), qr/AAA|DDDD|/, 'filter 3'); -like(http_get('/filter?len=2&dup=1'), qr/AAA|AAABB|BBDDDD|DDDD/, +like(http_get('/forward'), qr/AAABBCDDDD$/, 'forward'); +like(http_get('/filter?len=3'), qr/AAA#DDDD##$/, 'filter 3'); +like(http_get('/filter?len=2&dup=1'), qr/AAA#AAABB#BBDDDD#DDDD#$/, 'filter 2 dup'); -like(http_get('/prepend'), qr/XXXAAABBCDDDD/, 'prepend'); +like(http_get('/prepend'), qr/XXXAAABBCDDDD$/, 'prepend'); ############################################################################### From noreply at nginx.com Wed Apr 30 05:51:02 2025 From: noreply at nginx.com (noreply at nginx.com) Date: Wed, 30 Apr 2025 05:51:02 +0000 (UTC) Subject: [njs] Tests: improved js_body_filter.t tests. Message-ID: <20250430055102.0D3E346C03@pubserv1.nginx> details: https://github.com/nginx/njs/commit/7f901b6f87a29ab74d18040c18aebb5b5918b028 branches: master commit: 7f901b6f87a29ab74d18040c18aebb5b5918b028 user: Dmitry Volyntsev date: Mon, 28 Apr 2025 18:34:29 -0700 description: Tests: improved js_body_filter.t tests. Dropping Content-Length header in locations where response body length is modified. This is not strictly needed for the test itself, but can serve as an example for a typical body modification task. --- nginx/t/js_body_filter.t | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/nginx/t/js_body_filter.t b/nginx/t/js_body_filter.t index d0c74238..5fc8292a 100644 --- a/nginx/t/js_body_filter.t +++ b/nginx/t/js_body_filter.t @@ -46,6 +46,7 @@ http { } location /append { + js_header_filter test.clear_content_length; js_body_filter test.append; proxy_pass http://127.0.0.1:8081/source; } @@ -67,11 +68,13 @@ http { location /filter { proxy_buffering off; + js_header_filter test.clear_content_length; js_body_filter test.filter; proxy_pass http://127.0.0.1:8081/source; } location /prepend { + js_header_filter test.clear_content_length; js_body_filter test.prepend; proxy_pass http://127.0.0.1:8081/source; } @@ -108,6 +111,10 @@ $t->write_file('test.js', <write_file('test.js', < a + b.length, 0); r.sendHeader(); chain(chunks, 0); } @@ -170,15 +178,16 @@ $t->write_file('test.js', <try_run('no njs body filter')->plan(7); +$t->try_run('no njs body filter')->plan(8); ############################################################################### like(http_get('/append'), qr/AAABBCDDDDXXX$/, 'append'); +unlike(http_get('/append'), qr/Content-Length/, 'append no content-length'); like(http_get('/buffer_type'), qr/AAABBCDDDD$/, 'buffer type'); like(http_get('/buffer_type_nonutf8'), qr/\xaa\xaa\xbb\xcc\xdd\xdd$/, 'buffer type nonutf8');