@@ -40824,6 +40824,84 @@ static int64_t string_advance_index(JSString *p, int64_t index, BOOL unicode)
4082440824 return index;
4082540825}
4082640826
40827+ /* return the position of the first invalid character in the string or
40828+ -1 if none */
40829+ static int js_string_find_invalid_codepoint(JSString *p)
40830+ {
40831+ int i, c;
40832+ if (!p->is_wide_char)
40833+ return -1;
40834+ for(i = 0; i < p->len; i++) {
40835+ c = p->u.str16[i];
40836+ if (c >= 0xD800 && c <= 0xDFFF) {
40837+ if (c >= 0xDC00 || (i + 1) >= p->len)
40838+ return i;
40839+ c = p->u.str16[i + 1];
40840+ if (c < 0xDC00 || c > 0xDFFF)
40841+ return i;
40842+ i++;
40843+ }
40844+ }
40845+ return -1;
40846+ }
40847+
40848+ static JSValue js_string_isWellFormed(JSContext *ctx, JSValueConst this_val,
40849+ int argc, JSValueConst *argv)
40850+ {
40851+ JSValue str;
40852+ JSString *p;
40853+ BOOL ret;
40854+
40855+ str = JS_ToStringCheckObject(ctx, this_val);
40856+ if (JS_IsException(str))
40857+ return JS_EXCEPTION;
40858+ p = JS_VALUE_GET_STRING(str);
40859+ ret = (js_string_find_invalid_codepoint(p) < 0);
40860+ JS_FreeValue(ctx, str);
40861+ return JS_NewBool(ctx, ret);
40862+ }
40863+
40864+ static JSValue js_string_toWellFormed(JSContext *ctx, JSValueConst this_val,
40865+ int argc, JSValueConst *argv)
40866+ {
40867+ JSValue str, ret;
40868+ JSString *p;
40869+ int c, i;
40870+
40871+ str = JS_ToStringCheckObject(ctx, this_val);
40872+ if (JS_IsException(str))
40873+ return JS_EXCEPTION;
40874+
40875+ p = JS_VALUE_GET_STRING(str);
40876+ /* avoid reallocating the string if it is well-formed */
40877+ i = js_string_find_invalid_codepoint(p);
40878+ if (i < 0)
40879+ return str;
40880+
40881+ ret = js_new_string16(ctx, p->u.str16, p->len);
40882+ JS_FreeValue(ctx, str);
40883+ if (JS_IsException(ret))
40884+ return JS_EXCEPTION;
40885+
40886+ p = JS_VALUE_GET_STRING(ret);
40887+ for (; i < p->len; i++) {
40888+ c = p->u.str16[i];
40889+ if (c >= 0xD800 && c <= 0xDFFF) {
40890+ if (c >= 0xDC00 || (i + 1) >= p->len) {
40891+ p->u.str16[i] = 0xFFFD;
40892+ } else {
40893+ c = p->u.str16[i + 1];
40894+ if (c < 0xDC00 || c > 0xDFFF) {
40895+ p->u.str16[i] = 0xFFFD;
40896+ } else {
40897+ i++;
40898+ }
40899+ }
40900+ }
40901+ }
40902+ return ret;
40903+ }
40904+
4082740905static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val,
4082840906 int argc, JSValueConst *argv, int lastIndexOf)
4082940907{
@@ -42044,6 +42122,8 @@ static const JSCFunctionListEntry js_string_proto_funcs[] = {
4204442122 JS_CFUNC_MAGIC_DEF("charAt", 1, js_string_charAt, 0 ),
4204542123 JS_CFUNC_DEF("concat", 1, js_string_concat ),
4204642124 JS_CFUNC_DEF("codePointAt", 1, js_string_codePointAt ),
42125+ JS_CFUNC_DEF("isWellFormed", 0, js_string_isWellFormed ),
42126+ JS_CFUNC_DEF("toWellFormed", 0, js_string_toWellFormed ),
4204742127 JS_CFUNC_MAGIC_DEF("indexOf", 1, js_string_indexOf, 0 ),
4204842128 JS_CFUNC_MAGIC_DEF("lastIndexOf", 1, js_string_indexOf, 1 ),
4204942129 JS_CFUNC_MAGIC_DEF("includes", 1, js_string_includes, 0 ),
0 commit comments