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