From bb0aac71f2139a96a5cb46473f42797a2fcf2f65 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Fri, 5 May 2023 20:08:56 -0700 Subject: [PATCH] Change: non-compliant deprecated String methods were removed. The following methods were removed: String.bytesFrom(), String.prototype.fromBytes(), String.prototype.fromUTF8(), String.prototype.toBytes(), String.prototype.toUTF8(), String.prototype.toString(encoding). Because String.bytesFrom() was used to test the existing code which works with byte strings it was replaced with $262.bytesString() which is only available in unit tests. --- src/njs_string.c | 445 +--------------------------------- src/test/njs_externals_test.c | 173 +++++++++++++ src/test/njs_unit_test.c | 367 +++++++--------------------- 3 files changed, 264 insertions(+), 721 deletions(-) diff --git a/src/njs_string.c b/src/njs_string.c index fef02995..24dff724 100644 --- a/src/njs_string.c +++ b/src/njs_string.c @@ -66,13 +66,6 @@ static njs_int_t njs_string_slice_args(njs_vm_t *vm, njs_slice_prop_t *slice, njs_value_t *args, njs_uint_t nargs); static njs_int_t njs_string_from_char_code(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t is_point, njs_value_t *retval); -static njs_int_t njs_string_bytes_from(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_string_bytes_from_array_like(njs_vm_t *vm, - njs_value_t *value, njs_value_t *retval); -static njs_int_t njs_string_bytes_from_string(njs_vm_t *vm, - const njs_value_t *string, const njs_value_t *encoding, - njs_value_t *retval); static njs_int_t njs_string_match_multiple(njs_vm_t *vm, njs_value_t *args, njs_regexp_pattern_t *pattern, njs_value_t *retval); @@ -660,8 +653,6 @@ static const njs_object_prop_t njs_string_constructor_properties[] = NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), - NJS_DECLARE_PROP_NATIVE("bytesFrom", njs_string_bytes_from, 0, 0), - NJS_DECLARE_PROP_NATIVE("fromCharCode", njs_string_from_char_code, 1, 0), NJS_DECLARE_PROP_NATIVE("fromCodePoint", njs_string_from_char_code, 1, 1), @@ -837,58 +828,11 @@ njs_string_prototype_value_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -/* - * String.prototype.toString([encoding]). - * Returns the string as is if no additional argument is provided, - * otherwise converts a string into an encoded string: hex, base64, - * base64url. - */ - static njs_int_t njs_string_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_str_t enc, str; - njs_value_t value; - njs_string_prop_t string; - - ret = njs_string_prototype_value_of(vm, args, nargs, unused, retval); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (nargs < 2) { - return NJS_OK; - } - - if (njs_slow_path(!njs_is_string(&args[1]))) { - njs_type_error(vm, "encoding must be a string"); - return NJS_ERROR; - } - - njs_value_assign(&value, retval); - - (void) njs_string_prop(&string, &value); - - njs_string_get(&args[1], &enc); - - str.length = string.size; - str.start = string.start; - - if (enc.length == 3 && memcmp(enc.start, "hex", 3) == 0) { - return njs_string_hex(vm, retval, &str); - - } else if (enc.length == 6 && memcmp(enc.start, "base64", 6) == 0) { - return njs_string_base64(vm, retval, &str); - - } else if (enc.length == 9 && memcmp(enc.start, "base64url", 9) == 0) { - return njs_string_base64url(vm, retval, &str); - } - - njs_type_error(vm, "Unknown encoding: \"%V\"", &enc); - - return NJS_ERROR; + return njs_string_prototype_value_of(vm, args, nargs, unused, retval); } @@ -977,226 +921,6 @@ njs_string_object_validate(njs_vm_t *vm, njs_value_t *object) } -/* - * String.fromUTF8(start[, end]). - * The method converts an UTF-8 encoded byte string to an Unicode string. - */ - -static njs_int_t -njs_string_prototype_from_utf8(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) -{ - ssize_t length; - njs_int_t ret; - njs_slice_prop_t slice; - njs_string_prop_t string; - - njs_deprecated(vm, "String.prototype.fromUTF8()"); - - ret = njs_string_object_validate(vm, njs_argument(args, 0)); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - ret = njs_string_slice_prop(vm, &string, &slice, args, nargs); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (string.length != 0) { - /* ASCII or UTF8 string. */ - return njs_string_slice(vm, retval, &string, &slice); - } - - string.start += slice.start; - - length = njs_utf8_length(string.start, slice.length); - - if (length >= 0) { - return njs_string_new(vm, retval, string.start, slice.length, - length); - } - - njs_set_null(retval); - - return NJS_OK; -} - - -/* - * String.toUTF8(start[, end]). - * The method serializes Unicode string to an UTF-8 encoded byte string. - */ - -static njs_int_t -njs_string_prototype_to_utf8(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_slice_prop_t slice; - njs_string_prop_t string; - - njs_deprecated(vm, "String.prototype.toUTF8()"); - - ret = njs_string_object_validate(vm, njs_argument(args, 0)); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - (void) njs_string_prop(&string, njs_argument(args, 0)); - - string.length = 0; - slice.string_length = string.size; - - ret = njs_string_slice_args(vm, &slice, args, nargs); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - return njs_string_slice(vm, retval, &string, &slice); -} - - -/* - * String.fromBytes(start[, end]). - * The method converts a byte string to an Unicode string. - */ - -static njs_int_t -njs_string_prototype_from_bytes(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) -{ - u_char *p, *s, *start, *end; - size_t size; - njs_int_t ret; - njs_slice_prop_t slice; - njs_string_prop_t string; - - njs_deprecated(vm, "String.prototype.fromBytes()"); - - ret = njs_string_object_validate(vm, njs_argument(args, 0)); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - ret = njs_string_slice_prop(vm, &string, &slice, args, nargs); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (string.length != 0) { - /* ASCII or UTF8 string. */ - return njs_string_slice(vm, retval, &string, &slice); - } - - size = 0; - string.start += slice.start; - end = string.start + slice.length; - - for (p = string.start; p < end; p++) { - size += (*p < 0x80) ? 1 : 2; - } - - start = njs_string_alloc(vm, retval, size, slice.length); - - if (njs_fast_path(start != NULL)) { - - if (size == slice.length) { - memcpy(start, string.start, size); - - } else { - s = start; - end = string.start + slice.length; - - for (p = string.start; p < end; p++) { - s = njs_utf8_encode(s, *p); - } - } - - return NJS_OK; - } - - return NJS_ERROR; -} - - -/* - * String.toBytes(start[, end]). - * The method serializes an Unicode string to a byte string. - * The method returns null if a character larger than 255 is - * encountered in the Unicode string. - */ - -static njs_int_t -njs_string_prototype_to_bytes(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused, njs_value_t *retval) -{ - u_char *p; - size_t length; - uint32_t byte; - njs_int_t ret; - const u_char *s, *end; - njs_slice_prop_t slice; - njs_string_prop_t string; - njs_unicode_decode_t ctx; - - njs_deprecated(vm, "String.prototype.toBytes()"); - - ret = njs_string_object_validate(vm, njs_argument(args, 0)); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - ret = njs_string_slice_prop(vm, &string, &slice, args, nargs); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (string.length == 0) { - /* Byte string. */ - return njs_string_slice(vm, retval, &string, &slice); - } - - p = njs_string_alloc(vm, retval, slice.length, 0); - - if (njs_fast_path(p != NULL)) { - - if (string.length != string.size) { - /* UTF-8 string. */ - end = string.start + string.size; - - s = njs_string_utf8_offset(string.start, end, slice.start); - - length = slice.length; - - njs_utf8_decode_init(&ctx); - - while (length != 0 && s < end) { - byte = njs_utf8_decode(&ctx, &s, end); - - if (njs_slow_path(byte > 0xFF)) { - njs_release(vm, retval); - njs_set_null(retval); - - return NJS_OK; - } - - *p++ = (u_char) byte; - length--; - } - - } else { - /* ASCII string. */ - memcpy(p, string.start + slice.start, slice.length); - } - - return NJS_OK; - } - - return NJS_ERROR; -} - - static njs_int_t njs_string_prototype_slice(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) @@ -1618,165 +1342,6 @@ done: } -/* - * String.bytesFrom(array-like). - * Converts an array-like object containing octets into a byte string. - * - * String.bytesFrom(string[, encoding]). - * Converts a string using provided encoding: hex, base64, base64url to - * a byte string. - */ - -static njs_int_t -njs_string_bytes_from(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused, njs_value_t *retval) -{ - njs_value_t *value; - - njs_deprecated(vm, "String.bytesFrom()"); - - value = njs_arg(args, nargs, 1); - - if (njs_is_string(value)) { - return njs_string_bytes_from_string(vm, value, njs_arg(args, nargs, 2), - retval); - - } else if (njs_is_object(value)) { - - if (njs_is_object_string(value)) { - value = njs_object_value(value); - return njs_string_bytes_from_string(vm, value, - njs_arg(args, nargs, 2), - retval); - } - - return njs_string_bytes_from_array_like(vm, value, retval); - } - - njs_type_error(vm, "value must be a string or array-like object"); - - return NJS_ERROR; -} - - -static njs_int_t -njs_string_bytes_from_array_like(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) -{ - u_char *p; - int64_t length; - uint32_t u32; - njs_int_t ret; - njs_array_t *array; - njs_value_t *octet, index, prop; - njs_array_buffer_t *buffer; - - array = NULL; - buffer = NULL; - - switch (value->type) { - case NJS_ARRAY: - array = njs_array(value); - length = array->length; - break; - - case NJS_ARRAY_BUFFER: - case NJS_TYPED_ARRAY: - - if (njs_is_typed_array(value)) { - buffer = njs_typed_array(value)->buffer; - - } else { - buffer = njs_array_buffer(value); - } - - length = buffer->size; - break; - - default: - ret = njs_object_length(vm, value, &length); - if (njs_slow_path(ret == NJS_ERROR)) { - return ret; - } - } - - p = njs_string_alloc(vm, retval, length, 0); - if (njs_slow_path(p == NULL)) { - return NJS_ERROR; - } - - if (array != NULL) { - octet = array->start; - - while (length != 0) { - ret = njs_value_to_uint32(vm, octet, &u32); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - *p++ = (u_char) u32; - octet++; - length--; - } - - } else if (buffer != NULL) { - memcpy(p, buffer->u.u8, length); - - } else { - p += length - 1; - - while (length != 0) { - njs_set_number(&index, length - 1); - - ret = njs_value_property(vm, value, &index, &prop); - if (njs_slow_path(ret == NJS_ERROR)) { - return ret; - } - - ret = njs_value_to_uint32(vm, &prop, &u32); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - *p-- = (u_char) u32; - length--; - } - } - - return NJS_OK; -} - - -static njs_int_t -njs_string_bytes_from_string(njs_vm_t *vm, const njs_value_t *string, - const njs_value_t *encoding, njs_value_t *retval) -{ - njs_str_t enc, str; - - if (!njs_is_string(encoding)) { - njs_type_error(vm, "\"encoding\" must be a string"); - return NJS_ERROR; - } - - njs_string_get(encoding, &enc); - njs_string_get(string, &str); - - if (enc.length == 3 && memcmp(enc.start, "hex", 3) == 0) { - return njs_string_decode_hex(vm, retval, &str); - - } else if (enc.length == 6 && memcmp(enc.start, "base64", 6) == 0) { - return njs_string_decode_base64(vm, retval, &str); - - } else if (enc.length == 9 && memcmp(enc.start, "base64url", 9) == 0) { - return njs_string_decode_base64url(vm, retval, &str); - } - - njs_type_error(vm, "Unknown encoding: \"%V\"", &enc); - - return NJS_ERROR; -} - - size_t njs_decode_hex_length(const njs_str_t *src, size_t *out_size) { @@ -4085,14 +3650,6 @@ static const njs_object_prop_t njs_string_prototype_properties[] = NJS_DECLARE_PROP_NATIVE("concat", njs_string_prototype_concat, 1, 0), - NJS_DECLARE_PROP_NATIVE("fromUTF8", njs_string_prototype_from_utf8, 0, 0), - - NJS_DECLARE_PROP_NATIVE("toUTF8", njs_string_prototype_to_utf8, 0, 0), - - NJS_DECLARE_PROP_NATIVE("fromBytes", njs_string_prototype_from_bytes, 0, 0), - - NJS_DECLARE_PROP_NATIVE("toBytes", njs_string_prototype_to_bytes, 0, 0), - NJS_DECLARE_PROP_NATIVE("slice", njs_string_prototype_slice, 2, 0), NJS_DECLARE_PROP_NATIVE("substring", njs_string_prototype_substring, 2, 0), diff --git a/src/test/njs_externals_test.c b/src/test/njs_externals_test.c index e31bee93..d2f12ee4 100644 --- a/src/test/njs_externals_test.c +++ b/src/test/njs_externals_test.c @@ -570,6 +570,168 @@ njs_262_detach_array_buffer(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } +static njs_int_t +njs_262_bytes_from_array_like(njs_vm_t *vm, njs_value_t *value, + njs_value_t *retval) +{ + u_char *p; + int64_t length; + uint32_t u32; + njs_int_t ret; + njs_array_t *array; + njs_value_t *octet, index, prop; + njs_array_buffer_t *buffer; + + array = NULL; + buffer = NULL; + + switch (value->type) { + case NJS_ARRAY: + array = njs_array(value); + length = array->length; + break; + + case NJS_ARRAY_BUFFER: + case NJS_TYPED_ARRAY: + + if (njs_is_typed_array(value)) { + buffer = njs_typed_array(value)->buffer; + + } else { + buffer = njs_array_buffer(value); + } + + length = buffer->size; + break; + + default: + ret = njs_object_length(vm, value, &length); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + } + + p = njs_string_alloc(vm, retval, length, 0); + if (njs_slow_path(p == NULL)) { + return NJS_ERROR; + } + + if (array != NULL) { + octet = array->start; + + while (length != 0) { + ret = njs_value_to_uint32(vm, octet, &u32); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + *p++ = (u_char) u32; + octet++; + length--; + } + + } else if (buffer != NULL) { + memcpy(p, buffer->u.u8, length); + + } else { + p += length - 1; + + while (length != 0) { + njs_set_number(&index, length - 1); + + ret = njs_value_property(vm, value, &index, &prop); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + ret = njs_value_to_uint32(vm, &prop, &u32); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + *p-- = (u_char) u32; + length--; + } + } + + return NJS_OK; +} + + +static njs_int_t +njs_262_bytes_from_string(njs_vm_t *vm, const njs_value_t *string, + const njs_value_t *encoding, njs_value_t *retval) +{ + njs_str_t enc, str; + + if (!njs_is_string(encoding)) { + njs_type_error(vm, "\"encoding\" must be a string"); + return NJS_ERROR; + } + + njs_string_get(encoding, &enc); + njs_string_get(string, &str); + + if (enc.length == 3 && memcmp(enc.start, "hex", 3) == 0) { + return njs_string_decode_hex(vm, retval, &str); + + } else if (enc.length == 6 && memcmp(enc.start, "base64", 6) == 0) { + return njs_string_decode_base64(vm, retval, &str); + + } else if (enc.length == 9 && memcmp(enc.start, "base64url", 9) == 0) { + return njs_string_decode_base64url(vm, retval, &str); + } + + njs_type_error(vm, "Unknown encoding: \"%V\"", &enc); + + return NJS_ERROR; +} + + +/* + * $262.byteString(array-like). + * Converts an array-like object containing octets into a byte string. + * + * $262.byteString(string[, encoding]). + * Converts a string using provided encoding: hex, base64, base64url to + * a byte string. + * + * Note: the function produces a byte string, and byte strings are deprecated. + * The function is provided for testing of existing code which works with + * byte strings. When code working with byte strings is removed + * the function will be removed as well. + */ + +static njs_int_t +njs_262_byte_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused, njs_value_t *retval) +{ + njs_value_t *value; + + value = njs_arg(args, nargs, 1); + + if (njs_is_string(value)) { + return njs_262_bytes_from_string(vm, value, njs_arg(args, nargs, 2), + retval); + + } else if (njs_is_object(value)) { + + if (njs_is_object_string(value)) { + value = njs_object_value(value); + return njs_262_bytes_from_string(vm, value, + njs_arg(args, nargs, 2), + retval); + } + + return njs_262_bytes_from_array_like(vm, value, retval); + } + + njs_type_error(vm, "value must be a string or array-like object"); + + return NJS_ERROR; +} + + static njs_external_t njs_unit_test_262_external[] = { { @@ -591,6 +753,17 @@ static njs_external_t njs_unit_test_262_external[] = { } }, + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("byteString"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = njs_262_byte_string, + } + }, + }; diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index a83cf7cf..27c433f9 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -1047,56 +1047,9 @@ static njs_unit_test_t njs_test[] = { njs_str("undefined - undefined"), njs_str("NaN") }, - /* String.toString() method. */ - { njs_str("'A'.toString()"), njs_str("A") }, - { njs_str("'A'.toBytes().toString('latin1')"), - njs_str("TypeError: Unknown encoding: \"latin1\"") }, - - { njs_str("'ABCD'.toBytes().toString('hex')"), - njs_str("41424344") }, - - { njs_str("'\\x00\\xAA\\xBB\\xFF'.toBytes().toString('hex')"), - njs_str("00aabbff") }, - - { njs_str("'\\x00\\xAA\\xBB\\xFF'.toBytes().toString('base64')"), - njs_str("AKq7/w==") }, - - { njs_str("'ABCD'.toBytes().toString('base64')"), - njs_str("QUJDRA==") }, - - { njs_str("'ABC'.toBytes().toString('base64')"), - njs_str("QUJD") }, - - { njs_str("'AB'.toBytes().toString('base64')"), - njs_str("QUI=") }, - - { njs_str("'A'.toBytes().toString('base64')"), - njs_str("QQ==") }, - - { njs_str("''.toBytes().toString('base64')"), - njs_str("") }, - - { njs_str("'\\x00\\xAA\\xBB\\xFF'.toBytes().toString('base64url')"), - njs_str("AKq7_w") }, - - { njs_str("'ABCD'.toBytes().toString('base64url')"), - njs_str("QUJDRA") }, - - { njs_str("'ABC'.toBytes().toString('base64url')"), - njs_str("QUJD") }, - - { njs_str("'AB'.toBytes().toString('base64url')"), - njs_str("QUI") }, - - { njs_str("'A'.toBytes().toString('base64url')"), - njs_str("QQ") }, - - { njs_str("''.toBytes().toString('base64url')"), - njs_str("") }, - /* Assignment. */ { njs_str("var a, b = (a = [2]) * (3 * 4); a +' '+ b"), @@ -4348,7 +4301,7 @@ static njs_unit_test_t njs_test[] = { njs_str("[" " 'α'.repeat(33)," - " String.bytesFrom(Array(16).fill(0x9d))," + " $262.byteString(Array(16).fill(0x9d))," "]" ".map(v=>{var out = ['β', 'γ'].join(v); return out.length})"), njs_str("35,20") }, @@ -4369,7 +4322,7 @@ static njs_unit_test_t njs_test[] = { njs_str("var a = ['β','γ']; a.join('').length"), njs_str("2") }, - { njs_str("var a = ['β', String.bytesFrom([0x9d]),'γ']; a.join('').length"), + { njs_str("var a = ['β', $262.byteString([0x9d]),'γ']; a.join('').length"), njs_str("5") }, { njs_str("var a = []; a[5] = 5; a.join()"), @@ -4708,7 +4661,7 @@ static njs_unit_test_t njs_test[] = { njs_str("Array.prototype.slice.call('αβZγ')"), njs_str("α,β,Z,γ") }, - { njs_str("Array.prototype.slice.call(String.bytesFrom(Array(16).fill(0x9d)))[0].charCodeAt(0)"), + { njs_str("Array.prototype.slice.call($262.byteString(Array(16).fill(0x9d)))[0].charCodeAt(0)"), njs_str("157") }, { njs_str("Array.prototype.slice.call('αβZγ', 1)"), @@ -7809,37 +7762,34 @@ static njs_unit_test_t njs_test[] = { njs_str("(new String('abc')).hasOwnProperty('length')"), njs_str("true") }, - { njs_str("'abc'.toUTF8().length"), - njs_str("3") }, - { njs_str("'абв'.length"), njs_str("3") }, - { njs_str("'абв'.toUTF8().length"), + { njs_str("(new TextEncoder()).encode('абв').length"), njs_str("6") }, { njs_str("'αβγ'.length"), njs_str("3") }, - { njs_str("'αβγ'.toUTF8().length"), + { njs_str("(new TextEncoder()).encode('αβγ').length"), njs_str("6") }, { njs_str("'絵文字'.length"), njs_str("3") }, - { njs_str("'絵文字'.toUTF8().length"), + { njs_str("(new TextEncoder()).encode('絵文字').length"), njs_str("9") }, { njs_str("'えもじ'.length"), njs_str("3") }, - { njs_str("'えもじ'.toUTF8().length"), + { njs_str("(new TextEncoder()).encode('えもじ').length"), njs_str("9") }, { njs_str("'囲碁織'.length"), njs_str("3") }, - { njs_str("'囲碁織'.toUTF8().length"), + { njs_str("(new TextEncoder()).encode('囲碁織').length"), njs_str("9") }, { njs_str("var a = 'abc'; a.length"), @@ -7995,76 +7945,12 @@ static njs_unit_test_t njs_test[] = "var a = 'abc'; a.concat('абв', s)"), njs_str("abcабв123") }, - { njs_str("'\\u00CE\\u00B1'.toBytes() == 'α'"), - njs_str("true") }, - - { njs_str("'\\u00CE\\u00B1'.toBytes() === 'α'"), - njs_str("true") }, - - { njs_str("var b = '\\u00C2\\u00B6'.toBytes(), u = b.fromUTF8();" - "b.length +' '+ b +' '+ u.length +' '+ u"), - njs_str("2 ¶ 1 ¶") }, - - { njs_str("'α'.toBytes()"), - njs_str("null") }, - - { njs_str("'α'.toUTF8()[0]"), - njs_str("\xCE") }, - { njs_str("var r = /^\\x80$/; r.source + r.source.length"), njs_str("^\\x80$6") }, { njs_str("var r = /^\\\\x80$/; r.source + r.source.length"), njs_str("^\\\\x80$7") }, - { njs_str("/^\\x80$/.test('\\x80'.toBytes())"), - njs_str("true") }, - - { njs_str("/^\\xC2\\x80$/.test('\\x80'.toUTF8())"), - njs_str("true") }, - - { njs_str("'α'.toUTF8().toBytes()"), - njs_str("α") }, - - { njs_str("var a = 'a'.toBytes() + 'α'; a + a.length"), - njs_str("aα3") }, - - { njs_str("var a = 'µ§±®'.toBytes(); a"), - njs_str("\xB5\xA7\xB1\xAE") }, - - { njs_str("var a = 'µ§±®'.toBytes(2); a"), - njs_str("\xB1\xAE") }, - - { njs_str("var a = 'µ§±®'.toBytes(1,3); a"), - njs_str("\xA7\xB1") }, - - { njs_str("var a = '\\xB5\\xA7\\xB1\\xAE'.toBytes(); a.fromBytes()"), - njs_str("µ§±®") }, - - { njs_str("var a = '\\xB5\\xA7\\xB1\\xAE'.toBytes(); a.fromBytes(2)"), - njs_str("±®") }, - - { njs_str("var a = '\\xB5\\xA7\\xB1\\xAE'.toBytes(); a.fromBytes(1, 3)"), - njs_str("§±") }, - - { njs_str("'A'.repeat(8).toBytes() === 'A'.repeat(8)"), - njs_str("true") }, - - { njs_str("'A'.repeat(16).toBytes() === 'A'.repeat(16)"), - njs_str("true") }, - - { njs_str("'A'.repeat(38).toBytes(-5) === 'AAAAA'"), - njs_str("true") }, - - { njs_str("('α' + 'A'.repeat(32)).toBytes()"), - njs_str("null") }, - - { njs_str("('α' + 'A'.repeat(32)).toBytes(1) === 'A'.repeat(32)"), - njs_str("true") }, - - { njs_str("('α' + 'A'.repeat(40)).toBytes(-3,-1)"), - njs_str("AA") }, - { njs_str("var s = 'x'.repeat(2**10).repeat(2**14);" "var a = Array(200).fill(s);" "String.prototype.concat.apply(s, a.slice(1))"), @@ -8160,9 +8046,6 @@ static njs_unit_test_t njs_test[] = { njs_str("String.prototype.slice(1, 5)"), njs_str("") }, - { njs_str("String.prototype.toBytes(1, 5)"), - njs_str("") }, - { njs_str("'abc'.charAt(1 + 1)"), njs_str("c") }, @@ -8461,9 +8344,6 @@ static njs_unit_test_t njs_test[] = { njs_str("var r = new String('undefined').indexOf(x); var x; r"), njs_str("0") }, - { njs_str("'a a'.toUTF8().indexOf('a', 1)"), - njs_str("2") }, - { njs_str("'aaa'.lastIndexOf()"), njs_str("-1") }, @@ -8658,9 +8538,6 @@ static njs_unit_test_t njs_test[] = { njs_str("'\x00абвгдеёжз'.toUpperCase().length"), njs_str("10") }, - { njs_str("['ȿ', 'Ȿ', 'ȿ'.toUpperCase(), 'Ȿ'.toLowerCase()].map((v)=>v.toUTF8().length)"), - njs_str("2,3,3,2") }, - #if (!NJS_HAVE_MEMORY_SANITIZER) /* very long tests under MSAN */ { njs_str("var a = [], code;" "for (code = 0; code <= 1114111; code++) {" @@ -8863,16 +8740,6 @@ static njs_unit_test_t njs_test[] = { njs_str("var r = 'αβγ'.replaceAll('', 'X'); [r, r.length]"), njs_str("XαXβXγX,7") }, - { njs_str("var s = 'αz'.toUTF8();" - "var r = s.replace('z', 'β');" - "r.length"), - njs_str("4") }, - - { njs_str("var s = 'αzz'.toUTF8();" - "var r = s.replaceAll('z', 'β');" - "r.length"), - njs_str("3") }, - { njs_str("'abc'.replace('b', (m, o, s) => `|${s}|${o}|${m}|`)"), njs_str("a|abc|1|b|c") }, @@ -9648,10 +9515,6 @@ static njs_unit_test_t njs_test[] = { njs_str("('β' + 'α'.repeat(33) +'β').match(/α+/g)[0][32]"), njs_str("α") }, - { njs_str("var a = '\\u00CE\\u00B1'.toBytes().match(/α/g)[0] + 'α';" - "a +' '+ a.length"), - njs_str("αα 4") }, - { njs_str("'abc'.split()"), njs_str("abc") }, @@ -9915,93 +9778,9 @@ static njs_unit_test_t njs_test[] = njs_str("TypeError: Cannot convert a Symbol value to a string") }, { njs_str("[undefined, null, Symbol()]" - ".every(v=> { try {String.bytesFrom(v);} catch(e) {return e.name == 'TypeError'} })"), + ".every(v=> { try {$262.byteString(v);} catch(e) {return e.name == 'TypeError'} })"), njs_str("true") }, - { njs_str("String.bytesFrom({}).length"), - njs_str("0") }, - - { njs_str("String.bytesFrom({length:5, 0:'A'.charCodeAt(0), 2:'X', 3:NaN,4:0xfd}).toString('hex')"), - njs_str("41000000fd") }, - - { njs_str("String.bytesFrom([1, 2, 0.23, '5', 'A']).toString('hex')"), - njs_str("0102000500") }, - - { njs_str("String.bytesFrom([NaN, Infinity]).toString('hex')"), - njs_str("0000") }, - - { njs_str("String.bytesFrom(new Uint8Array([0xff,0xde,0xba])).toString('hex')"), - njs_str("ffdeba") }, - - { njs_str("String.bytesFrom((new Uint8Array([0xff,0xde,0xba])).buffer).toString('hex')"), - njs_str("ffdeba") }, - - { njs_str("String.bytesFrom('', 'hex')"), - njs_str("") }, - - { njs_str("String.bytesFrom('00aabbcc', 'hex').toString('hex')"), - njs_str("00aabbcc") }, - - { njs_str("String.bytesFrom(new String('00aabbcc'), 'hex').toString('hex')"), - njs_str("00aabbcc") }, - - { njs_str("String.bytesFrom('deadBEEF##', 'hex').toString('hex')"), - njs_str("deadbeef") }, - - { njs_str("String.bytesFrom('aa0', 'hex').toString('hex')"), - njs_str("aa") }, - - { njs_str("String.bytesFrom('', 'base64')"), - njs_str("") }, - - { njs_str("String.bytesFrom('#', 'base64')"), - njs_str("") }, - - { njs_str("String.bytesFrom('QQ==', 'base64')"), - njs_str("A") }, - - { njs_str("String.bytesFrom('QQ=', 'base64')"), - njs_str("A") }, - - { njs_str("String.bytesFrom('QQ', 'base64')"), - njs_str("A") }, - - { njs_str("String.bytesFrom('Q', 'base64')"), - njs_str("") }, - - { njs_str("String.bytesFrom('QUI=', 'base64')"), - njs_str("AB") }, - - { njs_str("String.bytesFrom('QUI', 'base64')"), - njs_str("AB") }, - - { njs_str("String.bytesFrom('QUJD', 'base64')"), - njs_str("ABC") }, - - { njs_str("String.bytesFrom('QUJDRA==', 'base64')"), - njs_str("ABCD") }, - - { njs_str("String.bytesFrom('', 'base64url')"), - njs_str("") }, - - { njs_str("String.bytesFrom('QQ', 'base64url')"), - njs_str("A") }, - - { njs_str("String.bytesFrom('QUI', 'base64url')"), - njs_str("AB") }, - - { njs_str("String.bytesFrom('QUJD', 'base64url')"), - njs_str("ABC") }, - - { njs_str("String.bytesFrom('QUJDRA', 'base64url')"), - njs_str("ABCD") }, - - { njs_str("String.bytesFrom('QUJDRA#', 'base64url')"), - njs_str("ABCD") }, - - { njs_str("String.bytesFrom('QUJDRA#', 'base64lol')"), - njs_str("TypeError: Unknown encoding: \"base64lol\"") }, - { njs_str("encodeURI.name"), njs_str("encodeURI")}, @@ -10056,7 +9835,7 @@ static njs_unit_test_t njs_test[] = { njs_str("decodeURI('%D0%B0%D0%B1%D0%B2').length"), njs_str("3")}, - { njs_str("decodeURI(String.bytesFrom([0x80,0x80]))"), + { njs_str("decodeURI($262.byteString([0x80,0x80]))"), njs_str("URIError: malformed URI")}, { njs_str("[" @@ -10098,9 +9877,9 @@ static njs_unit_test_t njs_test[] = " String.fromCodePoint(0x100)," " String.fromCodePoint(0x00, 0x100)," " String.fromCodePoint(0x00, 0x01, 0x100)," - " String.bytesFrom([0x80])," - " String.bytesFrom([0x60, 0x80])," - " String.bytesFrom([0x60, 0x60, 0x80])," + " $262.byteString([0x80])," + " $262.byteString([0x60, 0x80])," + " $262.byteString([0x60, 0x60, 0x80])," "].map(v => { try { return btoa(v); } catch (e) { return '#'} })"), njs_str("dW5kZWZpbmVk,,AA==,AAE=,AAEC,AP7/,#,#,#,#,#,#")}, @@ -11793,15 +11572,9 @@ static njs_unit_test_t njs_test[] = { njs_str("/\\x80/.test('\\u0080')"), njs_str("true") }, - { njs_str("/\\x80/.test('\\u0080'.toBytes())"), - njs_str("true") }, - { njs_str("/α/.test('\\u03B1')"), njs_str("true") }, - { njs_str("/α/.test('\\u00CE\\u00B1'.toBytes())"), - njs_str("true") }, - { njs_str("/[A-Za-z]/.test('S')"), njs_str("true") }, @@ -11838,11 +11611,7 @@ static njs_unit_test_t njs_test[] = njs_str("3 БВ бв 2 /бв/gi") }, #endif - { njs_str("var r = /\\x80/g; r.exec('\\u0081\\u0080'.toBytes());" - "r.lastIndex +' '+ r.source +' '+ r.source.length +' '+ r"), - njs_str("2 \\x80 4 /\\x80/g") }, - - { njs_str("var r = /_/g; var index = r.exec(String.bytesFrom([255,149,15,97,95])).index;" + { njs_str("var r = /_/g; var index = r.exec($262.byteString([255,149,15,97,95])).index;" "[index, r.lastIndex]"), njs_str("4,5") }, @@ -12108,10 +11877,10 @@ static njs_unit_test_t njs_test[] = { njs_str("Error('e').name + ': ' + Error('e').message"), njs_str("Error: e") }, - { njs_str("Error(String.bytesFrom(Array(1).fill(0x9d))).toString().length"), + { njs_str("Error($262.byteString(Array(1).fill(0x9d))).toString().length"), njs_str("8") }, - { njs_str("var e = Error('α'); e.name = String.bytesFrom(Array(1).fill(0x9d)); " + { njs_str("var e = Error('α'); e.name = $262.byteString(Array(1).fill(0x9d)); " "e.toString().length"), njs_str("5") }, @@ -18500,9 +18269,7 @@ static njs_unit_test_t njs_test[] = { njs_str("JSON.stringify('абв'.repeat(100)).length"), njs_str("302") }, - /* Byte strings. */ - - { njs_str("JSON.stringify('\\u00CE\\u00B1\\u00C2\\u00B6'.toBytes())"), + { njs_str("JSON.stringify($262.byteString([0xCE, 0xB1, 0xC2, 0xB6]))"), njs_str("\"α¶\"") }, /* Optional arguments. */ @@ -18538,7 +18305,7 @@ static njs_unit_test_t njs_test[] = { njs_str("JSON.stringify([1], null, '!!βββββββββββββββββ').length"), njs_str("15") }, - { njs_str("JSON.stringify([1], null, String.bytesFrom([0x9d])).length"), + { njs_str("JSON.stringify([1], null, $262.byteString([0x9d])).length"), njs_str("InternalError: space argument cannot be a byte string") }, { njs_str("JSON.stringify([1], null, 11)"), @@ -19281,15 +19048,15 @@ static njs_unit_test_t njs_test[] = { njs_str("var en = new TextEncoder(); var res = en.encode('α1α'); res[2]"), njs_str("49") }, - { njs_str("var en = new TextEncoder(); en.encode(String.bytesFrom([0xCE]))"), + { njs_str("var en = new TextEncoder(); en.encode($262.byteString([0xCE]))"), njs_str("239,191,189") }, { njs_str("var en = new TextEncoder();" - "en.encode(String.bytesFrom([0xCE, 0xB1, 0xCE]))"), + "en.encode($262.byteString([0xCE, 0xB1, 0xCE]))"), njs_str("206,177,239,191,189") }, { njs_str("var en = new TextEncoder();" - "en.encode(String.bytesFrom([0xCE, 0xCE, 0xB1]))"), + "en.encode($262.byteString([0xCE, 0xCE, 0xB1]))"), njs_str("239,191,189,206,177") }, { njs_str("var en = new TextEncoder(); en.encoding"), @@ -19313,27 +19080,27 @@ static njs_unit_test_t njs_test[] = "en.encodeInto('ααααα', utf8.subarray(2)); utf8[0]"), njs_str("0") }, - { njs_str("var str = String.bytesFrom([0xCE]);" + { njs_str("var str = $262.byteString([0xCE]);" "var en = new TextEncoder();" "var utf8 = new Uint8Array(3);" "var res = en.encodeInto(str, utf8); " "[njs.dump(res), utf8]"), njs_str("{read:1,written:3},239,191,189") }, - { njs_str("var str = String.bytesFrom([0xCE]);" + { njs_str("var str = $262.byteString([0xCE]);" "var en = new TextEncoder();" "var utf8 = new Uint8Array(5);" "en.encodeInto(str, utf8); utf8"), njs_str("239,191,189,0,0") }, - { njs_str("var str = String.bytesFrom([0xCE, 0xB1, 0xCE]);" + { njs_str("var str = $262.byteString([0xCE, 0xB1, 0xCE]);" "var en = new TextEncoder();" "var utf8 = new Uint8Array(5);" "var res = en.encodeInto(str, utf8);" "[njs.dump(res), utf8]"), njs_str("{read:2,written:5},206,177,239,191,189") }, - { njs_str("var str = String.bytesFrom([0xCE, 0xCE, 0xB1]);" + { njs_str("var str = $262.byteString([0xCE, 0xCE, 0xB1]);" "var en = new TextEncoder();" "var utf8 = new Uint8Array(5);" "var res = en.encodeInto(str, utf8);" @@ -20796,11 +20563,6 @@ static njs_unit_test_t njs_querystring_module_test[] = "[x.length, x[33], x[34]]"), njs_str("66,1,α") }, - { njs_str("var qs = require('querystring');" - "var s = qs.parse('X='+String.bytesFrom(Array(16).fill(0x9d))).X;" - "[s.length, s.toUTF8().length, s[15]]"), - njs_str("16,48,�") }, - { njs_str("var qs = require('querystring');" "qs.stringify({'baz': 'fuz'})"), njs_str("baz=fuz") }, @@ -20830,7 +20592,7 @@ static njs_unit_test_t njs_querystring_module_test[] = { njs_str("var qs = require('querystring'); " "qs.stringify({a: 'b'}, null, null, " - " {encodeURIComponent: () => String.bytesFrom([0x9d])})"), + " {encodeURIComponent: () => $262.byteString([0x9d])})"), njs_str("InternalError: invalid UTF-8 string") }, { njs_str("var qs = require('querystring');" @@ -20883,7 +20645,7 @@ static njs_unit_test_t njs_querystring_module_test[] = njs_str("") }, { njs_str("var qs = require('querystring');" - "qs.stringify({X: String.bytesFrom(Array(4).fill(0x9d))})"), + "qs.stringify({X: $262.byteString(Array(4).fill(0x9d))})"), njs_str("X=%9D%9D%9D%9D") }, { njs_str("var qs = require('querystring');" @@ -21024,8 +20786,68 @@ static njs_unit_test_t njs_buffer_module_test[] = "].every(args => Buffer.byteLength(args[0], args[1]) == args[2])"), njs_str("true") }, - { njs_str("Buffer.from([])"), - njs_str("") }, + { njs_str("Buffer.from({length:5, 0:'A'.charCodeAt(0), 2:'X', 3:NaN,4:0xfd}).toString('hex')"), + njs_str("41000000fd") }, + + { njs_str("Buffer.from([1, 2, 0.23, '5', 'A']).toString('hex')"), + njs_str("0102000500") }, + + { njs_str("Buffer.from([NaN, Infinity]).toString('hex')"), + njs_str("0000") }, + + { njs_str("Buffer.from(new Uint8Array([0xff,0xde,0xba])).toString('hex')"), + njs_str("ffdeba") }, + + { njs_str("Buffer.from((new Uint8Array([0xff,0xde,0xba])).buffer).toString('hex')"), + njs_str("ffdeba") }, + + { njs_str("[" + " ['', '']," + " ['aa0', 'aa']," + " ['00aabbcc', '00aabbcc']," + " [new String('00aabbcc'), '00aabbcc']," + " ['deadBEEF##', 'deadbeef']," + "].every(args => { " + " if (Buffer.from(args[0], 'hex').toString('hex') != args[1]) {" + " throw `Buffer.from(\"${args[0]}\", 'hex').toString('hex') != \"${args[1]}\"`;" + " }" + " return true;" + "})"), + njs_str("true") }, + + { njs_str("[" + " ['', '']," + " ['#', '']," + " ['Q', '']," + " ['QQ', 'A']," + " ['QQ=', 'A']," + " ['QQ==', 'A']," + " ['QUI=', 'AB']," + " ['QUI', 'AB']," + " ['QUJD', 'ABC']," + " ['QUJDRA==', 'ABCD']," + "].every(args => { " + " if (Buffer.from(args[0], 'base64') != args[1]) {" + " throw `Buffer.from(\"${args[0]}\", 'base64') != \"${args[1]}\"`;" + " }" + " return true;" + "})"), + njs_str("true") }, + + { njs_str("[" + " ['', '']," + " ['QQ', 'A']," + " ['QUI', 'AB']," + " ['QUJD', 'ABC']," + " ['QUJDRA', 'ABCD']," + " ['QUJDRA#', 'ABCD']," + "].every(args => { " + " if (Buffer.from(args[0], 'base64url') != args[1]) {" + " throw `Buffer.from(\"${args[0]}\", 'base64url') != \"${args[1]}\"`;" + " }" + " return true;" + "})"), + njs_str("true") }, { njs_str("Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72])"), njs_str("buffer") }, @@ -21165,7 +20987,7 @@ static njs_unit_test_t njs_buffer_module_test[] = "].every(args => Buffer.from(args[0], args[1]) == 'evil')"), njs_str("true") }, - { njs_str("var buf = Buffer.from(String.bytesFrom([0xF3])); buf"), + { njs_str("var buf = Buffer.from($262.byteString([0xF3])); buf"), njs_str("�") }, { njs_str("Buffer.from('', 'utf-128')"), @@ -22293,21 +22115,12 @@ static njs_unit_test_t njs_externals_test[] = { njs_str("typeof $r"), njs_str("object") }, - { njs_str("var a = $r.uri, s = a.fromUTF8(); s.length +' '+ s"), - njs_str("3 АБВ") }, - { njs_str("var a = $r.uri, b = $r2.uri, c = $r3.uri; a+b+c"), njs_str("АБВαβγabc") }, { njs_str("var a = $r.uri; $r.uri = $r2.uri; $r2.uri = a; $r2.uri+$r.uri"), njs_str("АБВαβγ") }, - { njs_str("var a = $r.uri, s = a.fromUTF8(2); s.length +' '+ s"), - njs_str("2 БВ") }, - - { njs_str("var a = $r.uri, s = a.fromUTF8(2, 4); s.length +' '+ s"), - njs_str("1 Б") }, - { njs_str("var a = $r.uri; a +' '+ a.length +' '+ a"), njs_str("АБВ 6 АБВ") }, -- 2.47.3