gitoria
All repositories: gitoria
4.3 KB
// jsoncheck.hl — WORKAROUND for hybriel ticket #12 (no soft JSON.parse): JSON.parse throws on// invalid input and a Hybriel program cannot catch it, so the framework answers 500 with the// source location. The API therefore checks the body's JSON SYNTAX by hand first (RFC 8259// grammar, nesting depth capped at 64, NO \u surrogate escapes — hl's JSON.parse refuses// them, even valid pairs) and answers 400. REMOVE this file and its one call in// api.hl (readBody) once JSON.parse has a failure path (#12).//// jsonErrorAt(text) → -1 when `text` is one valid JSON value (surrounded by whitespace),// else the 0-based character position of the first offence.static maxDepth = 64static isWs = (c) => { return c == 32 || c == 9 || c == 10 || c == 13 }static isDigit = (c) => { return c >= 48 && c <= 57 }static isHex = (c) => { return (c >= 48 && c <= 57) || (c >= 65 && c <= 70) || (c >= 97 && c <= 102) }static hexValue = (c) => { return c <= 57 ? c - 48 : (c <= 70 ? c - 55 : c - 87) }// the 4 hex digits at `at` as a number, or -1static hexAt = (s, at) => {if (at + 4 > s.length) { return -1 }let v = 0let k = 0while (k < 4) {let c = s.charCodeAt(at + k)if (!isHex(c)) { return -1 }v = v * 16 + hexValue(c)k = k + 1}return v}static skipWs = (s, at) => {let i = atwhile (i < s.length && isWs(s.charCodeAt(i))) { i = i + 1 }return i}// each scanner answers the position after what it read, or -(position + 1) of an offencestatic bad = (i) => { return -(i + 1) }static scanString = (s, at) => {let i = ati = i + 1while (i < s.length) {let c = s.charCodeAt(i)if (c == 34) { return i + 1 }if (c < 32) { return bad(i) }if (c == 92) {i = i + 1if (i >= s.length) { return bad(i) }let e = s.charCodeAt(i)if (e == 117) {let u = hexAt(s, i + 1)if (u < 0) { return bad(i) }// hl's JSON.parse refuses EVERY surrogate escape (\uD800-\uDFFF), even a valid// pair like \ud83d\ude00 (hybriel issue, mission 004) — refuse it here: 400, not 500.// Send such characters as raw UTF-8 instead (JS JSON.stringify does).if (u >= 55296 && u <= 57343) { return bad(i) }i = i + 4} else if (!(e == 34 || e == 92 || e == 47 || e == 98 || e == 102 || e == 110 || e == 114 || e == 116)) {return bad(i)}}i = i + 1}return bad(i)}static scanDigits = (s, at) => {let i = atlet start = iwhile (i < s.length && isDigit(s.charCodeAt(i))) { i = i + 1 }return i == start ? bad(i) : i}static scanNumber = (s, at) => {let i = atif (s.charCodeAt(i) == 45) { i = i + 1 }if (i >= s.length || !isDigit(s.charCodeAt(i))) { return bad(i) }if (s.charCodeAt(i) == 48) { i = i + 1 } else { i = scanDigits(s, i) }if (i < s.length && s.charCodeAt(i) == 46) {i = scanDigits(s, i + 1)if (i < 0) { return i }}if (i < s.length && (s.charCodeAt(i) == 101 || s.charCodeAt(i) == 69)) {i = i + 1if (i < s.length && (s.charCodeAt(i) == 43 || s.charCodeAt(i) == 45)) { i = i + 1 }i = scanDigits(s, i)}return i}static scanWord = (s, i, word) => {return s.slice(i, i + word.length) == word ? i + word.length : bad(i)}static scanValue = (s, at, depth) => {let i = ati = skipWs(s, i)if (i >= s.length) { return bad(i) }let c = s.charCodeAt(i)if (c == 34) { return scanString(s, i) }if (c == 45 || isDigit(c)) { return scanNumber(s, i) }if (c == 116) { return scanWord(s, i, 'true') }if (c == 102) { return scanWord(s, i, 'false') }if (c == 110) { return scanWord(s, i, 'null') }if (c == 123 || c == 91) {if (depth >= maxDepth) { return bad(i) }let close = c == 123 ? 125 : 93i = skipWs(s, i + 1)if (i < s.length && s.charCodeAt(i) == close) { return i + 1 }while (true) {if (c == 123) {i = skipWs(s, i)if (i >= s.length || s.charCodeAt(i) != 34) { return bad(i) }i = scanString(s, i)if (i < 0) { return i }i = skipWs(s, i)if (i >= s.length || s.charCodeAt(i) != 58) { return bad(i) }i = i + 1}i = scanValue(s, i, depth + 1)if (i < 0) { return i }i = skipWs(s, i)if (i >= s.length) { return bad(i) }let d = s.charCodeAt(i)if (d == close) { return i + 1 }if (d != 44) { return bad(i) }i = i + 1}}return bad(i)}static jsonErrorAt = (text) => {let i = scanValue(text, 0, 0)if (i < 0) { return -i - 1 }i = skipWs(text, i)return i < text.length ? i : -1}
Branches
- mainmain branch
Latest commits
- 4a2d7125initial commitmre