diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index 43adedea1f2b..4f0c3b75c0ea 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -5,3 +5,4 @@ self-hosted-runner: - macos-13-large - macos-13-xlarge - ubuntu-latest-reassure-tests + - macos-12 diff --git a/.github/actions/composite/setupNode/action.yml b/.github/actions/composite/setupNode/action.yml index 8eb4f6474638..086a2a383d28 100644 --- a/.github/actions/composite/setupNode/action.yml +++ b/.github/actions/composite/setupNode/action.yml @@ -1,6 +1,12 @@ name: Set up Node description: Set up Node +inputs: + IS_HYBRID_BUILD: + description: "Indicates if node is set up for hybrid app" + required: false + default: 'false' + outputs: cache-hit: description: Was there a cache hit on the main node_modules? @@ -27,14 +33,26 @@ runs: path: node_modules key: ${{ runner.os }}-node-modules-${{ hashFiles('package-lock.json', 'patches/**') }} + - id: cache-old-dot-node-modules + if: inputs.IS_HYBRID_BUILD == 'true' + uses: actions/cache@v4 + with: + path: Mobile-Expensify/node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('Mobile-Expensify/package-lock.json', 'Mobile-Expensify/patches/**') }} + - id: cache-desktop-node-modules uses: actions/cache@v4 with: path: desktop/node_modules key: ${{ runner.os }}-desktop-node-modules-${{ hashFiles('desktop/package-lock.json', 'desktop/patches/**') }} + - name: Remove ND node_modules if needed for hybrid app build + if: inputs.IS_HYBRID_BUILD == 'true' && steps.cache-node-modules.outputs.cache-hit == 'true' && steps.cache-old-dot-node-modules.outputs.cache-hit != 'true' + shell: bash + run: rm -rf node_modules + - name: Install root project node packages - if: steps.cache-node-modules.outputs.cache-hit != 'true' + if: steps.cache-node-modules.outputs.cache-hit != 'true' || (inputs.IS_HYBRID_BUILD == 'true' && steps.cache-old-dot-node-modules.outputs.cache-hit != 'true') uses: nick-fields/retry@3f757583fb1b1f940bc8ef4bf4734c8dc02a5847 with: timeout_minutes: 30 diff --git a/.github/actions/javascript/authorChecklist/index.js b/.github/actions/javascript/authorChecklist/index.js index 52fa68c65096..40d9ec3f13d0 100644 --- a/.github/actions/javascript/authorChecklist/index.js +++ b/.github/actions/javascript/authorChecklist/index.js @@ -3482,6 +3482,332 @@ exports.checkBypass = checkBypass; //# sourceMappingURL=gen-mapping.umd.js.map +/***/ }), + +/***/ 9105: +/***/ ((module) => { + +"use strict"; + + +const object = {}; +const hasOwnProperty = object.hasOwnProperty; +const forOwn = (object, callback) => { + for (const key in object) { + if (hasOwnProperty.call(object, key)) { + callback(key, object[key]); + } + } +}; + +const extend = (destination, source) => { + if (!source) { + return destination; + } + forOwn(source, (key, value) => { + destination[key] = value; + }); + return destination; +}; + +const forEach = (array, callback) => { + const length = array.length; + let index = -1; + while (++index < length) { + callback(array[index]); + } +}; + +const fourHexEscape = (hex) => { + return '\\u' + ('0000' + hex).slice(-4); +} + +const hexadecimal = (code, lowercase) => { + let hexadecimal = code.toString(16); + if (lowercase) return hexadecimal; + return hexadecimal.toUpperCase(); +}; + +const toString = object.toString; +const isArray = Array.isArray; +const isBuffer = (value) => { + return typeof Buffer === 'function' && Buffer.isBuffer(value); +}; +const isObject = (value) => { + // This is a very simple check, but it’s good enough for what we need. + return toString.call(value) == '[object Object]'; +}; +const isString = (value) => { + return typeof value == 'string' || + toString.call(value) == '[object String]'; +}; +const isNumber = (value) => { + return typeof value == 'number' || + toString.call(value) == '[object Number]'; +}; +const isFunction = (value) => { + return typeof value == 'function'; +}; +const isMap = (value) => { + return toString.call(value) == '[object Map]'; +}; +const isSet = (value) => { + return toString.call(value) == '[object Set]'; +}; + +/*--------------------------------------------------------------------------*/ + +// https://mathiasbynens.be/notes/javascript-escapes#single +const singleEscapes = { + '\\': '\\\\', + '\b': '\\b', + '\f': '\\f', + '\n': '\\n', + '\r': '\\r', + '\t': '\\t' + // `\v` is omitted intentionally, because in IE < 9, '\v' == 'v'. + // '\v': '\\x0B' +}; +const regexSingleEscape = /[\\\b\f\n\r\t]/; + +const regexDigit = /[0-9]/; +const regexWhitespace = /[\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/; + +const escapeEverythingRegex = /([\uD800-\uDBFF][\uDC00-\uDFFF])|([\uD800-\uDFFF])|(['"`])|[^]/g; +const escapeNonAsciiRegex = /([\uD800-\uDBFF][\uDC00-\uDFFF])|([\uD800-\uDFFF])|(['"`])|[^ !#-&\(-\[\]-_a-~]/g; + +const jsesc = (argument, options) => { + const increaseIndentation = () => { + oldIndent = indent; + ++options.indentLevel; + indent = options.indent.repeat(options.indentLevel) + }; + // Handle options + const defaults = { + 'escapeEverything': false, + 'minimal': false, + 'isScriptContext': false, + 'quotes': 'single', + 'wrap': false, + 'es6': false, + 'json': false, + 'compact': true, + 'lowercaseHex': false, + 'numbers': 'decimal', + 'indent': '\t', + 'indentLevel': 0, + '__inline1__': false, + '__inline2__': false + }; + const json = options && options.json; + if (json) { + defaults.quotes = 'double'; + defaults.wrap = true; + } + options = extend(defaults, options); + if ( + options.quotes != 'single' && + options.quotes != 'double' && + options.quotes != 'backtick' + ) { + options.quotes = 'single'; + } + const quote = options.quotes == 'double' ? + '"' : + (options.quotes == 'backtick' ? + '`' : + '\'' + ); + const compact = options.compact; + const lowercaseHex = options.lowercaseHex; + let indent = options.indent.repeat(options.indentLevel); + let oldIndent = ''; + const inline1 = options.__inline1__; + const inline2 = options.__inline2__; + const newLine = compact ? '' : '\n'; + let result; + let isEmpty = true; + const useBinNumbers = options.numbers == 'binary'; + const useOctNumbers = options.numbers == 'octal'; + const useDecNumbers = options.numbers == 'decimal'; + const useHexNumbers = options.numbers == 'hexadecimal'; + + if (json && argument && isFunction(argument.toJSON)) { + argument = argument.toJSON(); + } + + if (!isString(argument)) { + if (isMap(argument)) { + if (argument.size == 0) { + return 'new Map()'; + } + if (!compact) { + options.__inline1__ = true; + options.__inline2__ = false; + } + return 'new Map(' + jsesc(Array.from(argument), options) + ')'; + } + if (isSet(argument)) { + if (argument.size == 0) { + return 'new Set()'; + } + return 'new Set(' + jsesc(Array.from(argument), options) + ')'; + } + if (isBuffer(argument)) { + if (argument.length == 0) { + return 'Buffer.from([])'; + } + return 'Buffer.from(' + jsesc(Array.from(argument), options) + ')'; + } + if (isArray(argument)) { + result = []; + options.wrap = true; + if (inline1) { + options.__inline1__ = false; + options.__inline2__ = true; + } + if (!inline2) { + increaseIndentation(); + } + forEach(argument, (value) => { + isEmpty = false; + if (inline2) { + options.__inline2__ = false; + } + result.push( + (compact || inline2 ? '' : indent) + + jsesc(value, options) + ); + }); + if (isEmpty) { + return '[]'; + } + if (inline2) { + return '[' + result.join(', ') + ']'; + } + return '[' + newLine + result.join(',' + newLine) + newLine + + (compact ? '' : oldIndent) + ']'; + } else if (isNumber(argument)) { + if (json) { + // Some number values (e.g. `Infinity`) cannot be represented in JSON. + return JSON.stringify(argument); + } + if (useDecNumbers) { + return String(argument); + } + if (useHexNumbers) { + let hexadecimal = argument.toString(16); + if (!lowercaseHex) { + hexadecimal = hexadecimal.toUpperCase(); + } + return '0x' + hexadecimal; + } + if (useBinNumbers) { + return '0b' + argument.toString(2); + } + if (useOctNumbers) { + return '0o' + argument.toString(8); + } + } else if (!isObject(argument)) { + if (json) { + // For some values (e.g. `undefined`, `function` objects), + // `JSON.stringify(value)` returns `undefined` (which isn’t valid + // JSON) instead of `'null'`. + return JSON.stringify(argument) || 'null'; + } + return String(argument); + } else { // it’s an object + result = []; + options.wrap = true; + increaseIndentation(); + forOwn(argument, (key, value) => { + isEmpty = false; + result.push( + (compact ? '' : indent) + + jsesc(key, options) + ':' + + (compact ? '' : ' ') + + jsesc(value, options) + ); + }); + if (isEmpty) { + return '{}'; + } + return '{' + newLine + result.join(',' + newLine) + newLine + + (compact ? '' : oldIndent) + '}'; + } + } + + const regex = options.escapeEverything ? escapeEverythingRegex : escapeNonAsciiRegex; + result = argument.replace(regex, (char, pair, lone, quoteChar, index, string) => { + if (pair) { + if (options.minimal) return pair; + const first = pair.charCodeAt(0); + const second = pair.charCodeAt(1); + if (options.es6) { + // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + const codePoint = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; + const hex = hexadecimal(codePoint, lowercaseHex); + return '\\u{' + hex + '}'; + } + return fourHexEscape(hexadecimal(first, lowercaseHex)) + fourHexEscape(hexadecimal(second, lowercaseHex)); + } + + if (lone) { + return fourHexEscape(hexadecimal(lone.charCodeAt(0), lowercaseHex)); + } + + if ( + char == '\0' && + !json && + !regexDigit.test(string.charAt(index + 1)) + ) { + return '\\0'; + } + + if (quoteChar) { + if (quoteChar == quote || options.escapeEverything) { + return '\\' + quoteChar; + } + return quoteChar; + } + + if (regexSingleEscape.test(char)) { + // no need for a `hasOwnProperty` check here + return singleEscapes[char]; + } + + if (options.minimal && !regexWhitespace.test(char)) { + return char; + } + + const hex = hexadecimal(char.charCodeAt(0), lowercaseHex); + if (json || hex.length > 2) { + return fourHexEscape(hex); + } + + return '\\x' + ('00' + hex).slice(-2); + }); + + if (quote == '`') { + result = result.replace(/\$\{/g, '\\${'); + } + if (options.isScriptContext) { + // https://mathiasbynens.be/notes/etago + result = result + .replace(/<\/(script|style)/gi, '<\\/$1') + .replace(/