Web: TextField values set through the DOM (autofill-like) are lost; on_submit carries an empty value
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 48/100
Hướng nghiên cứu
Start by reproducing the issue with the supplied app.py and run_arms.py on Flet web, then trace how Flutter web semantics inputs sync DOM values back to TextField. Compare the autofill-like Locator.fill path with the working typed-input path, especially around Enter submission. Done means DOM-entered values reliably reach TextField.value and on_submit across the reported viewports.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Flet / flet-web: 1.0.5 (stock, no other code). Browser: Chromium headless shell (Playwright 1.64.1), macOS.
Mode: web (ft.run(main, port=8771), served to the browser).
App
One page: an email TextField, a password TextField(password=True) and a Button("Log In"). on_submit on both
fields and on_click on the button call one handler that prints the event's source, whether e.data is empty, and
whether each field's .value is empty (never the text). The full app.py and the Playwright script (run_arms.py) are below. Run: python app.py > server.log, then python run_arms.py 10 L1,L2 in the same directory.
Steps (n=10 per viewport, fresh browser context each run)
- Control, L1: click the email field, type the email; click the password field, type the password; press Enter.
- L2 (autofill-like): enable semantics by clicking
flt-semantics-placeholder(Flutter web builds no<input>
before that), then PlaywrightLocator.fillonflt-semantics input[type=text]andinput[type=password], with
no click on the fields; press Enter.
Result (60 runs, inputs found in 60/60)
| viewport | L1 OK | L2 OK | L2 value lost |
|---|---|---|---|
| 1280x800 | 10/10 | 3 | 7 |
| 390x844 (mobile, touch) | 10/10 | 6 | 4 |
| 844x390 (mobile, touch) | 10/10 | 3 | 7 |
In every one of the 18 lost runs the password <input>'s DOM value was already empty when Enter was pressed (read with
JS), and the server received one on_submit from the password field with e.data empty and both fields' .value
empty. Enter always produced an event (none of the 60 runs went without one). The loss looks time-dependent: early
runs mostly lost the values, later runs at 390x844 mostly kept them. It looks as if a later semantics/controller
resync overwrites values that the DOM received directly; we did not measure further.
Expected
A value placed in the field's <input> (as password managers and browser autofill do) is kept and reaches
TextField.value and on_submit's e.data.
Caveat
L2 enables semantics with a script click on the placeholder; a real autofill path may enable it differently.
app.py
import sys, time
import flet as ft
def main(page: ft.Page):
page.title = "Repro"
email = ft.TextField(label="Email", autofill_hints=[ft.AutofillHint.EMAIL])
password = ft.TextField(label="Password", password=True, can_reveal_password=False,
autofill_hints=[ft.AutofillHint.PASSWORD])
def handler(source):
def h(e):
data = getattr(e, "data", None)
ne = lambda v: "nonempty" if v else "empty"
print(f"EVENT source={source} data={ne(data)} email_value={ne(email.value)} "
f"password_value={ne(password.value)} t={time.monotonic():.3f}", flush=True)
return h
email.on_submit = handler("email")
password.on_submit = handler("password")
btn = ft.Button("Log In", on_click=handler("button"))
page.add(ft.Column([email, password, btn]))
print(f"SESSION_READY t={time.monotonic():.3f}", flush=True)
ft.run(main, view=None, port=8771)
run_arms.py
import json, time, os, sys
from playwright.sync_api import sync_playwright
HERE = os.path.dirname(os.path.abspath(__file__))
LOG = os.path.join(HERE, 'server.log')
URL = 'http://127.0.0.1:8771/'
VPS = [("1280x800", dict(viewport={'width':1280,'height':800})),
("390x844", dict(viewport={'width':390,'height':844}, is_mobile=True, has_touch=True)),
("844x390", dict(viewport={'width':844,'height':390}, is_mobile=True, has_touch=True))]
N = int(sys.argv[1]) if len(sys.argv) > 1 else 10
ARMS = sys.argv[2].split(',') if len(sys.argv) > 2 else ['L1', 'L2']
EMAIL = "[email protected]"; PW = "example-password-123" # dummy values
def loglines():
return open(LOG).read().splitlines()
def pw_state(pg):
return pg.evaluate("""()=>{const i=Array.from(document.querySelectorAll('input')).filter(e=>e.type==='password');
if(!i.length) return 'noinput'; return i.some(e=>e.value&&e.value.length>0)?'nonempty':'empty'}""")
def one(browser, vp, arm):
ctx = browser.new_context(**vp); pg = ctx.new_page()
n0 = len(loglines())
pg.goto(URL)
pg.wait_for_selector('flt-semantics-placeholder', state='attached', timeout=30000)
t = time.time()
while time.time()-t < 30 and not any(l.startswith('SESSION_READY') for l in loglines()[n0:]):
time.sleep(0.2)
time.sleep(1.0)
found = False; how = ''
if arm == 'L2':
pg.mouse.click(2, 2)
# semantics must be enabled to create DOM inputs; click on placeholder via JS (no field click)
pg.evaluate("document.querySelector('flt-semantics-placeholder')&&document.querySelector('flt-semantics-placeholder').click()")
how = 'mouse.click(2,2); placeholder.click() via JS to build semantics; fill on flt-semantics input[aria-label]'
try:
pg.wait_for_selector('flt-semantics input[type=password]', timeout=30000); found = True
except Exception: found = False
if found:
pg.locator('flt-semantics input[type=text]').first.fill(EMAIL)
pg.locator('flt-semantics input[type=password]').first.fill(PW)
else:
how = 'canvas coordinate clicks (no semantics enabled), keyboard.type'
# layout is fixed: email field centre ~(160,34), password ~(160,92)
pg.mouse.click(160, 34); time.sleep(0.5)
found = pg.evaluate("document.querySelectorAll('input').length")>0
pg.keyboard.type(EMAIL, delay=15)
pg.mouse.click(160, 92); time.sleep(0.5)
pg.keyboard.type(PW, delay=15)
time.sleep(0.5)
pws = pw_state(pg)
if arm == 'L1': found = found and pws != 'noinput'
n1 = len(loglines())
pg.keyboard.press('Enter')
t = time.time(); evs = []
while time.time()-t < 10:
evs = [l for l in loglines()[n1:] if l.startswith('EVENT')]
if evs and time.time()-t > 3: break
time.sleep(0.25)
if not evs: cls = 'NO_FRAME'
elif any('password_value=nonempty' in l or 'data=nonempty' in l for l in evs): cls = 'OK'
else: cls = 'DROP'
ctx.close()
return dict(found=found, dom_password_at_enter=pws, events=evs, cls=cls, how=how)
with sync_playwright() as p:
b = p.chromium.launch(headless=True)
out = open(os.path.join(HERE, 'runs.jsonl'), 'a')
for name, vp in VPS:
for arm in ARMS:
for i in range(N):
try: r = one(b, vp, arm)
except Exception as e: r = dict(found=False, dom_password_at_enter='err', events=[], cls='NO_FRAME', how='exception '+type(e).__name__)
r.update(viewport=name, arm=arm, run=i)
out.write(json.dumps(r)+'\n'); out.flush()
print(name, arm, i, r['found'], r['dom_password_at_enter'], r['cls'], flush=True)
b.close()
- Ngôn ngữ chính
- Python
- Star
- 17.5k
- Fork
- 740
- Merge trung bình
- 1 ngày 8 giờ
- Pull request đã merge (30 ngày)
- 74
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của flet-dev/flet
-
feature: python 3.15 supportĐang mởfeature request
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
flet-dev/flet#6985 · 3 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Web: `TextField.focus()` after `on_submit` discards keys typed while the focus request is in flightĐang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
Maintainer thường phản hồi trong vòng 1 ngày
-
feature request
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 1-2 ngày Mức phù hợp với người mới 42/100
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của flet-dev/flet
Issue tương tự
-
ChatBedrockConverse changes the keys of JSON tool results to camelCase (`order_id` becomes `orderId`)Có thể đã có người làm @geyazheng đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
langchain-ai/langchain-aws#1469 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
GCToggler leaves collection enabled if the body re-enables itCó thể đã có người làm @Gambit-Checkmate đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 7 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
EESSI/docs#949 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
doronz88/pymobiledevice3#2176 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
b4b usability
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Maintainer thường phản hồi trong vòng 1 ngày