nxt_uint_t nargs);
static njs_ret_t njs_string_from_char_code(njs_vm_t *vm,
njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
+static njs_ret_t njs_string_from_code_point(njs_vm_t *vm, njs_value_t *args,
+ nxt_uint_t nargs, njs_index_t unused);
static njs_ret_t njs_string_bytes_from(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused);
static njs_ret_t njs_string_bytes_from_array(njs_vm_t *vm,
{
.type = NJS_METHOD,
.name = njs_string("fromCodePoint"),
- .value = njs_native_function(njs_string_from_char_code, 0),
+ .value = njs_native_function(njs_string_from_code_point, 0),
.writable = 1,
.configurable = 1,
},
}
+static njs_ret_t
+njs_string_from_code_point(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ u_char *p;
+ double num;
+ size_t size;
+ int32_t code;
+ njs_ret_t ret;
+ nxt_uint_t i;
+
+ for (i = 1; i < nargs; i++) {
+ if (!njs_is_numeric(&args[i])) {
+ ret = njs_value_to_numeric(vm, &args[i], &args[i]);
+ if (ret != NXT_OK) {
+ return ret;
+ }
+ }
+ }
+
+ size = 0;
+
+ for (i = 1; i < nargs; i++) {
+ num = njs_number(&args[i]);
+ if (isnan(num)) {
+ goto range_error;
+ }
+
+ code = num;
+
+ if (code != num || code < 0 || code >= 0x110000) {
+ goto range_error;
+ }
+
+ size += nxt_utf8_size(code);
+ }
+
+ p = njs_string_alloc(vm, &vm->retval, size, nargs - 1);
+ if (nxt_slow_path(p == NULL)) {
+ return NXT_ERROR;
+ }
+
+ for (i = 1; i < nargs; i++) {
+ p = nxt_utf8_encode(p, njs_number(&args[i]));
+ }
+
+ return NXT_OK;
+
+range_error:
+
+ njs_range_error(vm, NULL);
+
+ return NXT_ERROR;
+}
+
+
static njs_ret_t
njs_string_prototype_index_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
{ nxt_string("String.fromCharCode('_').charCodeAt(0)"),
nxt_string("0") },
+ { nxt_string("String.fromCodePoint('_')"),
+ nxt_string("RangeError") },
+
{ nxt_string("String.fromCharCode(65.14)"),
nxt_string("A") },
+ { nxt_string("String.fromCodePoint(3.14)"),
+ nxt_string("RangeError") },
+
{ nxt_string("String.fromCharCode(65.14 + 65536)"),
nxt_string("A") },
+ { nxt_string("String.fromCodePoint(65 + 65536)"),
+ nxt_string("𐁁") },
+
{ nxt_string("String.fromCharCode(2**53 + 10)"),
nxt_string("\n") },
- { nxt_string("String.fromCharCode(65, 90)"),
- nxt_string("AZ") },
+ { nxt_string("String.fromCodePoint(1114111 + 1)"),
+ nxt_string("RangeError") },
- { nxt_string("String.fromCharCode(945, 946, 947)"),
- nxt_string("αβγ") },
+ { nxt_string("String.fromCharCode(65, 90) + String.fromCodePoint(65, 90)"),
+ nxt_string("AZAZ") },
+
+ { nxt_string("String.fromCharCode(945, 946, 947) + String.fromCodePoint(945, 946, 947)"),
+ nxt_string("αβγαβγ") },
{ nxt_string("(function() {"
" var n;"
"})()"),
nxt_string("65536") },
+#if (!NXT_HAVE_MEMORY_SANITIZER) /* very long test under MSAN */
+ { nxt_string("(function() {"
+ " var n;"
+ " for (n = 0; n <= 1114111; n++) {"
+ " if (String.fromCodePoint(n).codePointAt(0) !== n)"
+ " return n;"
+ " }"
+ " return -1"
+ "})()"),
+ nxt_string("-1") },
+#endif
+
{ nxt_string("var a = 'abcdef'; function f(a) {"
"return a.slice(a.indexOf('cd')) } f(a)"),
nxt_string("cdef") },
{ nxt_string("['ȿ', 'Ȿ', 'ȿ'.toUpperCase(), 'Ȿ'.toLowerCase()].map((v)=>v.toUTF8().length)"),
nxt_string("2,3,3,2") },
+#if (!NXT_HAVE_MEMORY_SANITIZER) /* very long tests under MSAN */
{ nxt_string("var a = [], code;"
- "for (code = 0; code < 65536; code++) {"
- " var s = String.fromCharCode(code);"
+ "for (code = 0; code <= 1114111; code++) {"
+ " var s = String.fromCodePoint(code);"
" var n = s.toUpperCase();"
" if (s != n && s != n.toLowerCase())"
" a.push(code);"
nxt_string("181,305,383,453,456,459,498,837,962,976,977,981,982,1008,1009,1013,7296,7297,7298,7299,7300,7301,7302,7303,7304,7835,8126") },
{ nxt_string("var a = [], code;"
- "for (code = 0; code < 65536; code++) {"
- " var s = String.fromCharCode(code);"
+ "for (code = 0; code <= 1114111; code++) {"
+ " var s = String.fromCodePoint(code);"
" var n = s.toLowerCase();"
" if (s != n && s != n.toUpperCase())"
" a.push(code);"
"} a"),
nxt_string("304,453,456,459,498,1012,7838,8486,8490,8491") },
+#endif
{ nxt_string("'abc'.trim()"),
nxt_string("abc") },