-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
Background: Working with an ancient hardware embedded web ui (circa 2012) which uses the prototypejs framework.
Playwright version
npx playwright --version
Version 1.31.2
Test case (happy path)
npx playwright codegen http://127.0.0.1:
<!DOCTYPE html>
<html>
<head></head>
<body>
<form>
Name <input type="text" name="name" />
<input type="submit" />
</form>
</body>
</html>
Produces the following events:
What I'm doing is clicking the <input type="text" name="name" /> and typing the word 'test' into that form control.
This is working as expected:
serializedArgs is type object
[{"o":[{"k":"name","v":"click"},{"k":"selector","v":"internal:role=textbox"},{"k":"position","v":{"v":"undefined"}},{"k":"signals","v":{"a":[],"id":2}},{"k":"button","v":"left"},{"k":"modifiers","v":0},{"k":"clickCount","v":1}],"id":1}]
args
args is type object
[
{
name: 'click',
selector: 'internal:role=textbox',
position: undefined,
signals: [],
button: 'left',
modifiers: 0,
clickCount: 1
}
]
ok
serializedArgs
serializedArgs is type object
[]
args
args is type object
[]
ok
serializedArgs
serializedArgs is type object
[]
args
args is type object
[]
ok
serializedArgs
serializedArgs is type object
[{"o":[{"k":"name","v":"fill"},{"k":"selector","v":"internal:role=textbox"},{"k":"signals","v":{"a":[],"id":2}},{"k":"text","v":"t"}],"id":1}]
args
args is type object
[
{
name: 'fill',
selector: 'internal:role=textbox',
signals: [],
text: 't'
}
]
ok
serializedArgs
serializedArgs is type object
[{"o":[{"k":"name","v":"fill"},{"k":"selector","v":"internal:role=textbox"},{"k":"signals","v":{"a":[],"id":2}},{"k":"text","v":"te"}],"id":1}]
args
args is type object
[
{
name: 'fill',
selector: 'internal:role=textbox',
signals: [],
text: 'te'
}
]
ok
serializedArgs
serializedArgs is type object
[{"o":[{"k":"name","v":"fill"},{"k":"selector","v":"internal:role=textbox"},{"k":"signals","v":{"a":[],"id":2}},{"k":"text","v":"tes"}],"id":1}]
args
args is type object
[
{
name: 'fill',
selector: 'internal:role=textbox',
signals: [],
text: 'tes'
}
]
ok
serializedArgs
serializedArgs is type object
[{"o":[{"k":"name","v":"fill"},{"k":"selector","v":"internal:role=textbox"},{"k":"signals","v":{"a":[],"id":2}},{"k":"text","v":"test"}],"id":1}]
args
args is type object
[
{
name: 'fill',
selector: 'internal:role=textbox',
signals: [],
text: 'test'
}
]
ok
serializedArgs
serializedArgs is type object
[]
args
args is type object
[]
ok
Sad path with prototypejs: serializedArgs can be of type string (should be object)
Please note I have not pasted in the prototypejs application, apologies.
When clicking or entering (any event) playwright page.js throws the following, because for some reason (quirks mode type thing? I don't know) causes serializedArgs to be of string type:
Uncaught (in promise) TypeError: serializedArgs.map is not a function
at Function.dispatch node_modules/playwright-core/lib/server/page.js:609:37)
at Page._onBindingCalled (node_modules/playwright-core/lib/server/page.js:218:23)
at FrameSession._onBindingCalled (node_modules/playwright-core/lib/server/chromium/crPage.js:717:37)
Event log: Here I also type the word test but into a different (much older) prototype application embeded in hardware:
Notice that
serializedArgsis a string but should be an object.
npx playwright codegen http://192.168.1.1:
serializedArgs
serializedArgs is type string
"[]"
[]
ok
serializedArgs
serializedArgs is type string
"[{\"o\": [{\"k\": \"name\", \"v\": \"click\"}, {\"k\": \"selector\", \"v\": \"#user\"}, {\"k\": \"position\", \"v\": {\"v\": \"undefined\"}}, {\"k\": \"signals\", \"v\": {\"a\": [], \"id\": 2}}, {\"k\": \"button\", \"v\": \"left\"}, {\"k\": \"modifiers\", \"v\": 0}, {\"k\": \"clickCount\", \"v\": 1}], \"id\": 1}]"
[{"o": [{"k": "name", "v": "click"}, {"k": "selector", "v": "#user"}, {"k": "position", "v": {"v": "undefined"}}, {"k": "signals", "v": {"a": [], "id": 2}}, {"k": "button", "v": "left"}, {"k": "modifiers", "v": 0}, {"k": "clickCount", "v": 1}], "id": 1}]
ok
serializedArgs
serializedArgs is type string
"[]"
[]
ok
serializedArgs
serializedArgs is type string
"[{\"o\": [{\"k\": \"name\", \"v\": \"fill\"}, {\"k\": \"selector\", \"v\": \"#user\"}, {\"k\": \"signals\", \"v\": {\"a\": [], \"id\": 2}}, {\"k\": \"text\", \"v\": \"t\"}], \"id\": 1}]"
[{"o": [{"k": "name", "v": "fill"}, {"k": "selector", "v": "#user"}, {"k": "signals", "v": {"a": [], "id": 2}}, {"k": "text", "v": "t"}], "id": 1}]
ok
serializedArgs
serializedArgs is type string
"[{\"o\": [{\"k\": \"name\", \"v\": \"fill\"}, {\"k\": \"selector\", \"v\": \"#user\"}, {\"k\": \"signals\", \"v\": {\"a\": [], \"id\": 2}}, {\"k\": \"text\", \"v\": \"te\"}], \"id\": 1}]"
[{"o": [{"k": "name", "v": "fill"}, {"k": "selector", "v": "#user"}, {"k": "signals", "v": {"a": [], "id": 2}}, {"k": "text", "v": "te"}], "id": 1}]
ok
serializedArgs
serializedArgs is type string
"[]"
[]
ok
serializedArgs
serializedArgs is type string
"[{\"o\": [{\"k\": \"name\", \"v\": \"fill\"}, {\"k\": \"selector\", \"v\": \"#user\"}, {\"k\": \"signals\", \"v\": {\"a\": [], \"id\": 2}}, {\"k\": \"text\", \"v\": \"tes\"}], \"id\": 1}]"
[{"o": [{"k": "name", "v": "fill"}, {"k": "selector", "v": "#user"}, {"k": "signals", "v": {"a": [], "id": 2}}, {"k": "text", "v": "tes"}], "id": 1}]
ok
serializedArgs
serializedArgs is type string
"[{\"o\": [{\"k\": \"name\", \"v\": \"fill\"}, {\"k\": \"selector\", \"v\": \"#user\"}, {\"k\": \"signals\", \"v\": {\"a\": [], \"id\": 2}}, {\"k\": \"text\", \"v\": \"test\"}], \"id\": 1}]"
[{"o": [{"k": "name", "v": "fill"}, {"k": "selector", "v": "#user"}, {"k": "signals", "v": {"a": [], "id": 2}}, {"k": "text", "v": "test"}], "id": 1}]
ok
serializedArgs
serializedArgs is type string
The crude 'fix' in playwright-core/lib/server/page.js
tldr JSON.parse serializedArgs to an object. (but why has serializedArgs become a string?).
- change
serializedArgsfromconstto mutable serializedArgs = JSON.parse(serializedArgs);to an object
static async dispatch(page, payload, context) {
let {
name,
seq,
serializedArgs
} = JSON.parse(payload);
try {
(0, _utils.assert)(context.world);
const binding = page.getBinding(name);
let result;
if (binding.needsHandle) {
const handle = await context.evaluateHandle(takeHandle, {
name,
seq
}).catch(e => null);
result = await binding.playwrightFunction({
frame: context.frame,
page,
context: page._browserContext
}, handle);
} else {
console.log("ok");
console.log("serializedArgs");
console.log("serializedArgs is type", typeof(serializedArgs));
console.log(JSON.stringify(serializedArgs));
if ( typeof(serializedArgs) === 'string' ) {
console.log("Converting serializedArgs into an object")
try {
serializedArgs = JSON.parse(serializedArgs);
console.log(serializedArgs);
} catch (e) {
console.error("Unable to parse serializedArgs:", e);
}
console.log(serializedArgs);
}
debugger;
I hope that helps, appreciate this is a very niche usecase however took me a long time to root cause so someone else may benefit if they're hitting this
- are we hitting some background compatibility /pollyfills perhaps?
- I've not been able to identify why / when
serializedArgsgets stringified
p.s. I would appreciate if someone would direct me how to use debugger; & --inspect --debug-brk within the context of playwright codegen it would save a lot of time.