microsoft / microsoft/playwright-python

[Bug]: RegExp values are not serialized by evaluate(), and returned RegExps leak internal protocol JSON

未关闭
#3,188 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

主要语言
Python
星标
15k
派生
1.2k
平均合并
55 分钟
30 天内合并 PR
4

描述

Version

1.62.0

Steps to reproduce
import re
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()

    # 1. Passing a compiled pattern in
    print(page.evaluate("(v) => [typeof v, String(v)]", re.compile(r"a\d+", re.I)))

    # 2. Getting a RegExp back out
    print(page.evaluate("() => /a\\d+/gi"))

    # 3. Nested in a structure
    print(page.evaluate("() => ({x: [/foo/m]})"))

    browser.close()
Expected behavior
  1. ['object', '/a\\d+/i'], and the value is a real RegExp inside the page.
  2. re.compile('a\\d+', re.IGNORECASE)
  3. {'x': [re.compile('foo', re.MULTILINE)]}

This is what playwright-dotnet does today. EvaluateArgumentValueConverter.cs serializes Regex (line 138) and parses "r" back into a Regex (line 351).

Actual behavior
  1. ['undefined', 'undefined'], the argument is silently dropped
  2. {'r': {'p': 'a\\d+', 'f': 'gi'}}
  3. {'x': [{'r': {'p': 'foo', 'f': 'm'}}]}

Two separate problems, both silent:

  • serialize_value() in playwright/_impl/_js_handle.py has no branch for re.Pattern, so a compiled pattern falls through to {"v": "undefined"}.
  • parse_value() has no branch for "r", so it hits the bare return value at the end and hands back the raw wire format. There is no way to tell from the outside that this dict is not the actual result.

The protocol supports this in both directions and the driver already implements both sides ({r: {p, f}} on serialize, new RegExp(v.r.p, v.r.f) on parse), so this is only missing on the Python side.

Additional context

Happy to send a PR, I have one ready. The serialize direction can reuse the existing escape_regex_flags() in _str_utils.py, which already maps re.IGNORECASE|DOTALL|MULTILINE to i/s/m for locators and route matching. The parse direction needs the inverse.

Two things worth an opinion before I do:

  1. JavaScript flags with no re equivalent (g, y, d, u, v). I would drop them rather than raise, since /foo/g is very common and raising would be worse than today's behavior. Note that playwright-dotnet's FromInlineFlags throws on these, which looks like a separate bug over there.
  2. A JS pattern that is not valid Python re syntax, for example /(?<name>x)/ (Python spells it (?P<name>x)). With this change that would raise from re.compile instead of returning the dict. I think raising is acceptable since the dict was never usable anyway, but let me know if you would rather it degrade some other way.
Environment
- Operating System: macOS 26.3.1
- CPU: arm64
- Browser: Chromium
- Python Version: 3.14.0

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 playwright/_impl/_js_handle.py 开始,检查 serialize_value() 和 parse_value(),然后查看 _str_utils.py 中的 escape_regex_flags(),了解现有的 flag 处理。复现 issue 中的三个 evaluate() 用例,并为已编译的模式、返回的 JavaScript RegExps 和嵌套值添加覆盖。完成标准是 Python 正则表达式值能够正确序列化,并且返回的 JavaScript RegExps 会变成 re.Pattern 对象,而不是协议字典。

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
api
Issue 类型
缺陷
难度
3/5
预计耗时
1-2 天
活跃度
活跃
描述清晰度
描述清楚
新手友好度
72/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。