Skip to content

Commit 5028b24

Browse files
[JS][BiDi] Add Script module commands and types (SeleniumHQ#11847)
* [js][bidi] Script Module completed with Tests. * [js][bidi] Code cleanup. * [js][bidi] Comment and clean up. * fix: Changed findByName logic and other minor fixes --------- Co-authored-by: Sri Harsha <12621691+harsha509@users.noreply.github.com>
1 parent 601b54a commit 5028b24

File tree

9 files changed

+1835
-0
lines changed

9 files changed

+1835
-0
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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 { LocalValue } = require('./protocolValue')
19+
class ArgumentValue {
20+
constructor(value) {
21+
this.value = value
22+
}
23+
24+
asMap() {
25+
if (this.value instanceof LocalValue) {
26+
return this.value.toJson()
27+
} else {
28+
// ReferenceValue
29+
return this.value.asMap()
30+
}
31+
}
32+
}
33+
34+
module.exports = { ArgumentValue }
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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 EvaluateResultType = {
19+
SUCCESS: 'success',
20+
EXCEPTION: 'exception',
21+
}
22+
23+
class EvaluateResultSuccess {
24+
constructor(realmId, value) {
25+
this.resultType = EvaluateResultType.SUCCESS
26+
this.realmId = realmId
27+
this.result = value
28+
}
29+
}
30+
31+
class EvaluateResultException {
32+
constructor(realmId, exceptionDetails) {
33+
this.resultType = EvaluateResultType.EXCEPTION
34+
this.realmId = realmId
35+
this.exceptionDetails = exceptionDetails
36+
}
37+
}
38+
39+
class ExceptionDetails {
40+
constructor(exceptionDetails) {
41+
this.columnNumber =
42+
'columnNumber' in exceptionDetails
43+
? exceptionDetails['columnNumber']
44+
: null
45+
this.exception =
46+
'exception' in exceptionDetails ? exceptionDetails['exception'] : null
47+
this.lineNumber =
48+
'lineNumber' in exceptionDetails ? exceptionDetails['lineNumber'] : null
49+
this.stackTrace =
50+
'stackTrace' in exceptionDetails ? exceptionDetails['stackTrace'] : null
51+
this.text = 'text' in exceptionDetails ? exceptionDetails['text'] : null
52+
}
53+
}
54+
55+
module.exports = {
56+
EvaluateResultType,
57+
EvaluateResultSuccess,
58+
EvaluateResultException,
59+
ExceptionDetails,
60+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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 = {
19+
UNDEFINED: 'undefined',
20+
NULL: 'null',
21+
STRING: 'string',
22+
NUMBER: 'number',
23+
SPECIAL_NUMBER: 'number',
24+
BOOLEAN: 'boolean',
25+
BIGINT: 'bigint',
26+
27+
findByName(name) {
28+
return (
29+
Object.values(this).find((type) => {
30+
return (
31+
typeof type === 'string' && name.toLowerCase() === type.toLowerCase()
32+
)
33+
}) || null
34+
)
35+
},
36+
}
37+
38+
const NonPrimitiveType = {
39+
ARRAY: 'array',
40+
DATE: 'date',
41+
MAP: 'map',
42+
OBJECT: 'object',
43+
REGULAR_EXPRESSION: 'regexp',
44+
SET: 'set',
45+
46+
findByName(name) {
47+
return (
48+
Object.values(this).find((type) => {
49+
return (
50+
typeof type === 'string' && name.toLowerCase() === type.toLowerCase()
51+
)
52+
}) || null
53+
)
54+
},
55+
}
56+
57+
const RemoteType = {
58+
SYMBOL: 'symbol',
59+
FUNCTION: 'function',
60+
WEAK_MAP: 'weakmap',
61+
WEAK_SET: 'weakset',
62+
ITERATOR: 'iterator',
63+
GENERATOR: 'generator',
64+
ERROR: 'error',
65+
PROXY: 'proxy',
66+
PROMISE: 'promise',
67+
TYPED_ARRAY: 'typedarray',
68+
ARRAY_BUFFER: 'arraybuffer',
69+
NODE_LIST: 'nodelist',
70+
HTML_COLLECTION: 'htmlcollection',
71+
NODE: 'node',
72+
WINDOW: 'window',
73+
74+
findByName(name) {
75+
return (
76+
Object.values(this).find((type) => {
77+
return (
78+
typeof type === 'string' && name.toLowerCase() === type.toLowerCase()
79+
)
80+
}) || null
81+
)
82+
},
83+
}
84+
85+
const SpecialNumberType = {
86+
NAN: 'NaN',
87+
MINUS_ZERO: '-0',
88+
INFINITY: 'Infinity',
89+
MINUS_INFINITY: '-Infinity',
90+
}
91+
92+
module.exports = {
93+
PrimitiveType,
94+
NonPrimitiveType,
95+
RemoteType,
96+
SpecialNumberType,
97+
}
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
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 {
19+
PrimitiveType,
20+
NonPrimitiveType,
21+
RemoteType,
22+
} = require('./protocolType')
23+
24+
const TYPE_CONSTANT = 'type'
25+
const VALUE_CONSTANT = 'value'
26+
const RemoteReferenceType = {
27+
HANDLE: 'handle',
28+
SHARED_ID: 'shareId',
29+
}
30+
31+
class LocalValue {
32+
constructor(type, value = null) {
33+
if (type === PrimitiveType.UNDEFINED || type === PrimitiveType.NULL) {
34+
this.type = type
35+
} else {
36+
this.type = type
37+
this.value = value
38+
}
39+
}
40+
41+
static createStringValue(value) {
42+
return new LocalValue(PrimitiveType.STRING, value)
43+
}
44+
45+
static createNumberValue(value) {
46+
return new LocalValue(PrimitiveType.NUMBER, value)
47+
}
48+
49+
static createSpecialNumberValue(value) {
50+
return new LocalValue(PrimitiveType.SPECIAL_NUMBER, value)
51+
}
52+
53+
static createUndefinedValue() {
54+
return new LocalValue(PrimitiveType.UNDEFINED)
55+
}
56+
57+
static createNullValue() {
58+
return new LocalValue(PrimitiveType.NULL)
59+
}
60+
61+
static createBooleanValue(value) {
62+
return new LocalValue(PrimitiveType.BOOLEAN, value)
63+
}
64+
65+
static createBigIntValue(value) {
66+
return new LocalValue(PrimitiveType.BIGINT, value)
67+
}
68+
69+
static createArrayValue(value) {
70+
return new LocalValue(NonPrimitiveType.ARRAY, value)
71+
}
72+
73+
static createDateValue(value) {
74+
return new LocalValue(NonPrimitiveType.DATE, value)
75+
}
76+
77+
static createMapValue(map) {
78+
let value = []
79+
Object.entries(map).forEach((entry) => {
80+
value.push(entry)
81+
})
82+
return new LocalValue(NonPrimitiveType.MAP, value)
83+
}
84+
85+
static createObjectValue(map) {
86+
let value = []
87+
Object.entries(map).forEach((entry) => {
88+
value.push(entry)
89+
})
90+
return new LocalValue(NonPrimitiveType.OBJECT, value)
91+
}
92+
93+
static createRegularExpressionValue(value) {
94+
return new LocalValue(NonPrimitiveType.REGULAR_EXPRESSION, value)
95+
}
96+
97+
static createSetValue(value) {
98+
return new LocalValue(NonPrimitiveType.SET, value)
99+
}
100+
101+
toJson() {
102+
let toReturn = {}
103+
toReturn[TYPE_CONSTANT] = this.type
104+
105+
if (
106+
!(
107+
this.type === PrimitiveType.NULL ||
108+
this.type === PrimitiveType.UNDEFINED
109+
)
110+
) {
111+
toReturn[VALUE_CONSTANT] = this.value
112+
}
113+
return toReturn
114+
}
115+
}
116+
117+
class RemoteValue {
118+
constructor(remoteValue) {
119+
this.type = null
120+
this.handle = null
121+
this.internalId = null
122+
this.value = null
123+
this.sharedId = null
124+
125+
if ('type' in remoteValue) {
126+
var typeString = remoteValue['type']
127+
if (PrimitiveType.findByName(typeString) != null) {
128+
this.type = PrimitiveType.findByName(typeString)
129+
} else if (NonPrimitiveType.findByName(typeString) != null) {
130+
this.type = NonPrimitiveType.findByName(typeString)
131+
} else {
132+
this.type = RemoteType.findByName(typeString)
133+
}
134+
}
135+
136+
if ('handle' in remoteValue) {
137+
this.handle = remoteValue['handle']
138+
}
139+
140+
if ('internalId' in remoteValue) {
141+
this.internalId = remoteValue['internalId']
142+
}
143+
144+
if ('value' in remoteValue) {
145+
this.value = remoteValue['value']
146+
}
147+
148+
if ('sharedId' in remoteValue) {
149+
this.sharedId = remoteValue['sharedId']
150+
}
151+
152+
if (this.value != null) {
153+
this.value = this.deserializeValue(this.value, this.type)
154+
}
155+
}
156+
157+
deserializeValue(value, type) {
158+
if ([NonPrimitiveType.MAP, NonPrimitiveType.OBJECT].includes(type)) {
159+
return Object.fromEntries(value)
160+
} else if (type === NonPrimitiveType.REGULAR_EXPRESSION) {
161+
return new RegExpValue(value.pattern, value.flags)
162+
}
163+
return value
164+
}
165+
}
166+
167+
class ReferenceValue {
168+
constructor(handle, shareId) {
169+
if (handle === RemoteReferenceType.HANDLE) {
170+
this.handle = shareId
171+
} else {
172+
this.handle = handle
173+
this.shareId = shareId
174+
}
175+
}
176+
177+
asMap() {
178+
const toReturn = {}
179+
if (this.handle != null) {
180+
toReturn[RemoteReferenceType.HANDLE] = this.handle
181+
}
182+
183+
if (this.shareId != null) {
184+
toReturn[RemoteReferenceType.SHARED_ID] = this.shareId
185+
}
186+
187+
return toReturn
188+
}
189+
}
190+
191+
class RegExpValue {
192+
constructor(pattern, flags = null) {
193+
this.pattern = pattern
194+
this.flags = flags
195+
}
196+
}
197+
198+
module.exports = {
199+
LocalValue,
200+
RemoteValue,
201+
ReferenceValue,
202+
RemoteReferenceType,
203+
RegExpValue,
204+
}

0 commit comments

Comments
 (0)