]> git.kaiwu.me - quickjs.git/commitdiff
added String.prototype.isWellFormed and String.prototype.toWellFormed
authorFabrice Bellard <fabrice@bellard.org>
Wed, 27 Dec 2023 16:16:47 +0000 (17:16 +0100)
committerFabrice Bellard <fabrice@bellard.org>
Wed, 27 Dec 2023 16:16:47 +0000 (17:16 +0100)
TODO
quickjs.c
test262.conf

diff --git a/TODO b/TODO
index 2ebf6202a26bb6da39d7962df516c1365eb258d7..92d89d29bc6dd3b04b0da2c418d0c3f174414ab6 100644 (file)
--- a/TODO
+++ b/TODO
@@ -63,5 +63,5 @@ Optimization ideas:
 Test262o:   0/11262 errors, 463 excluded
 Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
 
-Result: 16/76387 errors, 1497 excluded, 8397 skipped
+Result: 16/76419 errors, 1497 excluded, 8381 skipped
 Test262 commit: 31126581e7290f9233c29cefd93f66c6ac78f1c9
index cb98fda28fc56a2051b6fc26fa81d51ec6dcae05..99e96d68d8112a92fc16df48df6527379a1e52a0 100644 (file)
--- a/quickjs.c
+++ b/quickjs.c
@@ -40824,6 +40824,84 @@ static int64_t string_advance_index(JSString *p, int64_t index, BOOL unicode)
     return index;
 }
 
+/* return the position of the first invalid character in the string or
+   -1 if none */
+static int js_string_find_invalid_codepoint(JSString *p)
+{
+    int i, c;
+    if (!p->is_wide_char)
+        return -1;
+    for(i = 0; i < p->len; i++) {
+        c = p->u.str16[i];
+        if (c >= 0xD800 && c <= 0xDFFF) {
+            if (c >= 0xDC00 || (i + 1) >= p->len)
+                return i;
+            c = p->u.str16[i + 1];
+            if (c < 0xDC00 || c > 0xDFFF)
+                return i;
+            i++;
+        }
+    }
+    return -1;
+}
+
+static JSValue js_string_isWellFormed(JSContext *ctx, JSValueConst this_val,
+                                      int argc, JSValueConst *argv)
+{
+    JSValue str;
+    JSString *p;
+    BOOL ret;
+    
+    str = JS_ToStringCheckObject(ctx, this_val);
+    if (JS_IsException(str))
+        return JS_EXCEPTION;
+    p = JS_VALUE_GET_STRING(str);
+    ret = (js_string_find_invalid_codepoint(p) < 0);
+    JS_FreeValue(ctx, str);
+    return JS_NewBool(ctx, ret);
+}
+
+static JSValue js_string_toWellFormed(JSContext *ctx, JSValueConst this_val,
+                                      int argc, JSValueConst *argv)
+{
+    JSValue str, ret;
+    JSString *p;
+    int c, i;
+
+    str = JS_ToStringCheckObject(ctx, this_val);
+    if (JS_IsException(str))
+        return JS_EXCEPTION;
+
+    p = JS_VALUE_GET_STRING(str);
+    /* avoid reallocating the string if it is well-formed */
+    i = js_string_find_invalid_codepoint(p);
+    if (i < 0)
+        return str;
+
+    ret = js_new_string16(ctx, p->u.str16, p->len);
+    JS_FreeValue(ctx, str);
+    if (JS_IsException(ret))
+        return JS_EXCEPTION;
+    
+    p = JS_VALUE_GET_STRING(ret);
+    for (; i < p->len; i++) {
+        c = p->u.str16[i];
+        if (c >= 0xD800 && c <= 0xDFFF) {
+            if (c >= 0xDC00 || (i + 1) >= p->len) {
+                p->u.str16[i] = 0xFFFD;
+            } else {
+                c = p->u.str16[i + 1];
+                if (c < 0xDC00 || c > 0xDFFF) {
+                    p->u.str16[i] = 0xFFFD;
+                } else {
+                    i++;
+                }
+            }
+        }
+    }
+    return ret;
+}
+
 static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val,
                                  int argc, JSValueConst *argv, int lastIndexOf)
 {
@@ -42044,6 +42122,8 @@ static const JSCFunctionListEntry js_string_proto_funcs[] = {
     JS_CFUNC_MAGIC_DEF("charAt", 1, js_string_charAt, 0 ),
     JS_CFUNC_DEF("concat", 1, js_string_concat ),
     JS_CFUNC_DEF("codePointAt", 1, js_string_codePointAt ),
+    JS_CFUNC_DEF("isWellFormed", 0, js_string_isWellFormed ),
+    JS_CFUNC_DEF("toWellFormed", 0, js_string_toWellFormed ),
     JS_CFUNC_MAGIC_DEF("indexOf", 1, js_string_indexOf, 0 ),
     JS_CFUNC_MAGIC_DEF("lastIndexOf", 1, js_string_indexOf, 1 ),
     JS_CFUNC_MAGIC_DEF("includes", 1, js_string_includes, 0 ),
index 1fec965a8a6e2265adf860eb2eb8b7fc42f7e226..7ba23495ce9125d9fda01b69882f0376a47d2e99 100644 (file)
@@ -169,10 +169,10 @@ String.fromCodePoint
 String.prototype.at
 String.prototype.endsWith
 String.prototype.includes
-String.prototype.isWellFormed=skip
+String.prototype.isWellFormed
 String.prototype.matchAll
 String.prototype.replaceAll
-String.prototype.toWellFormed=skip
+String.prototype.toWellFormed
 String.prototype.trimEnd
 String.prototype.trimStart
 super