Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
- `Browser::Process#default_user_agent`, `#browser_version`, `#protocol_version`, `#v8_version` and `#webkit_version`,
use `Browser#default_user_agent` and `Browser#version` instead
- Ruby 3.1 support, Ferrum requires Ruby 3.2 or newer
- `#evaluate_async`, `#evaluate_func` and `#evaluate_on`, use `#evaluate` and `Node#evaluate`


## [0.19.1](https://github.com/rubycdp/ferrum/compare/v0.19.0...v0.19.1) (October 16, 2026) ##
Expand Down Expand Up @@ -122,8 +123,9 @@
- `Ferrum::Page::Stream#stream` now closes the CDP stream handle (`IO.close`) once it's been fully read, so streams
opened for `Ferrum::Browser#pdf` and `Ferrum::Page::Tracing#record` no longer keep their backing storage alive in
the browser; a failed `IO.close` is raised to the caller.
- `#evaluate_async`, `#evaluate_func` and `#evaluate_on` are deprecated, and scripts whose result will change in the upcoming
0.21 warn with a rewrite, see [upgrading](docs/13-javascript.md#upgrading-to-021)
- `#evaluate`/`#execute` await a returned promise or thenable, keywords are always named parameters and can't be
mixed with positional arguments, a thrown non-`Error` raises, and `Node#evaluate` resolves nodes and dates, see
[upgrading](docs/13-javascript.md#upgrading-to-021)
- `Ferrum::ScriptTimeoutError` is a `Ferrum::TimeoutError`

### Fixed
Expand Down
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,7 @@ page.evaluate(<<~JS, a: 1, b: 2)
JS
```

`await` works directly, and a function declaration's returned promise is
awaited:
`await` works directly, and a returned promise is awaited:

```ruby
page.evaluate("await fetch(url).then(r => r.text())", url: "/api")
Expand Down Expand Up @@ -134,8 +133,7 @@ page.evaluate("Array.from(nodes).map(n => n.textContent)", nodes: list)
page.at_css("input").evaluate("this.value")
```

Scripts written for the old API keep working, and Ferrum warns about any whose
result will change in the next release, 0.21, with a suggested rewrite. See
Coming from 0.20 or earlier? See
[upgrading to 0.21](docs/13-javascript.md#upgrading-to-021).

Do any mouse movements you like:
Expand Down
10 changes: 4 additions & 6 deletions docs/13-javascript.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,15 @@ page.at_css("input").execute("this.value = text", text: "hello")

#### Upgrading to 0.21

The next release, Ferrum 0.21, finishes the move to the API above. Until then, scripts written for the old API run
exactly as before, and Ferrum warns, pointing at your code, about any whose result will change. `evaluate_async`,
`evaluate_func` and `evaluate_on` are deprecated and will be removed in 0.21. Set
`FERRUM_DEPRECATION_WARNINGS=raise` to turn the warnings into errors while migrating, or `0` to silence them.
0.21 finishes the move to the API above. Ferrum 0.20 runs old-style scripts as before and warns about each change below,
pointing at your code, so upgrade to 0.20 first and fix its warnings.

| Warning | In 0.20 | From 0.21 | Rewrite |
| Script | 0.20 | 0.21 | Rewrite |
|---|---|---|---|
| Keyword arguments read through `arguments` | one object in `arguments[0]` | named parameters | `evaluate("options.foo", options: { foo: 1 })` |
| Mixing positional and keyword arguments | keywords appended as an object | `ArgumentError` | pass the object in braces, or name every argument |
| More than one expression, `"a(); b"` | returns `a()`, skips the rest | `SyntaxError` | `evaluate("function() { a(); return b }")` |
| Never runs, a line break before the script | `nil`, nothing runs | runs and returns its value | check it's safe to run, or remove it |
| A line break before the script | `nil`, nothing runs | runs and returns its value | check it's safe to run, or remove it |
| Returns a promise | `{}`, not awaited | awaited, raises if rejected | prefix with `void` to keep it from waiting |
| Returns an object with a `then` method | the object | awaited like a promise | wrap it, `({ value: object })` |
| Throws something that isn't an `Error` | the thrown value | `Ferrum::JavaScriptError` | return the value instead |
Expand Down
1 change: 0 additions & 1 deletion lib/ferrum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
require "ferrum/utils/platform"
require "ferrum/utils/elapsed_time"
require "ferrum/utils/attempt"
require "ferrum/utils/deprecate"
require "ferrum/errors"
require "ferrum/browser"
require "ferrum/remote_object"
Expand Down
3 changes: 1 addition & 2 deletions lib/ferrum/browser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ class Browser
screenshot pdf mhtml viewport_size device_pixel_ratio
start_screencast stop_screencast
frames frame_by main_frame
evaluate evaluate_handle execute
evaluate_on evaluate_async evaluate_func isolated_world
evaluate evaluate_handle execute isolated_world
add_script_tag add_style_tag bypass_csp
evaluate_on_new_document remove_script_on_new_document
on position position=
Expand Down
7 changes: 0 additions & 7 deletions lib/ferrum/frame/runtime.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

require "singleton"
require "ferrum/frame/script"
require "ferrum/frame/runtime/legacy"

module Ferrum
#
Expand Down Expand Up @@ -81,8 +80,6 @@ class Frame
# it run for as long as it takes.
#
module Runtime
include Legacy

INTERMITTENT_ATTEMPTS = ENV.fetch("FERRUM_INTERMITTENT_ATTEMPTS", 6).to_i
INTERMITTENT_SLEEP = ENV.fetch("FERRUM_INTERMITTENT_SLEEP", 0.1).to_f

Expand Down Expand Up @@ -199,10 +196,6 @@ def evaluate_in(object, expression, positional, keywords, mode: :value)
#
def run(expression, positional, keywords, mode:, on: nil)
script = Script.new(expression)
if legacy?(script, positional, keywords, mode: mode, on: on)
return run_legacy(script, positional, keywords, mode: mode, on: on)
end

named = keywords.except(:timeout, :args)
params, values = arguments_for(script, positional, named_arguments(keywords[:args], named), mode)
call(wrap(script, params, mode), values, on: on, mode: mode, timeout: script_timeout(keywords[:timeout]))
Expand Down
Loading
Loading