This patch traces all public async methods and wraps them
in a helper method that tags the sync stack trace.
Later on, if the method call throws an exception, we add
a captured stack trace to the original stack trace with the "--ASYNC--"
heading.
An example of a stack trace:
```
Error: net::ERR_ABORTED at http://localhost:8907/empty.html
at navigate (/Users/lushnikov/prog/puppeteer/lib/Page.js:622:37)
at process._tickCallback (internal/process/next_tick.js:68:7)
-- ASYNC --
at Page.<anonymous> (/Users/lushnikov/prog/puppeteer/lib/helper.js:147:27)
at fit (/Users/lushnikov/prog/puppeteer/test/page.spec.js:546:18)
at process._tickCallback (internal/process/next_tick.js:68:7)
```
This patch:
- moves implementation of page.goto and page.waitForNavigation
into FrameManager. The defaultNavigationTimeout gets moved to
FrameManager as well.
- moves NavigatorWatcher into FrameManager to avoid circular dependency
References #2918
This patch unifies logic in response trackign in page.goto and
page.waitForNavigation.
As a drive-by, we now make sure that we return the right response
for the right frame. This will come handy for future frame navigation
API.
References #2918
Bundled version of Puppeteer should rely on native WebSocket.
Luckily, 'ws' module supports the same interface as the native
browser websockets. This patch switches WebSocketTransport to
use the browser-compliant interface of 'ws'.
After this patch, I was able to bundle Puppeteer for browser
using the following config in `package.json`:
```json
"browser": {
"./lib/BrowserFetcher.js": false,
"ws": "./lib/BrowserWebSocket",
"fs": false,
"child_process": false,
"rimraf": false,
"readline": false
}
```
where `./lib/BrowserWebSocket` is:
```js
module.exports = WebSocket;
```
and the bundling command is:
```sh
$ browserify -r ./index.js:puppeteer > ppweb.js
```
References #2119
Currently connection assumes that transport is a websocket
and tries to handle websocket-related errors.
This patch:
- moves ConnectionTransport interface to use callbacks instead
of events. This way it could be used in browser context as well.
- introduces WebSocketTransport that implements ConnectionTransport
interface for ws.
This is a preparation step for 2 things:
- exposing `transport` option in the `puppeteer.connect` method
- better support for `browserify`
References #2119
This patch removes all dynamic requires in Puppeteer. This should
make it much simpler to bundle puppeteer/puppeteer-core packages.
We used dynamic requires in a few places in lib/:
- BrowserFetcher was choosing between `http` and `https` based on some
runtime value. This was easy to fix with explicit `require`.
- BrowserFetcher and Launcher needed to know project root to store
chromium revisions and to read package name and chromium revision from
package.json. (projectRoot value would be different in node6).
Instead of doing a backwards logic to infer these
variables, we now pass them directly from `//index.js`.
With this patch, I was able to bundle Puppeteer using browserify and
the following config in `package.json`:
```json
"browser": {
"./lib/BrowserFetcher.js": false,
"ws": "./lib/BrowserWebSocket",
"fs": false,
"child_process": false,
"rimraf": false,
"readline": false
}
```
(where `lib/BrowserWebSocket.js` is a courtesy of @Janpot from
https://github.com/GoogleChrome/puppeteer/pull/2374/)
And command:
```sh
$ browserify -r puppeteer:./index.js > ppweb.js
```
References #2119
We had (and still have) a ton of pull requests to support
PUPPETEER_EXECUTABLE_PATH and PUPPETEER_CHROMIUM_REVISION in puppeteer launcher.
We were hesitant before since env variables are not scoped
and thus don't make a good interface for a library. Now, since we
determined `puppeteer-core` as a library and `puppeteer` as our end-user
product, it's safe to satisfy our user needs.
This patch:
- teaches PUPPETEER_EXECUTABLE_PATH and PUPPETEER_CHROMIUM_REVISION
env variables to control how Puppeteer launches browser
- makes sure these variables play no role in `puppeteer-core` package.
Before v1.7.0 we were creating Response objects either from protocol's
Network.Response struct, or from the data available in the
requestIntercepted.
With the recent chagens to the request interception logic, we can
always create response from Newtork.Response struct; this allows
us to simply create Response objects from protocol payload.
If referer is passed to the options object its value will be used as the referer instead of the value set by `Page.setExtraHTTPHeaders()`.
This is the correct way to set referer header: otherwise, the `referer` header will override all the document subrequests.
Fixes#3090.
Introduce an API to manage permissions per browser context:
- BrowserContext.overridePermissions(origin, permissions)
- BrowserContext.clearPermissionOverrides()
Fixes#846.
I ran TypeScript against our code with `strictNullChecks` on. Most of the errors generated are noise, because TypeScript doesn't understand how our `assert` method works. But some were legitimate bugs. They are fixed in this patch.
This patch:
- merges `ElementHandle` into `ExecutionContext` (for simplicity; there's no good reason to have them in separate files).
- removes the necessity to pass handle factory when creating `ExecutionContext`
This makes it easier to create execution contexts out of payloads.
References #1215
It turned out that almost any usecase requires helper methods to access
DOM inside the ExecutionContext.
Instead of exposing execution contexts as-is, we should introduce
IsolatedWorld as a first-class citizen that will hold execution contexts
inside.
This patch adds a new require, `puppeteer/Errors`, that
holds all the Puppeteer-specific error classes.
Currently, the only custom error class we use is `TimeoutError`. We'll
expand in future with `CrashError` and some others.
Fixes#1694.
When an evaluation causes a navigation, for example:
```js
await page.evaluate(() => window.reload());
```
sometimes we process the ExecutionContextDestroyed event before the ack from the evaluate. When we do get the ack from the evaluate, we try to build a JSHandle for it, and try to find the execution by id. But it is gone, and we throw an error. This patch switches createJSHandle to accept an ExecutionContext instead of just an id.
This bug was making the test `should throw a nice error after a navigation` flaky.
In accordance with its declared type, `Map<string, Function>`.
Currently, it is used as a plain old JS object. The compiler marks this
usage as an error when `noImplicitAny: true`. This change switches to
use the appropriate Map methods `has/get/set`.
Fixes#3000
This changes sendCharacter to use document.execCommand instead of sending a `'char'` event from the protocol. This is more aligned with how input would come in from emoji keyboards, and removes the 3ish byte limit on characters that can be sent which prevented larger emoji from being rendered correctly.
Emoji will still fail to type correctly if typing them into an iframe that is in shadow dom.
fixes#1096
This patch rolls Chromium to r579032. The patch includes:
- https://crrev.com/577366 - DevTools: report redirect responses only if response interception is enabled
- https://crrev.com/577212 - DevTools: intercept requests resulting from redirects
- https://crrev.com/578934 - DevTools: Add a protocol method to insertText
Interception Logic in DevTools protocol has changed regarding redirects;
this patch migrates interceptions to dispatch "request" events based on
requestWillBeSent event.
I have seen some flaky test failures where it would be nice to have run the tests with `DEBUG=puppeteer:error`. Instead of always running tests like that, I am redirecting `debugError` to the output category of the test. This is the same thing that we do for Chromium's stderr.
As a drive-by, I added an additional `debugError` where we were usually a try..finally pattern.
When process is spawned with the 'pipe' set for stdout and stderr, Node expects these streams to be actually dispatched. If we don't, write into pipe becomes blocking and chrome stalls.
We work around that via setting 'ignore' to the stdin, stdout and stderr when the pipe communication channel is used.
Chrome Headless used to open about:blank by default; however, this
was recently changed.
We should open starting page no matter what to keep the environment
predictable.
Unfortunately, disabling javascript in page prevents any microtasks
to be executed even from puppeteer-originating javascript. As a
result, the IntersectionObserver hack we use to conditionally
scroll into view doesn't work.
To workaround this, we start always scrolling before clicking if
page's javascript is disabled.
Fixes#2898
This roll includes:
- https://crrev.com/574785 - DevTools: allow tracing over the remote debugging pipe.
This fixes tracing over the remote debugging pipe.
Chrome DevTools shows anonymous scripts with yellow background and names
them with `debugger://VM<scriptId>` prefix.
This patch starts reporting the same debugger:// urls for anonymous
scripts in puppeteer's JS coverage. This might simplify debugging, e.g.
using `debugger;` statement to reveal the script in DevTools and later
matching it against the one in the coverage.
This patch:
- simplifies test reusing the `offscreenbuttons.html` asset
- aligns IntersectionObserver usage with the one we have for
`ElementHandle._scrollIntoViewIfNeeded`.
This patch adds `reportAnonymousScripts` option to the `coverage.startJSCoverage` method. With this option, anonymous scripts are reported as well.
Fixes#2777
EmualationManager used to be injecting touch hooks to properly
support touch emulation.
However, these are no longer necessary, since https://crbug.com/133915
is long fixed.
Originally, we use `Element.scrollIntoViewIfNeeded` to make sure
button is on screen before trying to click it.
However, `Element.scrollIntoViewIfNeeded` doesn't work in certain
scenarios, e.g. when element is partially visible and horizontal
scrolling is required to make it fully visible.
This patch polyfills `element.scrollIntoViewIfNeeded` using
IntersectionObserver and `Element.scrollIntoView`.
Fixes#2804.
This patch:
- stops appending `undefined` to our protocol messages unnecessarily.
- rewrites `Cannot find execution context id` to `Execution context was destroyed, most likely because of a navigation.` when it occurs from a Puppeteer ExecutionContext. The error message is left alone if it occurs via a CDPSession.
This patch eliminates a common race condition with WaitTask, that
happens when predicate function gets resolved right before the execution
context gets destroyed.
This situation results in a "Cannot find context with specified id undefined"
exception.
Credits go to @jakub300 for his wonderful [investigation](https://github.com/GoogleChrome/puppeteer/issues/1325#issuecomment-395472092).
Fixes#1325.
I've been told that this will make our JavaScript tracing 💯x more accurate, at minimal performance loss. Let's turn it on for everyone always.
Fixes#1300.
This patch:
- adds `worker.evaluate` and `worker.evaluateHandle` methods as a shortcut to their execution context equivalents.
- makes the error messages a bit nicer when interacting with a closed worker (as opposed to a closed page).
- moves the worker tests into their own spec file.
This patch disables OOPIF by default.
**NOTE**: this is a temporary bandaid for the time we're crafting
the full-fledged support for site isolation over DevTools protocol.
References #2548.
It's impossible to launch chromium without initial page.
This patch makes sure that `puppeteer.launch()` always returns a browser
with at least one page user can connect to.
This patch disables crash reporting since it's not needed for
automation purposes.
It also deals some troubles for us since crashpad is a separate
process on Windows which has a larger lifetime than chromium.
This, in turn, prevents us from cleaning up profile directory.
Since Node 10, `console.assert` no longer throws an AssertionError.
(This is generally good since it aligns Node.js with Browsers.)
This patch migrates all usages of `console.assert` in our codebase.
- All the `lib/` and testing code is migrated onto a handmade `assert`
function. This is to make Puppeteer transpilation / bundling easier.
- All the tooling is switched to use Node's `assert` module.
Fixes#2547.
Page subtargets (e.g. out-of-process iframes and others) sometimes
die before we send the 'detach' command.
This is harmless to us, but we shouldn't have an unhandled promise
rejection in this case.
Example crash: https://cirrus-ci.com/task/4884032470908928
Some of the worker tests were failing on the bots. After investigating, I found one race in the test, and one race upstream in Chromium which I filed upstream as https://crbug.com/846099. But I added a small hack here as a temporary workaround.
References #2632
This adds `page.workers()`, and two events `workercreated` and `workerdestroyed`. It also forwards logs from a worker into the page `console` event.
Only dedicated workers are supported for now, ServiceWorkers will probably work differently because they aren't necessarily associated with a single page.
Fixes#2350.
This patch starts explicitly passing allowed options to the `Browser`
class. This, for example, makes it impossible to pass `appMode` as
an option to the `pptr.connect`.
This patch introduces Browser Contexts and methods to manage them:
- `browser.createIncognitoBrowserContext()` - to create new incognito
context
- `browser.browserContext()` - to get all existing contexts
- `browserContext.dispose()` - to dispose incognito context.
Fixes#85.
Today, `page.close()` method doesn't run page's beforeunload listeners.
This way users can be sure that `page.close()` actually closes the
page.
This patch adds an optional `runBeforeUnload` option to the
`page.close()` method that would run beforeunload listeners. Note:
running beforeunload handlers might cancel page closing.
Fixes#2386.