lib/puppeteer/page.rb in puppeteer-ruby-0.30.0 vs lib/puppeteer/page.rb in puppeteer-ruby-0.31.0
- old
+ new
@@ -1,6 +1,7 @@
require 'base64'
+require 'json'
require "stringio"
require_relative './page/pdf_options'
require_relative './page/screenshot_options'
require_relative './page/screenshot_task_queue'
@@ -96,11 +97,13 @@
emit_event(PageEmittedEvents::DOMContentLoaded)
end
@client.on_event('Page.loadEventFired') do |event|
emit_event(PageEmittedEvents::Load)
end
- # client.on('Runtime.consoleAPICalled', event => this._onConsoleAPI(event));
+ @client.on('Runtime.consoleAPICalled') do |event|
+ handle_console_api(event)
+ end
# client.on('Runtime.bindingCalled', event => this._onBindingCalled(event));
@client.on_event('Page.javascriptDialogOpening') do |event|
handle_dialog_opening(event)
end
@client.on_event('Runtime.exceptionThrown') do |exception|
@@ -371,43 +374,25 @@
unless items.empty?
@client.send_message("Network.setCookies", cookies: items)
end
end
- class ScriptTag
- # @param {!{content?: string, path?: string, type?: string, url?: string}} options
- def initialize(content: nil, path: nil, type: nil, url: nil)
- @content = content
- @path = path
- @type = type
- @url = url
- end
- attr_reader :content, :path, :type, :url
+ # @param url [String?]
+ # @param path [String?]
+ # @param content [String?]
+ # @param type [String?]
+ def add_script_tag(url: nil, path: nil, content: nil, type: nil)
+ main_frame.add_script_tag(url: url, path: path, content: content, type: type)
end
- # @param style_tag [Puppeteer::Page::ScriptTag]
- # @return {!Promise<!ElementHandle>}
- def add_script_tag(script_tag)
- main_frame.add_script_tag(script_tag)
+ # @param url [String?]
+ # @param path [String?]
+ # @param content [String?]
+ def add_style_tag(url: nil, path: nil, content: nil)
+ main_frame.add_style_tag(url: url, path: path, content: content)
end
- class StyleTag
- # @param {!{content?: string, path?: string, url?: string}} options
- def initialize(content: nil, path: nil, url: nil)
- @content = content
- @path = path
- @url = url
- end
- attr_reader :content, :path, :url
- end
-
- # @param style_tag [Puppeteer::Page::StyleTag]
- # @return {!Promise<!ElementHandle>}
- def add_style_tag(style_tag)
- main_frame.add_style_tag(style_tag)
- end
-
# /**
# * @param {string} name
# * @param {Function} puppeteerFunction
# */
# async exposeFunction(name, puppeteerFunction) {
@@ -492,35 +477,36 @@
err = PageError.new(message)
# err.stack = ''; // Don't report clientside error with a node stack attached
emit_event(PageEmittedEvents::PageError, err)
end
- # /**
- # * @param {!Protocol.Runtime.consoleAPICalledPayload} event
- # */
- # async _onConsoleAPI(event) {
- # if (event.executionContextId === 0) {
- # // DevTools protocol stores the last 1000 console messages. These
- # // messages are always reported even for removed execution contexts. In
- # // this case, they are marked with executionContextId = 0 and are
- # // reported upon enabling Runtime agent.
- # //
- # // Ignore these messages since:
- # // - there's no execution context we can use to operate with message
- # // arguments
- # // - these messages are reported before Puppeteer clients can subscribe
- # // to the 'console'
- # // page event.
- # //
- # // @see https://github.com/puppeteer/puppeteer/issues/3865
- # return;
- # }
- # const context = this._frameManager.executionContextById(event.executionContextId);
- # const values = event.args.map(arg => createJSHandle(context, arg));
- # this._addConsoleMessage(event.type, values, event.stackTrace);
- # }
+ private def handle_console_api(event)
+ if event['executionContextId'] == 0
+ # DevTools protocol stores the last 1000 console messages. These
+ # messages are always reported even for removed execution contexts. In
+ # this case, they are marked with executionContextId = 0 and are
+ # reported upon enabling Runtime agent.
+ #
+ # Ignore these messages since:
+ # - there's no execution context we can use to operate with message
+ # arguments
+ # - these messages are reported before Puppeteer clients can subscribe
+ # to the 'console'
+ # page event.
+ #
+ # @see https://github.com/puppeteer/puppeteer/issues/3865
+ return
+ end
+ context = @frame_manager.execution_context_by_id(event['executionContextId'])
+ values = event['args'].map do |arg|
+ remote_object = Puppeteer::RemoteObject.new(arg)
+ Puppeteer::JSHandle.create(context: context, remote_object: remote_object)
+ end
+ add_console_message(event['type'], values, event['stackTrace'])
+ end
+
# /**
# * @param {!Protocol.Runtime.bindingCalledPayload} event
# */
# async _onBindingCalled(event) {
# const {name, seq, args} = JSON.parse(event.payload);
@@ -568,37 +554,28 @@
# window[name]['callbacks'].get(seq).reject(value);
# window[name]['callbacks'].delete(seq);
# }
# }
- # /**
- # * @param {string} type
- # * @param {!Array<!Puppeteer.JSHandle>} args
- # * @param {Protocol.Runtime.StackTrace=} stackTrace
- # */
- # _addConsoleMessage(type, args, stackTrace) {
- # if (!this.listenerCount(PageEmittedEvents::Console)) {
- # args.forEach(arg => arg.dispose());
- # return;
- # }
- # const textTokens = [];
- # for (const arg of args) {
- # const remoteObject = arg._remoteObject;
- # if (remoteObject.objectId)
- # textTokens.push(arg.toString());
- # else
- # textTokens.push(helper.valueFromRemoteObject(remoteObject));
- # }
- # const location = stackTrace && stackTrace.callFrames.length ? {
- # url: stackTrace.callFrames[0].url,
- # lineNumber: stackTrace.callFrames[0].lineNumber,
- # columnNumber: stackTrace.callFrames[0].columnNumber,
- # } : {};
- # const message = new ConsoleMessage(type, textTokens.join(' '), args, location);
- # this.emit(PageEmittedEvents::Console, message);
- # }
+ private def add_console_message(type, args, stack_trace)
+ text_tokens = args.map { |arg| arg.remote_object.value }
+ call_frame = stack_trace['callFrames']&.first
+ location =
+ if call_frame
+ Puppeteer::ConsoleMessage::Location.new(
+ url: call_frame['url'],
+ line_number: call_frame['lineNumber'],
+ column_number: call_frame['columnNumber'],
+ )
+ else
+ nil
+ end
+ console_message = Puppeteer::ConsoleMessage.new(type, text_tokens.join(' '), args, location)
+ emit_event(PageEmittedEvents::Console, console_message)
+ end
+
private def handle_dialog_opening(event)
dialog_type = event['type']
unless %w(alert confirm prompt beforeunload).include?(dialog_type)
raise ArgumentError.new("Unknown javascript dialog type: #{dialog_type}")
end
@@ -864,17 +841,44 @@
main_frame.evaluate(page_function, *args)
end
define_async_method :async_evaluate
- # /**
- # * @param {Function|string} pageFunction
- # * @param {!Array<*>} args
- # */
- # async evaluateOnNewDocument(pageFunction, ...args) {
- # const source = helper.evaluationString(pageFunction, ...args);
- # await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source });
- # }
+ class JavaScriptFunction
+ def initialize(expression, args)
+ @expression = expression
+ @args = args
+ end
+
+ def source
+ "(#{@expression})(#{arguments})"
+ end
+
+ private def arguments
+ @args.map { |arg| arg.nil? ? nil : JSON.dump(arg) }.join(", ")
+ end
+ end
+
+ class JavaScriptExpression
+ def initialize(expression)
+ @expression = expression
+ end
+
+ def source
+ @expression
+ end
+ end
+
+ def evaluate_on_new_document(page_function, *args)
+ source =
+ if ['=>', 'async', 'function'].any? { |keyword| page_function.include?(keyword) }
+ JavaScriptFunction.new(page_function, args).source
+ else
+ JavaScriptExpression.new(page_function).source
+ end
+
+ @client.send_message('Page.addScriptToEvaluateOnNewDocument', source: source)
+ end
# @param {boolean} enabled
def cache_enabled=(enabled)
@frame_manager.network_manager.cache_enabled = enabled
end