From f3ea55fc6440ca9bf08e472f2d5e1f14ee0f4273 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Sun, 19 Jan 2014 15:06:10 +0100 Subject: [PATCH] Implement String.prototype.charAt and charCodeAt. --- jsbstring.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- jsobject.c | 3 ++- jsrun.c | 2 -- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/jsbstring.c b/jsbstring.c index 5c28822..2107538 100644 --- a/jsbstring.c +++ b/jsbstring.c @@ -32,6 +32,54 @@ static int Sp_valueOf(js_State *J, int n) return 1; } +static inline const char *utfindex(const char *s, int i) +{ + Rune rune; + int c, n = 0; + for (n = 0; n < i; ++n) { + c = *(unsigned char*)s; + if (c < Runeself) { + if (c == 0) + return NULL; + ++s; + } else + s += chartorune(&rune, s); + } + return s; +} + +static int Sp_charAt(js_State *J, int n) +{ + char buf[UTFmax + 1]; + const char *s = js_tostring(J, 0); + int pos = js_tointeger(J, 1); + s = utfindex(s, pos); + if (s) { + Rune rune; + chartorune(&rune, s); + buf[runetochar(buf, &rune)] = 0; + js_pushstring(J, buf); + } else { + js_pushliteral(J, ""); + } + return 1; +} + +static int Sp_charCodeAt(js_State *J, int n) +{ + const char *s = js_tostring(J, 0); + int pos = js_tointeger(J, 1); + s = utfindex(s, pos); + if (s) { + Rune rune; + chartorune(&rune, s); + js_pushnumber(J, rune); + } else { + js_pushnumber(J, NAN); + } + return 1; +} + static int S_fromCharCode(js_State *J, int n) { int i; @@ -39,7 +87,7 @@ static int S_fromCharCode(js_State *J, int n) char *s = malloc(n * UTFmax + 1), *p = s; // TODO: guard malloc with try/catch for (i = 0; i < n; i++) { - c = js_tonumber(J, i + 1); // TODO: ToUInt16() + c = js_tointeger(J, i + 1); // TODO: ToUInt16() p += runetochar(p, &c); } *p = 0; @@ -62,6 +110,8 @@ void jsB_initstring(js_State *J) js_setproperty(J, -2, "constructor"); jsB_propf(J, "toString", Sp_toString, 0); jsB_propf(J, "valueOf", Sp_valueOf, 0); + jsB_propf(J, "charAt", Sp_charAt, 1); + jsB_propf(J, "charCodeAt", Sp_charCodeAt, 1); } js_setproperty(J, -2, "prototype"); diff --git a/jsobject.c b/jsobject.c index 40b40a0..7081a62 100644 --- a/jsobject.c +++ b/jsobject.c @@ -3,6 +3,7 @@ #include "jsobject.h" #include "jsrun.h" #include "jsstate.h" +#include "jsutf.h" static js_Object *jsR_newfunction(js_State *J, js_Function *function, js_Environment *scope) { @@ -58,7 +59,7 @@ js_Object *jsR_newstring(js_State *J, const char *v) js_Property *ref; ref = jsR_setproperty(J, obj, "length"); ref->value.type = JS_TNUMBER; - ref->value.u.number = strlen(v); + ref->value.u.number = utflen(v); ref->readonly = 1; ref->dontenum = 1; ref->dontconf = 1; diff --git a/jsrun.c b/jsrun.c index 47e359f..ff41135 100644 --- a/jsrun.c +++ b/jsrun.c @@ -801,8 +801,6 @@ int jsR_loadscript(js_State *J, const char *filename, const char *source) jsP_optimize(J, P); F = jsC_compile(J, P); - jsP_dumpsyntax(J, P); - jsP_freeparse(J); if (!F) return 1;