UNPKG

ses

Version:

Hardened JavaScript for Fearless Cooperation

79 lines (69 loc) 2.2 kB
import { Number, String, TypeError, defineProperty, getOwnPropertyNames, isPrimitive, regexpExec, } from './commons.js'; import { assert } from './error/assert.js'; const { Fail, quote: q } = assert; const localePattern = /^(\w*[a-z])Locale([A-Z]\w*)$/; // Use concise methods to obtain named functions without constructor // behavior or `.prototype` property. const tamedMethods = { // See https://tc39.es/ecma262/#sec-string.prototype.localecompare localeCompare(arg) { if (this === null || this === undefined) { throw TypeError( 'Cannot localeCompare with null or undefined "this" value', ); } const s = `${this}`; const that = `${arg}`; if (s < that) { return -1; } if (s > that) { return 1; } s === that || Fail`expected ${q(s)} and ${q(that)} to compare`; return 0; }, toString() { return `${this}`; }, }; const nonLocaleCompare = tamedMethods.localeCompare; const numberToString = tamedMethods.toString; export default function tameLocaleMethods(intrinsics, localeTaming = 'safe') { if (localeTaming === 'unsafe') { return; } defineProperty(String.prototype, 'localeCompare', { value: nonLocaleCompare, }); for (const intrinsicName of getOwnPropertyNames(intrinsics)) { const intrinsic = intrinsics[intrinsicName]; if (!isPrimitive(intrinsic)) { for (const methodName of getOwnPropertyNames(intrinsic)) { const match = regexpExec(localePattern, methodName); if (match) { typeof intrinsic[methodName] === 'function' || Fail`expected ${q(methodName)} to be a function`; const nonLocaleMethodName = `${match[1]}${match[2]}`; const method = intrinsic[nonLocaleMethodName]; typeof method === 'function' || Fail`function ${q(nonLocaleMethodName)} not found`; defineProperty(intrinsic, methodName, { value: method }); } } } } // Numbers are special because toString accepts a radix instead of ignoring // all of the arguments that we would otherwise forward. defineProperty(Number.prototype, 'toLocaleString', { value: numberToString, }); }