Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/javascript/selenium-webdriver/bidi/protocolValue.js
2884 views
1
// Licensed to the Software Freedom Conservancy (SFC) under one
2
// or more contributor license agreements. See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership. The SFC licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License. You may obtain a copy of the License at
8
//
9
// http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied. See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
const { PrimitiveType, NonPrimitiveType, RemoteType, SpecialNumberType } = require('./protocolType')
19
20
const TYPE_CONSTANT = 'type'
21
const VALUE_CONSTANT = 'value'
22
/**
23
* Represents the types of remote reference.
24
* @enum {string}
25
*/
26
const RemoteReferenceType = {
27
HANDLE: 'handle',
28
SHARED_ID: 'sharedId',
29
}
30
31
/**
32
* Represents a local value with a specified type and optional value.
33
* @class
34
* Described in https://w3c.github.io/webdriver-bidi/#type-script-LocalValue
35
*/
36
class LocalValue {
37
constructor(type, value = null) {
38
if (type === PrimitiveType.UNDEFINED || type === PrimitiveType.NULL) {
39
this.type = type
40
} else {
41
this.type = type
42
this.value = value
43
}
44
}
45
46
/**
47
* Creates a new LocalValue object with a string value.
48
*
49
* @param {string} value - The string value to be stored in the LocalValue object.
50
* @returns {LocalValue} - The created LocalValue object.
51
*/
52
static createStringValue(value) {
53
return new LocalValue(PrimitiveType.STRING, value)
54
}
55
56
/**
57
* Creates a new LocalValue object with a number value.
58
*
59
* @param {number} value - The number value.
60
* @returns {LocalValue} - The created LocalValue object.
61
*/
62
static createNumberValue(value) {
63
return new LocalValue(PrimitiveType.NUMBER, value)
64
}
65
66
/**
67
* Creates a new LocalValue object with a special number value.
68
*
69
* @param {number} value - The value of the special number.
70
* @returns {LocalValue} - The created LocalValue object.
71
*/
72
static createSpecialNumberValue(value) {
73
return new LocalValue(PrimitiveType.SPECIAL_NUMBER, value)
74
}
75
76
/**
77
* Creates a new LocalValue object with an undefined value.
78
* @returns {LocalValue} - The created LocalValue object.
79
*/
80
static createUndefinedValue() {
81
return new LocalValue(PrimitiveType.UNDEFINED)
82
}
83
84
/**
85
* Creates a new LocalValue object with a null value.
86
* @returns {LocalValue} - The created LocalValue object.
87
*/
88
static createNullValue() {
89
return new LocalValue(PrimitiveType.NULL)
90
}
91
92
/**
93
* Creates a new LocalValue object with a boolean value.
94
*
95
* @param {boolean} value - The boolean value.
96
* @returns {LocalValue} - The created LocalValue object.
97
*/
98
static createBooleanValue(value) {
99
return new LocalValue(PrimitiveType.BOOLEAN, value)
100
}
101
102
/**
103
* Creates a new LocalValue object with a BigInt value.
104
*
105
* @param {BigInt} value - The BigInt value.
106
* @returns {LocalValue} - The created LocalValue object.
107
*/
108
static createBigIntValue(value) {
109
return new LocalValue(PrimitiveType.BIGINT, value)
110
}
111
112
/**
113
* Creates a new LocalValue object with an array.
114
*
115
* @param {Array} value - The array.
116
* @returns {LocalValue} - The created LocalValue object.
117
*/
118
static createArrayValue(value) {
119
return new LocalValue(NonPrimitiveType.ARRAY, value)
120
}
121
122
/**
123
* Creates a new LocalValue object with date value.
124
*
125
* @param {string} value - The date.
126
* @returns {LocalValue} - The created LocalValue object.
127
*/
128
static createDateValue(value) {
129
return new LocalValue(NonPrimitiveType.DATE, value)
130
}
131
132
/**
133
* Creates a new LocalValue object of map value.
134
* @param {Map} map - The map.
135
* @returns {LocalValue} - The created LocalValue object.
136
*/
137
static createMapValue(map) {
138
let value = []
139
Object.entries(map).forEach((entry) => {
140
value.push(entry)
141
})
142
return new LocalValue(NonPrimitiveType.MAP, value)
143
}
144
145
/**
146
* Creates a new LocalValue object from the passed object.
147
*
148
* @param {Object} object - The object.
149
* @returns {LocalValue} - The created LocalValue object.
150
*/
151
static createObjectValue(object) {
152
let value = []
153
Object.entries(object).forEach((entry) => {
154
value.push(entry)
155
})
156
return new LocalValue(NonPrimitiveType.OBJECT, value)
157
}
158
159
/**
160
* Creates a new LocalValue object of regular expression value.
161
*
162
* @param {string} value - The value of the regular expression.
163
* @returns {LocalValue} - The created LocalValue object.
164
*/
165
static createRegularExpressionValue(value) {
166
return new LocalValue(NonPrimitiveType.REGULAR_EXPRESSION, value)
167
}
168
169
/**
170
* Creates a new LocalValue object with the specified value.
171
* @param {Set} value - The value to be set.
172
* @returns {LocalValue} - The created LocalValue object.
173
*/
174
static createSetValue(value) {
175
return new LocalValue(NonPrimitiveType.SET, value)
176
}
177
178
/**
179
* Creates a new LocalValue object with the given channel value
180
*
181
* @param {ChannelValue} value - The channel value.
182
* @returns {LocalValue} - The created LocalValue object.
183
*/
184
static createChannelValue(value) {
185
return new LocalValue(NonPrimitiveType.CHANNEL, value)
186
}
187
188
static createReferenceValue(handle, sharedId) {
189
return new ReferenceValue(handle, sharedId)
190
}
191
192
static getArgument(argument) {
193
let localValue = null
194
195
if (
196
argument === SpecialNumberType.NAN ||
197
argument === SpecialNumberType.MINUS_ZERO ||
198
argument === SpecialNumberType.INFINITY ||
199
argument === SpecialNumberType.MINUS_INFINITY
200
) {
201
localValue = LocalValue.createSpecialNumberValue(argument)
202
return localValue
203
}
204
205
const type = typeof argument
206
207
switch (type) {
208
case PrimitiveType.STRING:
209
localValue = LocalValue.createStringValue(argument)
210
break
211
case PrimitiveType.NUMBER:
212
localValue = LocalValue.createNumberValue(argument)
213
break
214
case PrimitiveType.BOOLEAN:
215
localValue = LocalValue.createBooleanValue(argument)
216
break
217
case PrimitiveType.BIGINT:
218
localValue = LocalValue.createBigIntValue(argument.toString())
219
break
220
case PrimitiveType.UNDEFINED:
221
localValue = LocalValue.createUndefinedValue()
222
break
223
case NonPrimitiveType.OBJECT:
224
if (argument === null) {
225
localValue = LocalValue.createNullValue()
226
break
227
}
228
if (argument instanceof Date) {
229
localValue = LocalValue.createDateValue(argument)
230
} else if (argument instanceof Map) {
231
const map = []
232
233
argument.forEach((value, key) => {
234
let objectKey
235
if (typeof key === 'string') {
236
objectKey = key
237
} else {
238
objectKey = LocalValue.getArgument(key)
239
}
240
const objectValue = LocalValue.getArgument(value)
241
map.push([objectKey, objectValue])
242
})
243
localValue = new LocalValue(NonPrimitiveType.MAP, map)
244
} else if (argument instanceof Set) {
245
const set = []
246
argument.forEach((value) => {
247
set.push(LocalValue.getArgument(value))
248
})
249
localValue = LocalValue.createSetValue(set)
250
} else if (argument instanceof Array) {
251
const arr = []
252
argument.forEach((value) => {
253
arr.push(LocalValue.getArgument(value))
254
})
255
localValue = LocalValue.createArrayValue(arr)
256
} else if (argument instanceof RegExp) {
257
localValue = LocalValue.createRegularExpressionValue({
258
pattern: argument.source,
259
flags: argument.flags,
260
})
261
} else {
262
let value = []
263
Object.entries(argument).forEach((entry) => {
264
value.push([LocalValue.getArgument(entry[0]), LocalValue.getArgument(entry[1])])
265
})
266
localValue = new LocalValue(NonPrimitiveType.OBJECT, value)
267
}
268
break
269
}
270
271
return localValue
272
}
273
274
asMap() {
275
let toReturn = {}
276
toReturn[TYPE_CONSTANT] = this.type
277
278
if (!(this.type === PrimitiveType.NULL || this.type === PrimitiveType.UNDEFINED)) {
279
toReturn[VALUE_CONSTANT] = this.value
280
}
281
return toReturn
282
}
283
}
284
285
/**
286
* Represents a remote value.
287
* Described in https://w3c.github.io/webdriver-bidi/#type-script-RemoteValue.
288
* @class
289
*/
290
class RemoteValue {
291
constructor(remoteValue) {
292
this.type = null
293
this.handle = null
294
this.internalId = null
295
this.value = null
296
this.sharedId = null
297
298
if ('type' in remoteValue) {
299
const typeString = remoteValue['type']
300
if (PrimitiveType.findByName(typeString) != null) {
301
this.type = PrimitiveType.findByName(typeString)
302
} else if (NonPrimitiveType.findByName(typeString) != null) {
303
this.type = NonPrimitiveType.findByName(typeString)
304
} else {
305
this.type = RemoteType.findByName(typeString)
306
}
307
}
308
309
if ('handle' in remoteValue) {
310
this.handle = remoteValue['handle']
311
}
312
313
if ('internalId' in remoteValue) {
314
this.internalId = remoteValue['internalId']
315
}
316
317
if ('value' in remoteValue) {
318
this.value = remoteValue['value']
319
}
320
321
if ('sharedId' in remoteValue) {
322
this.sharedId = remoteValue['sharedId']
323
}
324
325
if (this.value != null) {
326
this.value = this.deserializeValue(this.value, this.type)
327
}
328
}
329
330
deserializeValue(value, type) {
331
if (type === NonPrimitiveType.OBJECT) {
332
return Object.fromEntries(value)
333
} else if (type === NonPrimitiveType.REGULAR_EXPRESSION) {
334
return new RegExpValue(value.pattern, value.flags)
335
}
336
return value
337
}
338
}
339
340
/**
341
* Represents a reference value in the protocol.
342
* Described in https://w3c.github.io/webdriver-bidi/#type-script-RemoteReference.
343
*/
344
class ReferenceValue {
345
#handle
346
#sharedId
347
348
/**
349
* Constructs a new ReferenceValue object.
350
* @param {string} handle - The handle value.
351
* @param {string} sharedId - The shared ID value.
352
*/
353
constructor(handle, sharedId) {
354
if (handle === RemoteReferenceType.HANDLE) {
355
this.#handle = sharedId
356
} else if (handle === RemoteReferenceType.SHARED_ID) {
357
this.#sharedId = sharedId
358
} else {
359
this.#handle = handle
360
this.#sharedId = sharedId
361
}
362
}
363
364
asMap() {
365
const toReturn = {}
366
if (this.#handle != null) {
367
toReturn[RemoteReferenceType.HANDLE] = this.#handle
368
}
369
370
if (this.#sharedId != null) {
371
toReturn[RemoteReferenceType.SHARED_ID] = this.#sharedId
372
}
373
374
return toReturn
375
}
376
}
377
378
/**
379
* Represents a regular expression value.
380
* Described in https://w3c.github.io/webdriver-bidi/#type-script-LocalValue.
381
*/
382
class RegExpValue {
383
/**
384
* Constructs a new RegExpValue object.
385
* @param {string} pattern - The pattern of the regular expression.
386
* @param {string|null} [flags=null] - The flags of the regular expression.
387
*/
388
constructor(pattern, flags = null) {
389
this.pattern = pattern
390
this.flags = flags
391
}
392
}
393
394
/**
395
* Represents serialization options.
396
* Described in https://w3c.github.io/webdriver-bidi/#type-script-SerializationOptions.
397
*/
398
class SerializationOptions {
399
/**
400
* Constructs a new instance of SerializationOptions.
401
* @param {number} [maxDomDepth=0] - The maximum depth to serialize the DOM.
402
* @param {number|null} [maxObjectDepth=null] - The maximum depth to serialize objects.
403
* @param {'none'|'open'|'all'} [includeShadowTree='none'] - The inclusion level of the shadow tree.
404
* @throws {Error} If the `includeShadowTree` value is not one of 'none', 'open', or 'all'.
405
*/
406
constructor(maxDomDepth = 0, maxObjectDepth = null, includeShadowTree = 'none') {
407
this._maxDomDepth = maxDomDepth
408
this._maxObjectDepth = maxObjectDepth
409
410
if (['none', 'open', 'all'].includes(includeShadowTree)) {
411
throw Error(`Valid types are 'none', 'open', and 'all'. Received: ${includeShadowTree}`)
412
}
413
this._includeShadowTree = includeShadowTree
414
}
415
}
416
417
/**
418
* Represents a channel value.
419
* Described in https://w3c.github.io/webdriver-bidi/#type-script-ChannelValue.
420
* @class
421
*/
422
class ChannelValue {
423
constructor(channel, options = undefined, resultOwnership = undefined) {
424
this.channel = channel
425
426
if (options !== undefined) {
427
if (options instanceof SerializationOptions) {
428
this.options = options
429
} else {
430
throw Error(`Pass in SerializationOptions object. Received: ${options} `)
431
}
432
}
433
434
if (resultOwnership !== undefined) {
435
if (['root', 'none'].includes(resultOwnership)) {
436
this.resultOwnership = resultOwnership
437
} else {
438
throw Error(`Valid types are 'root' and 'none. Received: ${resultOwnership}`)
439
}
440
}
441
}
442
}
443
444
module.exports = {
445
ChannelValue,
446
LocalValue,
447
RemoteValue,
448
ReferenceValue,
449
RemoteReferenceType,
450
RegExpValue,
451
SerializationOptions,
452
}
453
454