reduxjs / reselect

Selector library for Redux
MIT License
19.03k stars 671 forks source link

Improve treeshakeability of build artifacts #721

Closed aryaemami59 closed 1 month ago

aryaemami59 commented 3 months ago

This PR:

netlify[bot] commented 3 months ago

Deploy Preview for reselect-docs canceled.

Name Link
Latest commit 9fbee6a6e2df44d9c41c5594867808b9c904adfb
Latest deploy log https://app.netlify.com/sites/reselect-docs/deploys/66b8d685a5976a0008b323e4
codesandbox-ci[bot] commented 3 months ago

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

markerikson commented 3 months ago

Anything else you want to add here? Also, what's the net bundle size changes? (suppose it might help if we merge the size-limit PR first...)

aryaemami59 commented 3 months ago

Yeah let's do the size limit one first. Do you want me to get rid of the browser artifact?

markerikson commented 3 months ago

I think I'm missing some context here. I see that you added and removed a "browser" field entry, and the removal commit mentions some Webpack 4 incompat, but I don't know more beyond that. Can you clarify what you've found?

aryaemami59 commented 3 months ago

The CI example app for cra4 failed when I added it.

Edit: The cra4 example app failed for React-Redux when I added it, it failed because it has a .mjs extension and webapck4 doesn't like named imports of CJS libraries in a .mjs file, and use-sync-external-store is a CJS library. So I removed the browser field on React-Redux, and I removed it from Reselect's package.json as well because I was kinda scared it would create unexpected issues. Also Publint complains if you add a top level browser field so that was another reason.

aryaemami59 commented 2 months ago

Other changes to consider adding:

  1. We could add a top level unpkg field to package.json and set it to "./dist/reselect.browser.mjs" as currently the default build artifact consumed by unpkg is the same as main which is "./dist/cjs/index.js".

  2. We could have separate development and production entry points for cjs as opposed to conditionally re-exporting cjs artifacts in "./dist/cjs/index.js". So the exports field in our package.json could look something like this (we could probably get rid of the last "default" field altogether):

    "exports": {
    "./package.json": "./package.json",
    ".": {
      "types": "./dist/reselect.d.ts",
      "import": "./dist/reselect.mjs",
      "default": {
        "development": "./dist/cjs/reselect.development.cjs",
        "production": "./dist/cjs/reselect.production.min.cjs",
        "default": "./dist/cjs/index.js"
      }
    }
    },
  3. We could add a "bun" entry pointing to our "./src/index.ts" file:

    "exports": {
    "./package.json": "./package.json",
    ".": {
      "types": "./dist/reselect.d.mts",
      "bun": "./src/index.ts",
      "import": "./dist/reselect.mjs",
      "default": "./dist/cjs/index.js"
    }
    },
  4. We could have dual type definitions:

    "exports": {
    "./package.json": "./package.json",
    ".": {
      "import": {
        "types": "./dist/reselect.d.mts",
        "default": "./dist/reselect.mjs"
      },
      "default": {
        "types": "./dist/cjs/reselect.d.ts",
        "default": "./dist/cjs/index.js"
      }
    }
    },

Or maybe even:

  "exports": {
    "./package.json": "./package.json",
    ".": {
      "types": {
        "import": "./dist/reselect.d.mts",
        "default": "./dist/reselect.d.ts"
      },
      "import": "./dist/reselect.mjs",
      "default": "./dist/cjs/index.js"
    }
  },
markerikson commented 2 months ago

Can you summarize for me:

aryaemami59 commented 2 months ago

Summary

With Rollup

createSelector changes (Click to expand) **File Content**: ```ts export { createSelector } from 'reselect' ```
Before and After ```diff --- before/reselect/createSelector.js 2024-06-25 02:52:06.683601300 -0500 +++ after/reselect/createSelector.js 2024-06-25 08:06:25.509655000 -0500 @@ -4,11 +4,6 @@ throw new TypeError(errorMessage); } } -function assertIsObject(object, errorMessage = `expected an object, instead received ${typeof object}`) { - if (typeof object !== "object") { - throw new TypeError(errorMessage); - } -} function assertIsArrayOfFunctions(array, errorMessage = `expected all items to be functions, instead received the following types: `) { if (!array.every((item) => typeof item === "function")) { const itemTypes = array.map( @@ -46,7 +41,8 @@ return this.value; } }; -var Ref = typeof WeakRef !== "undefined" ? WeakRef : StrongRef; +var getWeakRef = () => typeof WeakRef === "undefined" ? StrongRef : WeakRef; +var Ref = /* @__PURE__ */ getWeakRef(); var UNTERMINATED = 0; var TERMINATED = 1; function createCacheNode() { @@ -107,7 +103,7 @@ resultsCount !== 0 && resultsCount--; } const needsWeakRef = typeof result === "object" && result !== null || typeof result === "function"; - lastResult = needsWeakRef ? new Ref(result) : result; + lastResult = needsWeakRef ? /* @__PURE__ */ new Ref(result) : result; } } terminatedNode.s = TERMINATED; @@ -153,8 +149,7 @@ memoize, memoizeOptions = [], argsMemoize = weakMapMemoize, - argsMemoizeOptions = [], - devModeChecks = {} + argsMemoizeOptions = [] } = combinedOptions; const finalMemoizeOptions = ensureIsArray(memoizeOptions); const finalArgsMemoizeOptions = ensureIsArray(argsMemoizeOptions); @@ -199,29 +194,4 @@ } var createSelector = /* @__PURE__ */ createSelectorCreator(weakMapMemoize); -// src/createStructuredSelector.ts -var createStructuredSelector = Object.assign( - (inputSelectorsObject, selectorCreator = createSelector) => { - assertIsObject( - inputSelectorsObject, - `createStructuredSelector expects first argument to be an object where each property is a selector, instead received a ${typeof inputSelectorsObject}` - ); - const inputSelectorKeys = Object.keys(inputSelectorsObject); - const dependencies = inputSelectorKeys.map( - (key) => inputSelectorsObject[key] - ); - const structuredSelector = selectorCreator( - dependencies, - (...inputSelectorResults) => { - return inputSelectorResults.reduce((composition, value, index) => { - composition[inputSelectorKeys[index]] = value; - return composition; - }, {}); - } - ); - return structuredSelector; - }, - { withTypes: () => createStructuredSelector } -); - export { createSelector }; ```
createSelectorCreator changes (Click to expand) **File Content**: ```ts export { createSelectorCreator } from 'reselect' ```
Before and After ```diff --- before/reselect/createSelectorCreator.js 2024-06-25 02:52:07.081602100 -0500 +++ after/reselect/createSelectorCreator.js 2024-06-25 08:06:25.511656400 -0500 @@ -4,11 +4,6 @@ throw new TypeError(errorMessage); } } -function assertIsObject(object, errorMessage = `expected an object, instead received ${typeof object}`) { - if (typeof object !== "object") { - throw new TypeError(errorMessage); - } -} function assertIsArrayOfFunctions(array, errorMessage = `expected all items to be functions, instead received the following types: `) { if (!array.every((item) => typeof item === "function")) { const itemTypes = array.map( @@ -46,7 +41,8 @@ return this.value; } }; -var Ref = typeof WeakRef !== "undefined" ? WeakRef : StrongRef; +var getWeakRef = () => typeof WeakRef === "undefined" ? StrongRef : WeakRef; +var Ref = /* @__PURE__ */ getWeakRef(); var UNTERMINATED = 0; var TERMINATED = 1; function createCacheNode() { @@ -107,7 +103,7 @@ resultsCount !== 0 && resultsCount--; } const needsWeakRef = typeof result === "object" && result !== null || typeof result === "function"; - lastResult = needsWeakRef ? new Ref(result) : result; + lastResult = needsWeakRef ? /* @__PURE__ */ new Ref(result) : result; } } terminatedNode.s = TERMINATED; @@ -153,8 +149,7 @@ memoize, memoizeOptions = [], argsMemoize = weakMapMemoize, - argsMemoizeOptions = [], - devModeChecks = {} + argsMemoizeOptions = [] } = combinedOptions; const finalMemoizeOptions = ensureIsArray(memoizeOptions); const finalArgsMemoizeOptions = ensureIsArray(argsMemoizeOptions); @@ -197,31 +192,5 @@ }); return createSelector2; } -var createSelector = /* @__PURE__ */ createSelectorCreator(weakMapMemoize); - -// src/createStructuredSelector.ts -var createStructuredSelector = Object.assign( - (inputSelectorsObject, selectorCreator = createSelector) => { - assertIsObject( - inputSelectorsObject, - `createStructuredSelector expects first argument to be an object where each property is a selector, instead received a ${typeof inputSelectorsObject}` - ); - const inputSelectorKeys = Object.keys(inputSelectorsObject); - const dependencies = inputSelectorKeys.map( - (key) => inputSelectorsObject[key] - ); - const structuredSelector = selectorCreator( - dependencies, - (...inputSelectorResults) => { - return inputSelectorResults.reduce((composition, value, index) => { - composition[inputSelectorKeys[index]] = value; - return composition; - }, {}); - } - ); - return structuredSelector; - }, - { withTypes: () => createStructuredSelector } -); export { createSelectorCreator }; ```
createStructuredSelector changes (Click to expand) **File Content**: ```ts export { createStructuredSelector } from 'reselect' ```
Before and After ```diff --- before/reselect/createStructuredSelector.js 2024-06-25 02:52:07.071602700 -0500 +++ after/reselect/createStructuredSelector.js 2024-06-25 08:06:25.280654700 -0500 @@ -46,7 +46,8 @@ return this.value; } }; -var Ref = typeof WeakRef !== "undefined" ? WeakRef : StrongRef; +var getWeakRef = () => typeof WeakRef === "undefined" ? StrongRef : WeakRef; +var Ref = /* @__PURE__ */ getWeakRef(); var UNTERMINATED = 0; var TERMINATED = 1; function createCacheNode() { @@ -107,7 +108,7 @@ resultsCount !== 0 && resultsCount--; } const needsWeakRef = typeof result === "object" && result !== null || typeof result === "function"; - lastResult = needsWeakRef ? new Ref(result) : result; + lastResult = needsWeakRef ? /* @__PURE__ */ new Ref(result) : result; } } terminatedNode.s = TERMINATED; @@ -153,8 +154,7 @@ memoize, memoizeOptions = [], argsMemoize = weakMapMemoize, - argsMemoizeOptions = [], - devModeChecks = {} + argsMemoizeOptions = [] } = combinedOptions; const finalMemoizeOptions = ensureIsArray(memoizeOptions); const finalArgsMemoizeOptions = ensureIsArray(argsMemoizeOptions); @@ -200,7 +200,7 @@ var createSelector = /* @__PURE__ */ createSelectorCreator(weakMapMemoize); // src/createStructuredSelector.ts -var createStructuredSelector = Object.assign( +var createStructuredSelector = /* @__PURE__ */ Object.assign( (inputSelectorsObject, selectorCreator = createSelector) => { assertIsObject( inputSelectorsObject, ```
lruMemoize changes (Click to expand) **File Content**: ```ts export { lruMemoize } from 'reselect' ```
Before and After ```diff --- before/reselect/lruMemoize.js 2024-06-25 02:52:06.954602200 -0500 +++ after/reselect/lruMemoize.js 2024-06-25 08:06:25.301656100 -0500 @@ -2,43 +2,6 @@ // src/utils.ts var NOT_FOUND = /* @__PURE__ */ Symbol("NOT_FOUND"); -function assertIsFunction(func, errorMessage = `expected a function, instead received ${typeof func}`) { - if (typeof func !== "function") { - throw new TypeError(errorMessage); - } -} -function assertIsObject(object, errorMessage = `expected an object, instead received ${typeof object}`) { - if (typeof object !== "object") { - throw new TypeError(errorMessage); - } -} -function assertIsArrayOfFunctions(array, errorMessage = `expected all items to be functions, instead received the following types: `) { - if (!array.every((item) => typeof item === "function")) { - const itemTypes = array.map( - (item) => typeof item === "function" ? `function ${item.name || "unnamed"}()` : typeof item - ).join(", "); - throw new TypeError(`${errorMessage}[${itemTypes}]`); - } -} -var ensureIsArray = (item) => { - return Array.isArray(item) ? item : [item]; -}; -function getDependencies(createSelectorArgs) { - const dependencies = Array.isArray(createSelectorArgs[0]) ? createSelectorArgs[0] : createSelectorArgs; - assertIsArrayOfFunctions( - dependencies, - `createSelector expects all input-selectors to be functions, but received the following types: ` - ); - return dependencies; -} -function collectInputSelectorResults(dependencies, inputSelectorArgs) { - const inputSelectorResults = []; - const { length } = dependencies; - for (let i = 0; i < length; i++) { - inputSelectorResults.push(dependencies[i].apply(null, inputSelectorArgs)); - } - return inputSelectorResults; -} // src/lruMemoize.ts function createSingletonCache(equals) { @@ -146,191 +109,4 @@ return memoized; } -// src/weakMapMemoize.ts -var StrongRef = class { - constructor(value) { - this.value = value; - } - deref() { - return this.value; - } -}; -var Ref = typeof WeakRef !== "undefined" ? WeakRef : StrongRef; -var UNTERMINATED = 0; -var TERMINATED = 1; -function createCacheNode() { - return { - s: UNTERMINATED, - v: void 0, - o: null, - p: null - }; -} -function weakMapMemoize(func, options = {}) { - let fnNode = createCacheNode(); - const { resultEqualityCheck } = options; - let lastResult; - let resultsCount = 0; - function memoized() { - let cacheNode = fnNode; - const { length } = arguments; - for (let i = 0, l = length; i < l; i++) { - const arg = arguments[i]; - if (typeof arg === "function" || typeof arg === "object" && arg !== null) { - let objectCache = cacheNode.o; - if (objectCache === null) { - cacheNode.o = objectCache = /* @__PURE__ */ new WeakMap(); - } - const objectNode = objectCache.get(arg); - if (objectNode === void 0) { - cacheNode = createCacheNode(); - objectCache.set(arg, cacheNode); - } else { - cacheNode = objectNode; - } - } else { - let primitiveCache = cacheNode.p; - if (primitiveCache === null) { - cacheNode.p = primitiveCache = /* @__PURE__ */ new Map(); - } - const primitiveNode = primitiveCache.get(arg); - if (primitiveNode === void 0) { - cacheNode = createCacheNode(); - primitiveCache.set(arg, cacheNode); - } else { - cacheNode = primitiveNode; - } - } - } - const terminatedNode = cacheNode; - let result; - if (cacheNode.s === TERMINATED) { - result = cacheNode.v; - } else { - result = func.apply(null, arguments); - resultsCount++; - if (resultEqualityCheck) { - const lastResultValue = lastResult?.deref?.() ?? lastResult; - if (lastResultValue != null && resultEqualityCheck(lastResultValue, result)) { - result = lastResultValue; - resultsCount !== 0 && resultsCount--; - } - const needsWeakRef = typeof result === "object" && result !== null || typeof result === "function"; - lastResult = needsWeakRef ? new Ref(result) : result; - } - } - terminatedNode.s = TERMINATED; - terminatedNode.v = result; - return result; - } - memoized.clearCache = () => { - fnNode = createCacheNode(); - memoized.resetResultsCount(); - }; - memoized.resultsCount = () => resultsCount; - memoized.resetResultsCount = () => { - resultsCount = 0; - }; - return memoized; -} - -// src/createSelectorCreator.ts -function createSelectorCreator(memoizeOrOptions, ...memoizeOptionsFromArgs) { - const createSelectorCreatorOptions = typeof memoizeOrOptions === "function" ? { - memoize: memoizeOrOptions, - memoizeOptions: memoizeOptionsFromArgs - } : memoizeOrOptions; - const createSelector2 = (...createSelectorArgs) => { - let recomputations = 0; - let dependencyRecomputations = 0; - let lastResult; - let directlyPassedOptions = {}; - let resultFunc = createSelectorArgs.pop(); - if (typeof resultFunc === "object") { - directlyPassedOptions = resultFunc; - resultFunc = createSelectorArgs.pop(); - } - assertIsFunction( - resultFunc, - `createSelector expects an output function after the inputs, but received: [${typeof resultFunc}]` - ); - const combinedOptions = { - ...createSelectorCreatorOptions, - ...directlyPassedOptions - }; - const { - memoize, - memoizeOptions = [], - argsMemoize = weakMapMemoize, - argsMemoizeOptions = [], - devModeChecks = {} - } = combinedOptions; - const finalMemoizeOptions = ensureIsArray(memoizeOptions); - const finalArgsMemoizeOptions = ensureIsArray(argsMemoizeOptions); - const dependencies = getDependencies(createSelectorArgs); - const memoizedResultFunc = memoize(function recomputationWrapper() { - recomputations++; - return resultFunc.apply( - null, - arguments - ); - }, ...finalMemoizeOptions); - const selector = argsMemoize(function dependenciesChecker() { - dependencyRecomputations++; - const inputSelectorResults = collectInputSelectorResults( - dependencies, - arguments - ); - lastResult = memoizedResultFunc.apply(null, inputSelectorResults); - return lastResult; - }, ...finalArgsMemoizeOptions); - return Object.assign(selector, { - resultFunc, - memoizedResultFunc, - dependencies, - dependencyRecomputations: () => dependencyRecomputations, - resetDependencyRecomputations: () => { - dependencyRecomputations = 0; - }, - lastResult: () => lastResult, - recomputations: () => recomputations, - resetRecomputations: () => { - recomputations = 0; - }, - memoize, - argsMemoize - }); - }; - Object.assign(createSelector2, { - withTypes: () => createSelector2 - }); - return createSelector2; -} -var createSelector = /* @__PURE__ */ createSelectorCreator(weakMapMemoize); - -// src/createStructuredSelector.ts -var createStructuredSelector = Object.assign( - (inputSelectorsObject, selectorCreator = createSelector) => { - assertIsObject( - inputSelectorsObject, - `createStructuredSelector expects first argument to be an object where each property is a selector, instead received a ${typeof inputSelectorsObject}` - ); - const inputSelectorKeys = Object.keys(inputSelectorsObject); - const dependencies = inputSelectorKeys.map( - (key) => inputSelectorsObject[key] - ); - const structuredSelector = selectorCreator( - dependencies, - (...inputSelectorResults) => { - return inputSelectorResults.reduce((composition, value, index) => { - composition[inputSelectorKeys[index]] = value; - return composition; - }, {}); - } - ); - return structuredSelector; - }, - { withTypes: () => createStructuredSelector } -); - export { lruMemoize }; ```
referenceEqualityCheck changes (Click to expand) **File Content**: ```ts export { referenceEqualityCheck } from 'reselect' ```
Before and After ```diff --- before/reselect/referenceEqualityCheck.js 2024-06-25 02:52:06.880601900 -0500 +++ after/reselect/referenceEqualityCheck.js 2024-06-25 08:06:25.338656200 -0500 @@ -1,228 +1,4 @@ // src/devModeChecks/identityFunctionCheck.ts -function assertIsFunction(func, errorMessage = `expected a function, instead received ${typeof func}`) { - if (typeof func !== "function") { - throw new TypeError(errorMessage); - } -} -function assertIsObject(object, errorMessage = `expected an object, instead received ${typeof object}`) { - if (typeof object !== "object") { - throw new TypeError(errorMessage); - } -} -function assertIsArrayOfFunctions(array, errorMessage = `expected all items to be functions, instead received the following types: `) { - if (!array.every((item) => typeof item === "function")) { - const itemTypes = array.map( - (item) => typeof item === "function" ? `function ${item.name || "unnamed"}()` : typeof item - ).join(", "); - throw new TypeError(`${errorMessage}[${itemTypes}]`); - } -} -var ensureIsArray = (item) => { - return Array.isArray(item) ? item : [item]; -}; -function getDependencies(createSelectorArgs) { - const dependencies = Array.isArray(createSelectorArgs[0]) ? createSelectorArgs[0] : createSelectorArgs; - assertIsArrayOfFunctions( - dependencies, - `createSelector expects all input-selectors to be functions, but received the following types: ` - ); - return dependencies; -} -function collectInputSelectorResults(dependencies, inputSelectorArgs) { - const inputSelectorResults = []; - const { length } = dependencies; - for (let i = 0; i < length; i++) { - inputSelectorResults.push(dependencies[i].apply(null, inputSelectorArgs)); - } - return inputSelectorResults; -} var referenceEqualityCheck = (a, b) => a === b; -// src/weakMapMemoize.ts -var StrongRef = class { - constructor(value) { - this.value = value; - } - deref() { - return this.value; - } -}; -var Ref = typeof WeakRef !== "undefined" ? WeakRef : StrongRef; -var UNTERMINATED = 0; -var TERMINATED = 1; -function createCacheNode() { - return { - s: UNTERMINATED, - v: void 0, - o: null, - p: null - }; -} -function weakMapMemoize(func, options = {}) { - let fnNode = createCacheNode(); - const { resultEqualityCheck } = options; - let lastResult; - let resultsCount = 0; - function memoized() { - let cacheNode = fnNode; - const { length } = arguments; - for (let i = 0, l = length; i < l; i++) { - const arg = arguments[i]; - if (typeof arg === "function" || typeof arg === "object" && arg !== null) { - let objectCache = cacheNode.o; - if (objectCache === null) { - cacheNode.o = objectCache = /* @__PURE__ */ new WeakMap(); - } - const objectNode = objectCache.get(arg); - if (objectNode === void 0) { - cacheNode = createCacheNode(); - objectCache.set(arg, cacheNode); - } else { - cacheNode = objectNode; - } - } else { - let primitiveCache = cacheNode.p; - if (primitiveCache === null) { - cacheNode.p = primitiveCache = /* @__PURE__ */ new Map(); - } - const primitiveNode = primitiveCache.get(arg); - if (primitiveNode === void 0) { - cacheNode = createCacheNode(); - primitiveCache.set(arg, cacheNode); - } else { - cacheNode = primitiveNode; - } - } - } - const terminatedNode = cacheNode; - let result; - if (cacheNode.s === TERMINATED) { - result = cacheNode.v; - } else { - result = func.apply(null, arguments); - resultsCount++; - if (resultEqualityCheck) { - const lastResultValue = lastResult?.deref?.() ?? lastResult; - if (lastResultValue != null && resultEqualityCheck(lastResultValue, result)) { - result = lastResultValue; - resultsCount !== 0 && resultsCount--; - } - const needsWeakRef = typeof result === "object" && result !== null || typeof result === "function"; - lastResult = needsWeakRef ? new Ref(result) : result; - } - } - terminatedNode.s = TERMINATED; - terminatedNode.v = result; - return result; - } - memoized.clearCache = () => { - fnNode = createCacheNode(); - memoized.resetResultsCount(); - }; - memoized.resultsCount = () => resultsCount; - memoized.resetResultsCount = () => { - resultsCount = 0; - }; - return memoized; -} - -// src/createSelectorCreator.ts -function createSelectorCreator(memoizeOrOptions, ...memoizeOptionsFromArgs) { - const createSelectorCreatorOptions = typeof memoizeOrOptions === "function" ? { - memoize: memoizeOrOptions, - memoizeOptions: memoizeOptionsFromArgs - } : memoizeOrOptions; - const createSelector2 = (...createSelectorArgs) => { - let recomputations = 0; - let dependencyRecomputations = 0; - let lastResult; - let directlyPassedOptions = {}; - let resultFunc = createSelectorArgs.pop(); - if (typeof resultFunc === "object") { - directlyPassedOptions = resultFunc; - resultFunc = createSelectorArgs.pop(); - } - assertIsFunction( - resultFunc, - `createSelector expects an output function after the inputs, but received: [${typeof resultFunc}]` - ); - const combinedOptions = { - ...createSelectorCreatorOptions, - ...directlyPassedOptions - }; - const { - memoize, - memoizeOptions = [], - argsMemoize = weakMapMemoize, - argsMemoizeOptions = [], - devModeChecks = {} - } = combinedOptions; - const finalMemoizeOptions = ensureIsArray(memoizeOptions); - const finalArgsMemoizeOptions = ensureIsArray(argsMemoizeOptions); - const dependencies = getDependencies(createSelectorArgs); - const memoizedResultFunc = memoize(function recomputationWrapper() { - recomputations++; - return resultFunc.apply( - null, - arguments - ); - }, ...finalMemoizeOptions); - const selector = argsMemoize(function dependenciesChecker() { - dependencyRecomputations++; - const inputSelectorResults = collectInputSelectorResults( - dependencies, - arguments - ); - lastResult = memoizedResultFunc.apply(null, inputSelectorResults); - return lastResult; - }, ...finalArgsMemoizeOptions); - return Object.assign(selector, { - resultFunc, - memoizedResultFunc, - dependencies, - dependencyRecomputations: () => dependencyRecomputations, - resetDependencyRecomputations: () => { - dependencyRecomputations = 0; - }, - lastResult: () => lastResult, - recomputations: () => recomputations, - resetRecomputations: () => { - recomputations = 0; - }, - memoize, - argsMemoize - }); - }; - Object.assign(createSelector2, { - withTypes: () => createSelector2 - }); - return createSelector2; -} -var createSelector = /* @__PURE__ */ createSelectorCreator(weakMapMemoize); - -// src/createStructuredSelector.ts -var createStructuredSelector = Object.assign( - (inputSelectorsObject, selectorCreator = createSelector) => { - assertIsObject( - inputSelectorsObject, - `createStructuredSelector expects first argument to be an object where each property is a selector, instead received a ${typeof inputSelectorsObject}` - ); - const inputSelectorKeys = Object.keys(inputSelectorsObject); - const dependencies = inputSelectorKeys.map( - (key) => inputSelectorsObject[key] - ); - const structuredSelector = selectorCreator( - dependencies, - (...inputSelectorResults) => { - return inputSelectorResults.reduce((composition, value, index) => { - composition[inputSelectorKeys[index]] = value; - return composition; - }, {}); - } - ); - return structuredSelector; - }, - { withTypes: () => createStructuredSelector } -); - export { referenceEqualityCheck }; ```
setGlobalDevModeChecks changes (Click to expand) **File Content**: ```ts export { setGlobalDevModeChecks } from 'reselect' ```
Before and After ```diff --- before/reselect/setGlobalDevModeChecks.js 2024-06-25 02:52:06.783602100 -0500 +++ after/reselect/setGlobalDevModeChecks.js 2024-06-25 08:06:25.492654000 -0500 @@ -8,229 +8,5 @@ var setGlobalDevModeChecks = (devModeChecks) => { Object.assign(globalDevModeChecks, devModeChecks); }; -function assertIsFunction(func, errorMessage = `expected a function, instead received ${typeof func}`) { - if (typeof func !== "function") { - throw new TypeError(errorMessage); - } -} -function assertIsObject(object, errorMessage = `expected an object, instead received ${typeof object}`) { - if (typeof object !== "object") { - throw new TypeError(errorMessage); - } -} -function assertIsArrayOfFunctions(array, errorMessage = `expected all items to be functions, instead received the following types: `) { - if (!array.every((item) => typeof item === "function")) { - const itemTypes = array.map( - (item) => typeof item === "function" ? `function ${item.name || "unnamed"}()` : typeof item - ).join(", "); - throw new TypeError(`${errorMessage}[${itemTypes}]`); - } -} -var ensureIsArray = (item) => { - return Array.isArray(item) ? item : [item]; -}; -function getDependencies(createSelectorArgs) { - const dependencies = Array.isArray(createSelectorArgs[0]) ? createSelectorArgs[0] : createSelectorArgs; - assertIsArrayOfFunctions( - dependencies, - `createSelector expects all input-selectors to be functions, but received the following types: ` - ); - return dependencies; -} -function collectInputSelectorResults(dependencies, inputSelectorArgs) { - const inputSelectorResults = []; - const { length } = dependencies; - for (let i = 0; i < length; i++) { - inputSelectorResults.push(dependencies[i].apply(null, inputSelectorArgs)); - } - return inputSelectorResults; -} - -// src/weakMapMemoize.ts -var StrongRef = class { - constructor(value) { - this.value = value; - } - deref() { - return this.value; - } -}; -var Ref = typeof WeakRef !== "undefined" ? WeakRef : StrongRef; -var UNTERMINATED = 0; -var TERMINATED = 1; -function createCacheNode() { - return { - s: UNTERMINATED, - v: void 0, - o: null, - p: null - }; -} -function weakMapMemoize(func, options = {}) { - let fnNode = createCacheNode(); - const { resultEqualityCheck } = options; - let lastResult; - let resultsCount = 0; - function memoized() { - let cacheNode = fnNode; - const { length } = arguments; - for (let i = 0, l = length; i < l; i++) { - const arg = arguments[i]; - if (typeof arg === "function" || typeof arg === "object" && arg !== null) { - let objectCache = cacheNode.o; - if (objectCache === null) { - cacheNode.o = objectCache = /* @__PURE__ */ new WeakMap(); - } - const objectNode = objectCache.get(arg); - if (objectNode === void 0) { - cacheNode = createCacheNode(); - objectCache.set(arg, cacheNode); - } else { - cacheNode = objectNode; - } - } else { - let primitiveCache = cacheNode.p; - if (primitiveCache === null) { - cacheNode.p = primitiveCache = /* @__PURE__ */ new Map(); - } - const primitiveNode = primitiveCache.get(arg); - if (primitiveNode === void 0) { - cacheNode = createCacheNode(); - primitiveCache.set(arg, cacheNode); - } else { - cacheNode = primitiveNode; - } - } - } - const terminatedNode = cacheNode; - let result; - if (cacheNode.s === TERMINATED) { - result = cacheNode.v; - } else { - result = func.apply(null, arguments); - resultsCount++; - if (resultEqualityCheck) { - const lastResultValue = lastResult?.deref?.() ?? lastResult; - if (lastResultValue != null && resultEqualityCheck(lastResultValue, result)) { - result = lastResultValue; - resultsCount !== 0 && resultsCount--; - } - const needsWeakRef = typeof result === "object" && result !== null || typeof result === "function"; - lastResult = needsWeakRef ? new Ref(result) : result; - } - } - terminatedNode.s = TERMINATED; - terminatedNode.v = result; - return result; - } - memoized.clearCache = () => { - fnNode = createCacheNode(); - memoized.resetResultsCount(); - }; - memoized.resultsCount = () => resultsCount; - memoized.resetResultsCount = () => { - resultsCount = 0; - }; - return memoized; -} - -// src/createSelectorCreator.ts -function createSelectorCreator(memoizeOrOptions, ...memoizeOptionsFromArgs) { - const createSelectorCreatorOptions = typeof memoizeOrOptions === "function" ? { - memoize: memoizeOrOptions, - memoizeOptions: memoizeOptionsFromArgs - } : memoizeOrOptions; - const createSelector2 = (...createSelectorArgs) => { - let recomputations = 0; - let dependencyRecomputations = 0; - let lastResult; - let directlyPassedOptions = {}; - let resultFunc = createSelectorArgs.pop(); - if (typeof resultFunc === "object") { - directlyPassedOptions = resultFunc; - resultFunc = createSelectorArgs.pop(); - } - assertIsFunction( - resultFunc, - `createSelector expects an output function after the inputs, but received: [${typeof resultFunc}]` - ); - const combinedOptions = { - ...createSelectorCreatorOptions, - ...directlyPassedOptions - }; - const { - memoize, - memoizeOptions = [], - argsMemoize = weakMapMemoize, - argsMemoizeOptions = [], - devModeChecks = {} - } = combinedOptions; - const finalMemoizeOptions = ensureIsArray(memoizeOptions); - const finalArgsMemoizeOptions = ensureIsArray(argsMemoizeOptions); - const dependencies = getDependencies(createSelectorArgs); - const memoizedResultFunc = memoize(function recomputationWrapper() { - recomputations++; - return resultFunc.apply( - null, - arguments - ); - }, ...finalMemoizeOptions); - const selector = argsMemoize(function dependenciesChecker() { - dependencyRecomputations++; - const inputSelectorResults = collectInputSelectorResults( - dependencies, - arguments - ); - lastResult = memoizedResultFunc.apply(null, inputSelectorResults); - return lastResult; - }, ...finalArgsMemoizeOptions); - return Object.assign(selector, { - resultFunc, - memoizedResultFunc, - dependencies, - dependencyRecomputations: () => dependencyRecomputations, - resetDependencyRecomputations: () => { - dependencyRecomputations = 0; - }, - lastResult: () => lastResult, - recomputations: () => recomputations, - resetRecomputations: () => { - recomputations = 0; - }, - memoize, - argsMemoize - }); - }; - Object.assign(createSelector2, { - withTypes: () => createSelector2 - }); - return createSelector2; -} -var createSelector = /* @__PURE__ */ createSelectorCreator(weakMapMemoize); - -// src/createStructuredSelector.ts -var createStructuredSelector = Object.assign( - (inputSelectorsObject, selectorCreator = createSelector) => { - assertIsObject( - inputSelectorsObject, - `createStructuredSelector expects first argument to be an object where each property is a selector, instead received a ${typeof inputSelectorsObject}` - ); - const inputSelectorKeys = Object.keys(inputSelectorsObject); - const dependencies = inputSelectorKeys.map( - (key) => inputSelectorsObject[key] - ); - const structuredSelector = selectorCreator( - dependencies, - (...inputSelectorResults) => { - return inputSelectorResults.reduce((composition, value, index) => { - composition[inputSelectorKeys[index]] = value; - return composition; - }, {}); - } - ); - return structuredSelector; - }, - { withTypes: () => createStructuredSelector } -); export { setGlobalDevModeChecks }; ```
unstable_autotrackMemoize changes (Click to expand) **File Content**: ```ts export { unstable_autotrackMemoize } from 'reselect' ```
Before and After ```diff --- before/reselect/unstable_autotrackMemoize.js 2024-06-25 02:52:06.928601500 -0500 +++ after/reselect/unstable_autotrackMemoize.js 2024-06-25 08:06:25.328656400 -0500 @@ -4,38 +4,6 @@ throw new TypeError(errorMessage); } } -function assertIsObject(object, errorMessage = `expected an object, instead received ${typeof object}`) { - if (typeof object !== "object") { - throw new TypeError(errorMessage); - } -} -function assertIsArrayOfFunctions(array, errorMessage = `expected all items to be functions, instead received the following types: `) { - if (!array.every((item) => typeof item === "function")) { - const itemTypes = array.map( - (item) => typeof item === "function" ? `function ${item.name || "unnamed"}()` : typeof item - ).join(", "); - throw new TypeError(`${errorMessage}[${itemTypes}]`); - } -} -var ensureIsArray = (item) => { - return Array.isArray(item) ? item : [item]; -}; -function getDependencies(createSelectorArgs) { - const dependencies = Array.isArray(createSelectorArgs[0]) ? createSelectorArgs[0] : createSelectorArgs; - assertIsArrayOfFunctions( - dependencies, - `createSelector expects all input-selectors to be functions, but received the following types: ` - ); - return dependencies; -} -function collectInputSelectorResults(dependencies, inputSelectorArgs) { - const inputSelectorResults = []; - const { length } = dependencies; - for (let i = 0; i < length; i++) { - inputSelectorResults.push(dependencies[i].apply(null, inputSelectorArgs)); - } - return inputSelectorResults; -} // src/autotrackMemoize/autotracking.ts var $REVISION = 0; @@ -61,8 +29,7 @@ // based. We don't actively tell the caches which depend on the storage that // anything has happened. Instead, we recompute the caches when needed. set value(newValue) { - if (this.value === newValue) - return; + if (this.value === newValue) return; this._value = newValue; this.revision = ++$REVISION; } @@ -150,8 +117,10 @@ dirtyTag(tag, null); } }; + +// src/autotrackMemoize/proxy.ts var nextId = 0; -var proto = Object.getPrototypeOf({}); +var proto = /* @__PURE__ */ Object.getPrototypeOf({}); var ObjectTreeNode = class { constructor(value) { this.value = value; @@ -348,191 +317,4 @@ return memoized; } -// src/weakMapMemoize.ts -var StrongRef = class { - constructor(value) { - this.value = value; - } - deref() { - return this.value; - } -}; -var Ref = typeof WeakRef !== "undefined" ? WeakRef : StrongRef; -var UNTERMINATED = 0; -var TERMINATED = 1; -function createCacheNode() { - return { - s: UNTERMINATED, - v: void 0, - o: null, - p: null - }; -} -function weakMapMemoize(func, options = {}) { - let fnNode = createCacheNode(); - const { resultEqualityCheck } = options; - let lastResult; - let resultsCount = 0; - function memoized() { - let cacheNode = fnNode; - const { length } = arguments; - for (let i = 0, l = length; i < l; i++) { - const arg = arguments[i]; - if (typeof arg === "function" || typeof arg === "object" && arg !== null) { - let objectCache = cacheNode.o; - if (objectCache === null) { - cacheNode.o = objectCache = /* @__PURE__ */ new WeakMap(); - } - const objectNode = objectCache.get(arg); - if (objectNode === void 0) { - cacheNode = createCacheNode(); - objectCache.set(arg, cacheNode); - } else { - cacheNode = objectNode; - } - } else { - let primitiveCache = cacheNode.p; - if (primitiveCache === null) { - cacheNode.p = primitiveCache = /* @__PURE__ */ new Map(); - } - const primitiveNode = primitiveCache.get(arg); - if (primitiveNode === void 0) { - cacheNode = createCacheNode(); - primitiveCache.set(arg, cacheNode); - } else { - cacheNode = primitiveNode; - } - } - } - const terminatedNode = cacheNode; - let result; - if (cacheNode.s === TERMINATED) { - result = cacheNode.v; - } else { - result = func.apply(null, arguments); - resultsCount++; - if (resultEqualityCheck) { - const lastResultValue = lastResult?.deref?.() ?? lastResult; - if (lastResultValue != null && resultEqualityCheck(lastResultValue, result)) { - result = lastResultValue; - resultsCount !== 0 && resultsCount--; - } - const needsWeakRef = typeof result === "object" && result !== null || typeof result === "function"; - lastResult = needsWeakRef ? new Ref(result) : result; - } - } - terminatedNode.s = TERMINATED; - terminatedNode.v = result; - return result; - } - memoized.clearCache = () => { - fnNode = createCacheNode(); - memoized.resetResultsCount(); - }; - memoized.resultsCount = () => resultsCount; - memoized.resetResultsCount = () => { - resultsCount = 0; - }; - return memoized; -} - -// src/createSelectorCreator.ts -function createSelectorCreator(memoizeOrOptions, ...memoizeOptionsFromArgs) { - const createSelectorCreatorOptions = typeof memoizeOrOptions === "function" ? { - memoize: memoizeOrOptions, - memoizeOptions: memoizeOptionsFromArgs - } : memoizeOrOptions; - const createSelector2 = (...createSelectorArgs) => { - let recomputations = 0; - let dependencyRecomputations = 0; - let lastResult; - let directlyPassedOptions = {}; - let resultFunc = createSelectorArgs.pop(); - if (typeof resultFunc === "object") { - directlyPassedOptions = resultFunc; - resultFunc = createSelectorArgs.pop(); - } - assertIsFunction( - resultFunc, - `createSelector expects an output function after the inputs, but received: [${typeof resultFunc}]` - ); - const combinedOptions = { - ...createSelectorCreatorOptions, - ...directlyPassedOptions - }; - const { - memoize, - memoizeOptions = [], - argsMemoize = weakMapMemoize, - argsMemoizeOptions = [], - devModeChecks = {} - } = combinedOptions; - const finalMemoizeOptions = ensureIsArray(memoizeOptions); - const finalArgsMemoizeOptions = ensureIsArray(argsMemoizeOptions); - const dependencies = getDependencies(createSelectorArgs); - const memoizedResultFunc = memoize(function recomputationWrapper() { - recomputations++; - return resultFunc.apply( - null, - arguments - ); - }, ...finalMemoizeOptions); - const selector = argsMemoize(function dependenciesChecker() { - dependencyRecomputations++; - const inputSelectorResults = collectInputSelectorResults( - dependencies, - arguments - ); - lastResult = memoizedResultFunc.apply(null, inputSelectorResults); - return lastResult; - }, ...finalArgsMemoizeOptions); - return Object.assign(selector, { - resultFunc, - memoizedResultFunc, - dependencies, - dependencyRecomputations: () => dependencyRecomputations, - resetDependencyRecomputations: () => { - dependencyRecomputations = 0; - }, - lastResult: () => lastResult, - recomputations: () => recomputations, - resetRecomputations: () => { - recomputations = 0; - }, - memoize, - argsMemoize - }); - }; - Object.assign(createSelector2, { - withTypes: () => createSelector2 - }); - return createSelector2; -} -var createSelector = /* @__PURE__ */ createSelectorCreator(weakMapMemoize); - -// src/createStructuredSelector.ts -var createStructuredSelector = Object.assign( - (inputSelectorsObject, selectorCreator = createSelector) => { - assertIsObject( - inputSelectorsObject, - `createStructuredSelector expects first argument to be an object where each property is a selector, instead received a ${typeof inputSelectorsObject}` - ); - const inputSelectorKeys = Object.keys(inputSelectorsObject); - const dependencies = inputSelectorKeys.map( - (key) => inputSelectorsObject[key] - ); - const structuredSelector = selectorCreator( - dependencies, - (...inputSelectorResults) => { - return inputSelectorResults.reduce((composition, value, index) => { - composition[inputSelectorKeys[index]] = value; - return composition; - }, {}); - } - ); - return structuredSelector; - }, - { withTypes: () => createStructuredSelector } -); - export { autotrackMemoize as unstable_autotrackMemoize }; ```
weakMapMemoize changes (Click to expand) **File Content**: ```ts export { weakMapMemoize } from 'reselect' ```
Before and After ```diff --- before/reselect/weakMapMemoize.js 2024-06-25 02:52:07.058601400 -0500 +++ after/reselect/weakMapMemoize.js 2024-06-25 08:06:25.352656500 -0500 @@ -1,41 +1,4 @@ // src/devModeChecks/identityFunctionCheck.ts -function assertIsFunction(func, errorMessage = `expected a function, instead received ${typeof func}`) { - if (typeof func !== "function") { - throw new TypeError(errorMessage); - } -} -function assertIsObject(object, errorMessage = `expected an object, instead received ${typeof object}`) { - if (typeof object !== "object") { - throw new TypeError(errorMessage); - } -} -function assertIsArrayOfFunctions(array, errorMessage = `expected all items to be functions, instead received the following types: `) { - if (!array.every((item) => typeof item === "function")) { - const itemTypes = array.map( - (item) => typeof item === "function" ? `function ${item.name || "unnamed"}()` : typeof item - ).join(", "); - throw new TypeError(`${errorMessage}[${itemTypes}]`); - } -} -var ensureIsArray = (item) => { - return Array.isArray(item) ? item : [item]; -}; -function getDependencies(createSelectorArgs) { - const dependencies = Array.isArray(createSelectorArgs[0]) ? createSelectorArgs[0] : createSelectorArgs; - assertIsArrayOfFunctions( - dependencies, - `createSelector expects all input-selectors to be functions, but received the following types: ` - ); - return dependencies; -} -function collectInputSelectorResults(dependencies, inputSelectorArgs) { - const inputSelectorResults = []; - const { length } = dependencies; - for (let i = 0; i < length; i++) { - inputSelectorResults.push(dependencies[i].apply(null, inputSelectorArgs)); - } - return inputSelectorResults; -} // src/weakMapMemoize.ts var StrongRef = class { @@ -46,7 +9,8 @@ return this.value; } }; -var Ref = typeof WeakRef !== "undefined" ? WeakRef : StrongRef; +var getWeakRef = () => typeof WeakRef === "undefined" ? StrongRef : WeakRef; +var Ref = /* @__PURE__ */ getWeakRef(); var UNTERMINATED = 0; var TERMINATED = 1; function createCacheNode() { @@ -107,7 +71,7 @@ resultsCount !== 0 && resultsCount--; } const needsWeakRef = typeof result === "object" && result !== null || typeof result === "function"; - lastResult = needsWeakRef ? new Ref(result) : result; + lastResult = needsWeakRef ? /* @__PURE__ */ new Ref(result) : result; } } terminatedNode.s = TERMINATED; @@ -125,103 +89,4 @@ return memoized; } -// src/createSelectorCreator.ts -function createSelectorCreator(memoizeOrOptions, ...memoizeOptionsFromArgs) { - const createSelectorCreatorOptions = typeof memoizeOrOptions === "function" ? { - memoize: memoizeOrOptions, - memoizeOptions: memoizeOptionsFromArgs - } : memoizeOrOptions; - const createSelector2 = (...createSelectorArgs) => { - let recomputations = 0; - let dependencyRecomputations = 0; - let lastResult; - let directlyPassedOptions = {}; - let resultFunc = createSelectorArgs.pop(); - if (typeof resultFunc === "object") { - directlyPassedOptions = resultFunc; - resultFunc = createSelectorArgs.pop(); - } - assertIsFunction( - resultFunc, - `createSelector expects an output function after the inputs, but received: [${typeof resultFunc}]` - ); - const combinedOptions = { - ...createSelectorCreatorOptions, - ...directlyPassedOptions - }; - const { - memoize, - memoizeOptions = [], - argsMemoize = weakMapMemoize, - argsMemoizeOptions = [], - devModeChecks = {} - } = combinedOptions; - const finalMemoizeOptions = ensureIsArray(memoizeOptions); - const finalArgsMemoizeOptions = ensureIsArray(argsMemoizeOptions); - const dependencies = getDependencies(createSelectorArgs); - const memoizedResultFunc = memoize(function recomputationWrapper() { - recomputations++; - return resultFunc.apply( - null, - arguments - ); - }, ...finalMemoizeOptions); - const selector = argsMemoize(function dependenciesChecker() { - dependencyRecomputations++; - const inputSelectorResults = collectInputSelectorResults( - dependencies, - arguments - ); - lastResult = memoizedResultFunc.apply(null, inputSelectorResults); - return lastResult; - }, ...finalArgsMemoizeOptions); - return Object.assign(selector, { - resultFunc, - memoizedResultFunc, - dependencies, - dependencyRecomputations: () => dependencyRecomputations, - resetDependencyRecomputations: () => { - dependencyRecomputations = 0; - }, - lastResult: () => lastResult, - recomputations: () => recomputations, - resetRecomputations: () => { - recomputations = 0; - }, - memoize, - argsMemoize - }); - }; - Object.assign(createSelector2, { - withTypes: () => createSelector2 - }); - return createSelector2; -} -var createSelector = /* @__PURE__ */ createSelectorCreator(weakMapMemoize); - -// src/createStructuredSelector.ts -var createStructuredSelector = Object.assign( - (inputSelectorsObject, selectorCreator = createSelector) => { - assertIsObject( - inputSelectorsObject, - `createStructuredSelector expects first argument to be an object where each property is a selector, instead received a ${typeof inputSelectorsObject}` - ); - const inputSelectorKeys = Object.keys(inputSelectorsObject); - const dependencies = inputSelectorKeys.map( - (key) => inputSelectorsObject[key] - ); - const structuredSelector = selectorCreator( - dependencies, - (...inputSelectorResults) => { - return inputSelectorResults.reduce((composition, value, index) => { - composition[inputSelectorKeys[index]] = value; - return composition; - }, {}); - } - ); - return structuredSelector; - }, - { withTypes: () => createStructuredSelector } -); - export { weakMapMemoize }; ```
markerikson commented 2 months ago

Nice, that does seem like it's better!

aryaemami59 commented 2 months ago

@markerikson I'll try to put togther the same kind of chart for the other Redux repos as well. It might be good to have it as a point of reference.

aryaemami59 commented 1 month ago

Thanks. Can we add esbuild to devDependencies instead of the resolutions field? Do you want me to put up a PR for that?