var uncurryThis = require('../internals/function-uncurry-this'); var hasOwn = require('../internals/has-own-property'); var $SyntaxError = SyntaxError; var $parseInt = parseInt; var fromCharCode = String.fromCharCode; var at = uncurryThis(''.charAt); var slice = uncurryThis(''.slice); var exec = uncurryThis(/./.exec); var codePoints = { '\\"': '"', '\\\\': '\\', '\\/': '/', '\\b': '\b', '\\f': '\f', '\\n': '\n', '\\r': '\r', '\\t': '\t' }; var IS_4_HEX_DIGITS = /^[\da-f]{4}$/i; // eslint-disable-next-line regexp/no-control-character -- safe var IS_C0_CONTROL_CODE = /^[\u0000-\u001F]$/; module.exports = function (source, i) { var unterminated = true; var value = ''; while (i < source.length) { var chr = at(source, i); if (chr == '\\') { var twoChars = slice(source, i, i + 2); if (hasOwn(codePoints, twoChars)) { value += codePoints[twoChars]; i += 2; } else if (twoChars == '\\u') { i += 2; var fourHexDigits = slice(source, i, i + 4); if (!exec(IS_4_HEX_DIGITS, fourHexDigits)) throw $SyntaxError('Bad Unicode escape at: ' + i); value += fromCharCode($parseInt(fourHexDigits, 16)); i += 4; } else throw $SyntaxError('Unknown escape sequence: "' + twoChars + '"'); } else if (chr == '"') { unterminated = false; i++; break; } else { if (exec(IS_C0_CONTROL_CODE, chr)) throw $SyntaxError('Bad control character in string literal at: ' + i); value += chr; i++; } } if (unterminated) throw $SyntaxError('Unterminated string at: ' + i); return { value: value, end: i }; };