Class: Puppeteer::Bidi::JSHandle

Inherits:
Object
  • Object
show all
Defined in:
lib/puppeteer/bidi/js_handle.rb,
sig/puppeteer/bidi/js_handle.rbs

Overview

JSHandle represents a reference to a JavaScript object Based on Puppeteer's BidiJSHandle implementation

Direct Known Subclasses

ElementHandle

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(realm, remote_value) ⇒ JSHandle

Returns a new instance of JSHandle.

Parameters:

  • realm (Core::Realm)
  • remote_value (Hash[String, untyped])


14
15
16
17
18
# File 'lib/puppeteer/bidi/js_handle.rb', line 14

def initialize(realm, remote_value)
  @realm = realm
  @remote_value = remote_value
  @disposed = false
end

Instance Attribute Details

#realmCore::Realm (readonly)

: Core::Realm

Returns:



9
10
11
# File 'lib/puppeteer/bidi/js_handle.rb', line 9

def realm
  @realm
end

Class Method Details

.from(remote_value, realm) ⇒ JSHandle, ElementHandle

Factory method to create JSHandle from remote value

Parameters:

  • remote_value (Hash[String, untyped])
  • realm (Core::Realm)

Returns:



24
25
26
27
28
29
30
# File 'lib/puppeteer/bidi/js_handle.rb', line 24

def self.from(remote_value, realm)
  if remote_value['type'] == 'node'
    ElementHandle.new(realm, remote_value)
  else
    new(realm, remote_value)
  end
end

Instance Method Details

#as_elementElementHandle?

Convert to ElementHandle if this is an element

Returns:



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/puppeteer/bidi/js_handle.rb', line 164

def as_element
  return nil unless @remote_value['type'] == 'node'

  # Check if it's an element node (nodeType 1) or text node (nodeType 3)
  result = @realm.call_function(
    '(node) => node.nodeType',
    false,
    arguments: [@remote_value]
  ).wait

  return nil if result['type'] == 'exception'

  node_type = result['result']['value']

  # 1 = ELEMENT_NODE, 3 = TEXT_NODE
  if node_type == 1 || node_type == 3
    ElementHandle.new(@realm, @remote_value)
  else
    nil
  end
end

#assert_not_disposedvoid

This method returns an undefined value.

Check if this handle has been disposed and raise error if so



215
216
217
# File 'lib/puppeteer/bidi/js_handle.rb', line 215

def assert_not_disposed
  raise JSHandleDisposedError if @disposed
end

#disposevoid

This method returns an undefined value.

Dispose this handle by releasing the remote object



52
53
54
55
56
57
58
59
60
# File 'lib/puppeteer/bidi/js_handle.rb', line 52

def dispose
  return if @disposed

  @disposed = true

  # Release the remote reference if it has a handle
  handle_id = id
  @realm.disown([handle_id]).wait if handle_id
end

#disposed?Boolean

Check if handle has been disposed

Returns:

  • (Boolean)


46
47
48
# File 'lib/puppeteer/bidi/js_handle.rb', line 46

def disposed?
  @disposed
end

#evaluate(script, *args) ⇒ Object

Evaluate JavaScript function with this handle as the first argument

Parameters:

  • script (String)
  • args (Object)

Returns:

  • (Object)


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/puppeteer/bidi/js_handle.rb', line 72

def evaluate(script, *args)
  assert_not_disposed

  # Prepend this handle as first argument
  all_args = [@remote_value] + args.map { |arg| Serializer.serialize(arg) }

  result = @realm.call_function(script, true, arguments: all_args).wait

  # Check for exceptions
  if result['type'] == 'exception'
    handle_evaluation_exception(result)
  end

  # Deserialize result
  Deserializer.deserialize(result['result'])
end

#evaluate_handle(script, *args) ⇒ JSHandle

Evaluate JavaScript function and return a handle to the result

Parameters:

  • script (String)
  • args (Object)

Returns:



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/puppeteer/bidi/js_handle.rb', line 93

def evaluate_handle(script, *args)
  assert_not_disposed

  # Prepend this handle as first argument
  all_args = [@remote_value] + args.map { |arg| Serializer.serialize(arg) }

  # Puppeteer passes awaitPromise: true to wait for promises to resolve
  result = @realm.call_function(script, true, arguments: all_args).wait

  # Check for exceptions
  if result['type'] == 'exception'
    handle_evaluation_exception(result)
  end

  # Return handle (don't deserialize)
  JSHandle.from(result['result'], @realm)
end

#get_propertiesHash[String, JSHandle]

Get all properties of the object

Returns:



137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/puppeteer/bidi/js_handle.rb', line 137

def get_properties
  assert_not_disposed

  property_names = evaluate('(object) => Object.keys(object ?? {})')
  return {} unless property_names.is_a?(Array)

  handles = AsyncUtils.await_promise_all(
    *property_names.map do |property_name|
      -> { get_property(property_name) }
    end
  )

  property_names.zip(handles).to_h
end

#get_property(property_name) ⇒ JSHandle

Get a property of the object

Parameters:

  • property_name (String)

Returns:



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/puppeteer/bidi/js_handle.rb', line 114

def get_property(property_name)
  assert_not_disposed

  result = @realm.call_function(
    '(object, property) => object[property]',
    false,
    arguments: [
      @remote_value,
      Serializer.serialize(property_name)
    ]
  ).wait

  if result['type'] == 'exception'
    exception_details = result['exceptionDetails']
    text = exception_details['text'] || 'Evaluation failed'
    raise text
  end

  JSHandle.from(result['result'], @realm)
end

#handle_evaluation_exception(result) ⇒ void

This method returns an undefined value.

Handle evaluation exceptions

Parameters:

  • result (Hash[String, untyped])


222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/puppeteer/bidi/js_handle.rb', line 222

def handle_evaluation_exception(result)
  exception_details = result['exceptionDetails']
  return unless exception_details

  text = exception_details['text'] || 'Evaluation failed'
  exception = exception_details['exception']

  error_message = text

  if exception && exception['type'] == 'object' && !exception.key?('value')
    error_message = text
  elsif exception && exception['type'] != 'error'
    thrown_value = Deserializer.deserialize(exception)
    error_message = "Evaluation failed: #{thrown_value}"
  end

  raise error_message
end

#idString?

Get the handle ID (handle or sharedId)

Returns:

  • (String, nil)


64
65
66
# File 'lib/puppeteer/bidi/js_handle.rb', line 64

def id
  @remote_value['handle'] || @remote_value['sharedId']
end

#json_valueObject

Convert this handle to a JSON-serializable value

Returns:

  • (Object)


154
155
156
157
158
159
160
# File 'lib/puppeteer/bidi/js_handle.rb', line 154

def json_value
  assert_not_disposed

  # Use evaluate with identity function, just like Puppeteer does
  # This leverages BiDi's built-in serialization with returnByValue: true
  evaluate('(value) => value')
end

#primitive_value?Boolean

Check if this is a primitive value

Returns:

  • (Boolean)


188
189
190
191
# File 'lib/puppeteer/bidi/js_handle.rb', line 188

def primitive_value?
  type = @remote_value['type']
  %w[string number bigint boolean undefined null].include?(type)
end

#remote_objectHash[String, untyped]

Get the remote object (alias for remote_value)

Returns:

  • (Hash[String, untyped])


40
41
42
# File 'lib/puppeteer/bidi/js_handle.rb', line 40

def remote_object
  @remote_value
end

#remote_valueHash[String, untyped]

Get the remote value (BiDi Script.RemoteValue)

Returns:

  • (Hash[String, untyped])


34
35
36
# File 'lib/puppeteer/bidi/js_handle.rb', line 34

def remote_value
  @remote_value
end

#to_sString

String representation of this handle

Returns:

  • (String)


195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/puppeteer/bidi/js_handle.rb', line 195

def to_s
  return 'JSHandle@disposed' if @disposed

  if primitive_value?
    value = Deserializer.deserialize(@remote_value)
    # For strings, don't use inspect (no quotes)
    if value.is_a?(String)
      "JSHandle:#{value}"
    else
      "JSHandle:#{value.inspect}"
    end
  else
    "JSHandle@#{@remote_value['type']}"
  end
end