|
1817 | 1817 | copy2[symbol] = value[symbol]; |
1818 | 1818 | }); |
1819 | 1819 | return copy2; |
1820 | | - } else if (isJSONObject(value)) { |
| 1820 | + } |
| 1821 | + if (isJSONObject(value)) { |
1821 | 1822 | const copy2 = { |
1822 | 1823 | ...value |
1823 | 1824 | }; |
1824 | 1825 | Object.getOwnPropertySymbols(value).forEach((symbol) => { |
1825 | 1826 | copy2[symbol] = value[symbol]; |
1826 | 1827 | }); |
1827 | 1828 | return copy2; |
1828 | | - } else { |
1829 | | - return value; |
1830 | 1829 | } |
| 1830 | + return value; |
1831 | 1831 | } |
1832 | 1832 | function applyProp(object, key, value) { |
1833 | 1833 | if (object[key] === value) { |
1834 | 1834 | return object; |
1835 | | - } else { |
1836 | | - const updatedObject = shallowClone(object); |
1837 | | - updatedObject[key] = value; |
1838 | | - return updatedObject; |
1839 | 1835 | } |
| 1836 | + const updatedObject = shallowClone(object); |
| 1837 | + updatedObject[key] = value; |
| 1838 | + return updatedObject; |
1840 | 1839 | } |
1841 | 1840 | function getIn(object, path) { |
1842 | 1841 | let value = object; |
|
1845 | 1844 | if (isJSONObject(value)) { |
1846 | 1845 | value = value[path[i]]; |
1847 | 1846 | } else if (isJSONArray(value)) { |
1848 | | - value = value[parseInt(path[i])]; |
| 1847 | + value = value[Number.parseInt(path[i])]; |
1849 | 1848 | } else { |
1850 | 1849 | value = void 0; |
1851 | 1850 | } |
|
1862 | 1861 | const updatedValue = setIn(object ? object[key] : void 0, path.slice(1), value, createPath); |
1863 | 1862 | if (isJSONObject(object) || isJSONArray(object)) { |
1864 | 1863 | return applyProp(object, key, updatedValue); |
1865 | | - } else { |
1866 | | - if (createPath) { |
1867 | | - const newObject = IS_INTEGER_REGEX.test(key) ? [] : {}; |
1868 | | - newObject[key] = updatedValue; |
1869 | | - return newObject; |
1870 | | - } else { |
1871 | | - throw new Error("Path does not exist"); |
1872 | | - } |
1873 | 1864 | } |
| 1865 | + if (createPath) { |
| 1866 | + const newObject = IS_INTEGER_REGEX.test(key) ? [] : {}; |
| 1867 | + newObject[key] = updatedValue; |
| 1868 | + return newObject; |
| 1869 | + } |
| 1870 | + throw new Error("Path does not exist"); |
1874 | 1871 | } |
1875 | 1872 | var IS_INTEGER_REGEX = /^\d+$/; |
1876 | 1873 | function updateIn(object, path, transform) { |
|
1895 | 1892 | const key2 = path[0]; |
1896 | 1893 | if (!(key2 in object)) { |
1897 | 1894 | return object; |
1898 | | - } else { |
1899 | | - const updatedObject = shallowClone(object); |
1900 | | - if (isJSONArray(updatedObject)) { |
1901 | | - updatedObject.splice(parseInt(key2), 1); |
1902 | | - } |
1903 | | - if (isJSONObject(updatedObject)) { |
1904 | | - delete updatedObject[key2]; |
1905 | | - } |
1906 | | - return updatedObject; |
1907 | 1895 | } |
| 1896 | + const updatedObject = shallowClone(object); |
| 1897 | + if (isJSONArray(updatedObject)) { |
| 1898 | + updatedObject.splice(Number.parseInt(key2), 1); |
| 1899 | + } |
| 1900 | + if (isJSONObject(updatedObject)) { |
| 1901 | + delete updatedObject[key2]; |
| 1902 | + } |
| 1903 | + return updatedObject; |
1908 | 1904 | } |
1909 | 1905 | const key = path[0]; |
1910 | 1906 | const updatedValue = deleteIn(object[key], path.slice(1)); |
|
1915 | 1911 | const index = path[path.length - 1]; |
1916 | 1912 | return updateIn(document2, parentPath, (items) => { |
1917 | 1913 | if (!Array.isArray(items)) { |
1918 | | - throw new TypeError("Array expected at path " + JSON.stringify(parentPath)); |
| 1914 | + throw new TypeError(`Array expected at path ${JSON.stringify(parentPath)}`); |
1919 | 1915 | } |
1920 | 1916 | const updatedItems = shallowClone(items); |
1921 | | - updatedItems.splice(parseInt(index), 0, value); |
| 1917 | + updatedItems.splice(Number.parseInt(index), 0, value); |
1922 | 1918 | return updatedItems; |
1923 | 1919 | }); |
1924 | 1920 | } |
|
1945 | 1941 | return path.map(compileJSONPointerProp).join(""); |
1946 | 1942 | } |
1947 | 1943 | function compileJSONPointerProp(pathProp) { |
1948 | | - return "/" + String(pathProp).replace(/~/g, "~0").replace(/\//g, "~1"); |
| 1944 | + return `/${String(pathProp).replace(/~/g, "~0").replace(/\//g, "~1")}`; |
1949 | 1945 | } |
1950 | 1946 |
|
1951 | 1947 | // ../node_modules/immutable-json-patch/lib/esm/immutableJSONPatch.js |
|
1954 | 1950 | for (let i = 0; i < operations.length; i++) { |
1955 | 1951 | validateJSONPatchOperation(operations[i]); |
1956 | 1952 | let operation = operations[i]; |
1957 | | - if (options && options.before) { |
| 1953 | + if (options?.before) { |
1958 | 1954 | const result = options.before(updatedDocument, operation); |
1959 | 1955 | if (result !== void 0) { |
1960 | 1956 | if (result.document !== void 0) { |
|
1983 | 1979 | } else if (operation.op === "test") { |
1984 | 1980 | test(updatedDocument, path, operation.value); |
1985 | 1981 | } else { |
1986 | | - throw new Error("Unknown JSONPatch operation " + JSON.stringify(operation)); |
| 1982 | + throw new Error(`Unknown JSONPatch operation ${JSON.stringify(operation)}`); |
1987 | 1983 | } |
1988 | | - if (options && options.after) { |
| 1984 | + if (options?.after) { |
1989 | 1985 | const result = options.after(updatedDocument, operation, previousDocument); |
1990 | 1986 | if (result !== void 0) { |
1991 | 1987 | updatedDocument = result; |
|
1995 | 1991 | return updatedDocument; |
1996 | 1992 | } |
1997 | 1993 | function replace(document2, path, value) { |
1998 | | - return setIn(document2, path, value); |
| 1994 | + return existsIn(document2, path) ? setIn(document2, path, value) : document2; |
1999 | 1995 | } |
2000 | 1996 | function remove(document2, path) { |
2001 | 1997 | return deleteIn(document2, path); |
2002 | 1998 | } |
2003 | 1999 | function add(document2, path, value) { |
2004 | 2000 | if (isArrayItem(document2, path)) { |
2005 | 2001 | return insertAt(document2, path, value); |
2006 | | - } else { |
2007 | | - return setIn(document2, path, value); |
2008 | 2002 | } |
| 2003 | + return setIn(document2, path, value); |
2009 | 2004 | } |
2010 | 2005 | function copy(document2, path, from) { |
2011 | 2006 | const value = getIn(document2, from); |
2012 | 2007 | if (isArrayItem(document2, path)) { |
2013 | 2008 | return insertAt(document2, path, value); |
2014 | | - } else { |
2015 | | - const value2 = getIn(document2, from); |
2016 | | - return setIn(document2, path, value2); |
2017 | 2009 | } |
| 2010 | + return setIn(document2, path, value); |
2018 | 2011 | } |
2019 | 2012 | function move(document2, path, from) { |
2020 | 2013 | const value = getIn(document2, from); |
|
2051 | 2044 | function validateJSONPatchOperation(operation) { |
2052 | 2045 | const ops = ["add", "remove", "replace", "copy", "move", "test"]; |
2053 | 2046 | if (!ops.includes(operation.op)) { |
2054 | | - throw new Error("Unknown JSONPatch op " + JSON.stringify(operation.op)); |
| 2047 | + throw new Error(`Unknown JSONPatch op ${JSON.stringify(operation.op)}`); |
2055 | 2048 | } |
2056 | 2049 | if (typeof operation.path !== "string") { |
2057 | | - throw new Error('Required property "path" missing or not a string in operation ' + JSON.stringify(operation)); |
| 2050 | + throw new Error(`Required property "path" missing or not a string in operation ${JSON.stringify(operation)}`); |
2058 | 2051 | } |
2059 | 2052 | if (operation.op === "copy" || operation.op === "move") { |
2060 | 2053 | if (typeof operation.from !== "string") { |
2061 | | - throw new Error('Required property "from" missing or not a string in operation ' + JSON.stringify(operation)); |
| 2054 | + throw new Error(`Required property "from" missing or not a string in operation ${JSON.stringify(operation)}`); |
2062 | 2055 | } |
2063 | 2056 | } |
2064 | 2057 | } |
|
2887 | 2880 | get featureSettings() { |
2888 | 2881 | return __privateGet(this, _args)?.featureSettings; |
2889 | 2882 | } |
| 2883 | + /** |
| 2884 | + * Getter for injectName, will be overridden by subclasses (namely ContentFeature) |
| 2885 | + * @returns {string | undefined} |
| 2886 | + */ |
| 2887 | + get injectName() { |
| 2888 | + return void 0; |
| 2889 | + } |
2890 | 2890 | /** |
2891 | 2891 | * Given a config key, interpret the value as a list of conditionals objects, and return the elements that match the current page |
2892 | 2892 | * Consider in your feature using patchSettings instead as per `getFeatureSetting`. |
|
2925 | 2925 | * @property {object} [experiment] |
2926 | 2926 | * @property {string} [experiment.experimentName] |
2927 | 2927 | * @property {string} [experiment.cohort] |
| 2928 | + * @property {object} [context] |
| 2929 | + * @property {boolean} [context.frame] - true if the condition applies to frames |
| 2930 | + * @property {boolean} [context.top] - true if the condition applies to the top frame |
| 2931 | + * @property {string} [injectName] - the inject name to match against (e.g., "apple-isolated") |
2928 | 2932 | */ |
2929 | 2933 | /** |
2930 | 2934 | * Takes multiple conditional blocks and returns true if any apply. |
|
2946 | 2950 | _matchConditionalBlock(conditionBlock) { |
2947 | 2951 | const conditionChecks = { |
2948 | 2952 | domain: this._matchDomainConditional, |
| 2953 | + context: this._matchContextConditional, |
2949 | 2954 | urlPattern: this._matchUrlPatternConditional, |
2950 | 2955 | experiment: this._matchExperimentConditional, |
2951 | | - minSupportedVersion: this._matchMinSupportedVersion |
| 2956 | + minSupportedVersion: this._matchMinSupportedVersion, |
| 2957 | + injectName: this._matchInjectNameConditional |
2952 | 2958 | }; |
2953 | 2959 | for (const key in conditionBlock) { |
2954 | 2960 | if (!conditionChecks[key]) { |
|
2984 | 2990 | return cohort.feature === "contentScopeExperiments" && cohort.subfeature === experiment.experimentName && cohort.cohort === experiment.cohort; |
2985 | 2991 | }); |
2986 | 2992 | } |
| 2993 | + /** |
| 2994 | + * Takes a condition block and returns true if the current context matches the context. |
| 2995 | + * @param {ConditionBlock} conditionBlock |
| 2996 | + * @returns {boolean} |
| 2997 | + */ |
| 2998 | + _matchContextConditional(conditionBlock) { |
| 2999 | + if (!conditionBlock.context) return false; |
| 3000 | + const isFrame = window.self !== window.top; |
| 3001 | + if (conditionBlock.context.frame && isFrame) { |
| 3002 | + return true; |
| 3003 | + } |
| 3004 | + if (conditionBlock.context.top && !isFrame) { |
| 3005 | + return true; |
| 3006 | + } |
| 3007 | + return false; |
| 3008 | + } |
2987 | 3009 | /** |
2988 | 3010 | * Takes a condtion block and returns true if the current url matches the urlPattern. |
2989 | 3011 | * @param {ConditionBlock} conditionBlock |
|
3012 | 3034 | } |
3013 | 3035 | return matchHostname(domain, conditionBlock.domain); |
3014 | 3036 | } |
| 3037 | + /** |
| 3038 | + * Takes a condition block and returns true if the current inject name matches the injectName. |
| 3039 | + * @param {ConditionBlock} conditionBlock |
| 3040 | + * @returns {boolean} |
| 3041 | + */ |
| 3042 | + _matchInjectNameConditional(conditionBlock) { |
| 3043 | + if (!conditionBlock.injectName) return false; |
| 3044 | + const currentInjectName = this.injectName; |
| 3045 | + if (!currentInjectName) return false; |
| 3046 | + return conditionBlock.injectName === currentInjectName; |
| 3047 | + } |
3015 | 3048 | /** |
3016 | 3049 | * Takes a condition block and returns true if the platform version satisfies the `minSupportedFeature` |
3017 | 3050 | * @param {ConditionBlock} conditionBlock |
|
3889 | 3922 | const historyMethodProxy = new DDGProxy(urlChangedInstance, History.prototype, "pushState", { |
3890 | 3923 | apply(target, thisArg, args) { |
3891 | 3924 | const changeResult = DDGReflect.apply(target, thisArg, args); |
3892 | | - console.log("pushstate event"); |
3893 | 3925 | handleURLChange("push"); |
3894 | 3926 | return changeResult; |
3895 | 3927 | } |
|
0 commit comments