From 90649345e011cdb998efe216f5e94a38d81eb4d2 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Sun, 7 Jan 2018 01:43:59 +1100 Subject: Avoid String.fromCodePoint (IE compat) --- src/defs.js | 23 +++++++++++++++++------ src/lobject.js | 7 +++++-- src/lutf8lib.js | 3 ++- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/defs.js b/src/defs.js index e5ffe35..b96dcf5 100644 --- a/src/defs.js +++ b/src/defs.js @@ -173,11 +173,10 @@ const to_jsstring = function(value, from, to) { let str = ""; for (let i = (from!==void 0?from:0); i < to;) { - let u; let u0 = value[i++]; if (u0 < 0x80) { /* single byte sequence */ - u = u0; + str += String.fromCharCode(u0); } else if (u0 < 0xC2 || u0 > 0xF4) { throw RangeError("cannot convert invalid utf8 to javascript string"); } else if (u0 <= 0xDF) { @@ -185,7 +184,7 @@ const to_jsstring = function(value, from, to) { if (i >= to) throw RangeError("cannot convert invalid utf8 to javascript string"); let u1 = value[i++]; if ((u1&0xC0) !== 0x80) throw RangeError("cannot convert invalid utf8 to javascript string"); - u = ((u0 & 0x1F) << 6) + (u1 & 0x3F); + str += String.fromCharCode(((u0 & 0x1F) << 6) + (u1 & 0x3F)); } else if (u0 <= 0xEF) { /* three byte sequence */ if (i+1 >= to) throw RangeError("cannot convert invalid utf8 to javascript string"); @@ -193,7 +192,15 @@ const to_jsstring = function(value, from, to) { if ((u1&0xC0) !== 0x80) throw RangeError("cannot convert invalid utf8 to javascript string"); let u2 = value[i++]; if ((u2&0xC0) !== 0x80) throw RangeError("cannot convert invalid utf8 to javascript string"); - u = ((u0 & 0x0F) << 12) + ((u1 & 0x3F) << 6) + (u2 & 0x3F); + let u = ((u0 & 0x0F) << 12) + ((u1 & 0x3F) << 6) + (u2 & 0x3F); + if (u <= 0xFFFF) { /* BMP codepoint */ + str += String.fromCharCode(u); + } else { /* Astral codepoint */ + u -= 0x10000; + let s1 = (u >> 10) + 0xD800; + let s2 = (u % 0x400) + 0xDC00; + str += String.fromCharCode(s1, s2); + } } else { /* four byte sequence */ if (i+2 >= to) throw RangeError("cannot convert invalid utf8 to javascript string"); @@ -203,9 +210,13 @@ const to_jsstring = function(value, from, to) { if ((u2&0xC0) !== 0x80) throw RangeError("cannot convert invalid utf8 to javascript string"); let u3 = value[i++]; if ((u3&0xC0) !== 0x80) throw RangeError("cannot convert invalid utf8 to javascript string"); - u = ((u0 & 0x07) << 18) + ((u1 & 0x3F) << 12) + ((u2 & 0x3F) << 6) + (u3 & 0x3F); + /* Has to be astral codepoint */ + let u = ((u0 & 0x07) << 18) + ((u1 & 0x3F) << 12) + ((u2 & 0x3F) << 6) + (u3 & 0x3F); + u -= 0x10000; + let s1 = (u >> 10) + 0xD800; + let s2 = (u % 0x400) + 0xDC00; + str += String.fromCharCode(s1, s2); } - str += String.fromCodePoint(u); } return str; }; diff --git a/src/lobject.js b/src/lobject.js index bd10be8..b5d4a96 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -607,9 +607,12 @@ const luaO_pushvfstring = function(L, fmt, argp) { } break; } - case char['U']: - pushstr(L, defs.to_luastring(String.fromCodePoint(argp[a++]))); + case char['U']: { + let buff = new Uint8Array(UTF8BUFFSZ); + let l = luaO_utf8esc(buff, argp[a++]); + pushstr(L, buff.subarray(UTF8BUFFSZ - l)); break; + } case char['%']: pushstr(L, defs.to_luastring("%", true)); break; diff --git a/src/lutf8lib.js b/src/lutf8lib.js index 722d9f1..58533cf 100644 --- a/src/lutf8lib.js +++ b/src/lutf8lib.js @@ -76,10 +76,11 @@ const utflen = function(L) { return 1; }; +const p_U = lua.to_luastring("%U"); const pushutfchar = function(L, arg) { let code = lauxlib.luaL_checkinteger(L, arg); lauxlib.luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, lua.to_luastring("value out of range", true)); - lua.lua_pushstring(L, lua.to_luastring(String.fromCodePoint(code))); + lua.lua_pushfstring(L, p_U, code); }; /* -- cgit v1.2.3-70-g09d2