Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite loop in prettyDOM calls crashes test when locator.element() is not found #7249

Open
6 tasks done
tsirlucas opened this issue Jan 14, 2025 · 3 comments
Open
6 tasks done
Labels
feat: browser Issues and PRs related to the browser runner p3-minor-bug An edge case that only affects very specific usage (priority)

Comments

@tsirlucas
Copy link
Contributor

Describe the bug

In

const pretty = stringify(dom, Number.POSITIVE_INFINITY, {
Infinity is sent as parameter to stringify and in
? stringify(object, Math.floor(maxDepth / 2))
the stop condition to the recursion is done by dividing the maxDepth by 2. Considering Infinity / 2 = Infinity, the code enters in a loop and ends up crashing the page.

Reproduction

Found it in private big project (can only be reproduced if the DOM is large enough to enter the result.length >= MAX_LENGTH check. Maybe we can reproduce it by adding a unit test where we send a really small maxDepth and the whole page as object.

System Info

System:
    OS: macOS 15.1.1
    CPU: (14) arm64 Apple M3 Max
    Memory: 6.47 GB / 36.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.12.2 - ~/.nvm/versions/node/v20.12.2/bin/node
    Yarn: 4.6.0 - ~/.nvm/versions/node/v20.12.2/bin/yarn
    npm: 10.5.0 - ~/.nvm/versions/node/v20.12.2/bin/npm
    pnpm: 9.15.2 - ~/.nvm/versions/node/v20.12.2/bin/pnpm
  Browsers:
    Chrome: 131.0.6778.265
    Safari: 18.1.1

Used Package Manager

yarn

Validations

@tsirlucas
Copy link
Contributor Author

Im interested in opening a PR for this one, I think we have a few options here:

Considering that we can have another big value instead of Infinity, lets call it BIG_VALUE_NOT_INFINITY

  • Dont send Number.POSITIVE_INFINITY and instead use BIG_VALUE_NOT_INFINITY
  • Add a safety check inside the function where we overwrite the maxDepth value with BIG_VALUE_NOT_INFINITY

@hi-ogawa hi-ogawa added feat: browser Issues and PRs related to the browser runner p3-minor-bug An edge case that only affects very specific usage (priority) and removed pending triage labels Jan 15, 2025
@hi-ogawa
Copy link
Contributor

Thanks for investigating the issue. Btw, can you share how the error message looks like?

Considering the loop happens due to it goes over MAX_LENGTH = 10000, the simple repro would be like this. Do you see the same error?

import { test } from 'vitest'
import { page } from "@vitest/browser/context"

test("repro", () => {
  let el = document.createElement("div");
  el.textContent = "a".repeat(20000)
  document.body.appendChild(el);
  page.getByText("no-such-text").element()
})
 FAIL   chromium  test/basic.test.ts > repro
RangeError: Maximum call stack size exceeded
 ❯ printPlugin ../../packages/pretty-format/dist/index.js:1:0

@tsirlucas
Copy link
Contributor Author

Thanks for investigating the issue. Btw, can you share how the error message looks like?

There is no error message. Browser crashes and process wont close. In CI it just hangs until the CI itself times out.

image image

However, I noticed it only happens with expect.element and with following test case instead:

test('should handle large nested DOM timeout', async () => {
  let parentDiv = document.createElement("div");
  let currentDiv = parentDiv;

  for (let i = 0; i < 20000; i++) {
    const newDiv = document.createElement("div");
    currentDiv.appendChild(newDiv);
    currentDiv = newDiv;
  }

  document.body.appendChild(parentDiv);

  await expect.element(page.getByText("no-such-text")).toBeVisible()
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: browser Issues and PRs related to the browser runner p3-minor-bug An edge case that only affects very specific usage (priority)
Projects
None yet
Development

No branches or pull requests

2 participants