Skip to content

Conversation

@YCChenVictor
Copy link

Object.defineProperty is updated to lazily load the undici dependency for the fetch method. This change allows for simpler and more reliable mocking of the fetch method for testing purposes, resolving issues encountered with premature method invocation during testing.

Fixes: #52015

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/startup
  • @nodejs/web-standards

@nodejs-github-botnodejs-github-bot added lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels Mar 30, 2024
Copy link
Member

@mcollinamcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this setup slows down every invocation of fetch() by adding an additional function call and the require logic. The previous logic added lazy loading that should be kept in.

Could you add a test? I don't understand what would not be possible in the previous setup.

@MoLow
Copy link
Member

Could you add a test? I don't understand what would not be possible in the previous setup.

see #52015
mocking globalThis.fetch is harder without this fix.

1 similar comment
@MoLow
Copy link
Member

Could you add a test? I don't understand what would not be possible in the previous setup.

see #52015
mocking globalThis.fetch is harder without this fix.

@mcollina
Copy link
Member

The test should be added and the lazyloading kept in.

@regseb
Copy link
Contributor

regseb commented Apr 4, 2024

@mcollina

I think this configuration is faster on the first call (there's no need to replace get and set by value). And the speed is the same for next calls.


console.log("BEFORE");console.log(Object.getOwnPropertyDescriptor(globalThis,"fetch"));console.log(Object.getOwnPropertyDescriptor(globalThis,"fetch").set.toString());console.log(Object.getOwnPropertyDescriptor(globalThis,"fetch").get.toString());fetch;console.log("AFTER");console.log(Object.getOwnPropertyDescriptor(globalThis,"fetch"));console.log(Object.getOwnPropertyDescriptor(globalThis,"fetch").value.toString());

When I run the above code in Node.js v21.7.0:

BEFORE{get: [Function: get], set: [Function: set], enumerable: true, configurable: true } function set(value){ObjectDefineProperty(globalThis, 'fetch',{__proto__: null, writable: true, value, })} get(){function fetch(input, init = undefined){// Loading undici alone lead to promises which breaks lots of tests so we // have to load it really lazily for now. const{fetch: impl } = require('internal/deps/undici/undici'); return impl(input, init)} set(fetch); return fetch} AFTER{value: [Function: fetch], writable: true, enumerable: true, configurable: true } function fetch(input, init = undefined){// Loading undici alone lead to promises which breaks lots of tests so we // have to load it really lazily for now. const{fetch: impl } = require('internal/deps/undici/undici'); return impl(input, init)} 

With this pull request, the AFTER configuration is directly available.


Lazyloading is kept, as undici is only imported when fetch() is run.

value: functionfetch(input,init=undefined){// eslint-disable-line func-name-matching
// Loading undici alone lead to promises which breaks lots of tests so we
// have to load it really lazily for now.
const{fetch: impl}=require('internal/deps/undici/undici');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really need to lazily load it every time?
Can't we have something around the lines of:

letimpl;value: functionfetch(input,init=undefined){impl??=require('internal/deps/undici/undici');returnimpl(input,init)},

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically require would cache it anyway, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, technically it will, but the cost for calling require would still be higher (I don't have benchmarks, but it has more overhead than holding a local variable in memory)

@mcollina
Copy link
Member

What @atlowChemi wrote in #52275 (comment)

const{ installObjectURLMethods }=require('internal/url');
installObjectURLMethods();

{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the curly bracket is no longer necessary. It was probably used to avoid creating the set function in the root scope.

Object.defineProperty is updated to lazily load the undici dependency for the fetch method. This change allows for simpler and more reliable mocking of the fetch method for testing purposes, resolving issues encountered with premature method invocation during testing. Fixes: nodejs#52015
@YCChenVictorYCChenVictorforce-pushed the feature/lazy-fetch-undici-loading branch from 796a413 to 9ee922eCompareApril 7, 2024 05:58
@MoLowMoLow requested a review from mcollinaApril 7, 2024 07:33
Copy link
Member

@atlowChemiatlowChemi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than lint errors, LGTM

Copy link
Member

@mcollinamcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Instead of importing undici upfront, the module is now conditionally required using require only when the fetch function is called for the first time and the undici implementation is not already available. This lazy loading approach improves resource usage and test reliability by loading undici only when needed.
@YCChenVictorYCChenVictorforce-pushed the feature/lazy-fetch-undici-loading branch from 9ee922e to 5c6a889CompareApril 9, 2024 01:14
@MoLowMoLow added request-ci Add this label to start a Jenkins CI on a PR. and removed request-ci Add this label to start a Jenkins CI on a PR. labels Apr 9, 2024
@mcollinamcollina added the request-ci Add this label to start a Jenkins CI on a PR. label Apr 9, 2024
@MoLow
Copy link
Member

MoLow commented Apr 9, 2024

@YCChenVictor can you add a test that checks #52015 won't regress?

@panvapanva added the commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. label Apr 9, 2024
@YCChenVictorYCChenVictorforce-pushed the feature/lazy-fetch-undici-loading branch from b42ee5b to 2eddedaCompareApril 9, 2024 13:25
Copy link
Contributor

@Ethan-ArrowoodEthan-Arrowood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does this work with the following lines (just below your contribution?):

exposeLazyInterfaces(globalThis,'internal/deps/undici/undici',['FormData','Headers','Request','Response',]);

If I use any of those interfaces, should fetch be loaded as well?

@YCChenVictorYCChenVictorforce-pushed the feature/lazy-fetch-undici-loading branch from 2eddeda to 7937b69CompareApril 11, 2024 08:08
@MoLowMoLow added the request-ci Add this label to start a Jenkins CI on a PR. label Apr 11, 2024
@github-actionsgithub-actionsbot removed the request-ci Add this label to start a Jenkins CI on a PR. label Apr 11, 2024
@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@YCChenVictor
Copy link
Author

I'm uncertain why the checks failed. Perhaps I should rebase this branch on the latest node commit? Any guidance would be greatly appreciated, and I'm sincerely grateful for any corrections or suggestions. Thank you!

@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@joyeecheung
Copy link
Member

The failures are most likely flakes.

@nodejs-github-bot
Copy link
Collaborator

@joyeecheungjoyeecheung added the commit-queue Add this label to land a pull request using GitHub Actions. label Apr 12, 2024
@nodejs-github-botnodejs-github-bot added commit-queue-failed An error occurred while landing this pull request using GitHub Actions. and removed commit-queue Add this label to land a pull request using GitHub Actions. labels Apr 12, 2024
@nodejs-github-bot
Copy link
Collaborator

Commit Queue failed
- Loading data for nodejs/node/pull/52275 ✔ Done loading data for nodejs/node/pull/52275 ----------------------------------- PR info ------------------------------------ Title lib: refactor lazy loading of undici for fetch method (#52275) Author Victor Chen (@YCChenVictor, first-time contributor) Branch YCChenVictor:feature/lazy-fetch-undici-loading -> nodejs:main Labels lib / src, needs-ci, commit-queue-squash Commits 3 - lib: refactor lazy loading of undici for fetch method - lib: implement lazy loading for fetch function - lib: test for fetch mock without prior invocation Committers 1 - YCChen PR-URL: https://github.com/nodejs/node/pull/52275 Fixes: https://github.com/nodejs/node/issues/52015 Reviewed-By: Moshe Atlow Reviewed-By: Matteo Collina Reviewed-By: Chemi Atlow Reviewed-By: James M Snell ------------------------------ Generated metadata ------------------------------ PR-URL: https://github.com/nodejs/node/pull/52275 Fixes: https://github.com/nodejs/node/issues/52015 Reviewed-By: Moshe Atlow Reviewed-By: Matteo Collina Reviewed-By: Chemi Atlow Reviewed-By: James M Snell -------------------------------------------------------------------------------- ⚠ Commits were pushed since the last approving review: ⚠ - lib: test for fetch mock without prior invocation ℹ This PR was created on Sat, 30 Mar 2024 14:26:41 GMT ✔ Approvals: 4 ✔ - Moshe Atlow (@MoLow) (TSC): https://github.com/nodejs/node/pull/52275#pullrequestreview-1990083304 ✔ - Matteo Collina (@mcollina) (TSC): https://github.com/nodejs/node/pull/52275#pullrequestreview-1985970496 ✔ - Chemi Atlow (@atlowChemi): https://github.com/nodejs/node/pull/52275#pullrequestreview-1988005649 ✔ - James M Snell (@jasnell) (TSC): https://github.com/nodejs/node/pull/52275#pullrequestreview-1992479891 ✔ Last GitHub CI successful ℹ Last Full PR CI on 2024-04-12T14:12:32Z: https://ci.nodejs.org/job/node-test-pull-request/58323/ - Querying data for job/node-test-pull-request/58323/ ✔ Last Jenkins CI successful -------------------------------------------------------------------------------- ✔ Aborted `git node land` session in /home/runner/work/node/node/.ncu
https://github.com/nodejs/node/actions/runs/8665947485

@joyeecheungjoyeecheung added commit-queue Add this label to land a pull request using GitHub Actions. and removed commit-queue-failed An error occurred while landing this pull request using GitHub Actions. labels Apr 12, 2024
@nodejs-github-botnodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Apr 12, 2024
@nodejs-github-botnodejs-github-bot merged commit 2cd3073 into nodejs:mainApr 12, 2024
@nodejs-github-bot
Copy link
Collaborator

Landed in 2cd3073

aduh95 pushed a commit that referenced this pull request Apr 29, 2024
Object.defineProperty is updated to lazily load the undici dependency for the fetch method. This change allows for simpler and more reliable mocking of the fetch method for testing purposes, resolving issues encountered with premature method invocation during testing. Fixes: #52015 PR-URL: #52275 Reviewed-By: Moshe Atlow <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Chemi Atlow <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
marco-ippolito pushed a commit that referenced this pull request May 2, 2024
Object.defineProperty is updated to lazily load the undici dependency for the fetch method. This change allows for simpler and more reliable mocking of the fetch method for testing purposes, resolving issues encountered with premature method invocation during testing. Fixes: #52015 PR-URL: #52275 Reviewed-By: Moshe Atlow <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Chemi Atlow <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
@marco-ippolitomarco-ippolito mentioned this pull request May 2, 2024
marco-ippolito pushed a commit that referenced this pull request May 3, 2024
Object.defineProperty is updated to lazily load the undici dependency for the fetch method. This change allows for simpler and more reliable mocking of the fetch method for testing purposes, resolving issues encountered with premature method invocation during testing. Fixes: #52015 PR-URL: #52275 Reviewed-By: Moshe Atlow <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Chemi Atlow <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commit-queue-squashAdd this label to instruct the Commit Queue to squash all the PR commits into the first one.lib / srcIssues and PRs related to general changes in the lib or src directory.needs-ciPRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

breaking change in 21.7.0 when mocking fetch

12 participants

@YCChenVictor@nodejs-github-bot@MoLow@mcollina@regseb@joyeecheung@hulkish@jasnell@bakkot@Ethan-Arrowood@atlowChemi@panva