buninu-browser 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -34,8 +34,18 @@ export class BrowserDialog {
34
34
  await host.call('loadDocument',{url:'about:dialog',source:entry.picker?entry.picker.document(size,background):dialogDocument(entry.request,size,background),contentType:'text/html'});
35
35
  if(this.active===entry)this.changed();
36
36
  }
37
- async invoke(method,...args) {
37
+ invoke(method,...args) {
38
38
  const entry=this.active;if(!entry)return;
39
+ const invoke=()=>this.invokeEntry(entry,method,...args);
40
+ if(!['press','type','click'].includes(method))return invoke();
41
+ // Modal input bypasses the page's blocked script turn. Serialize it here:
42
+ // overlapping down/up requests must not consume the same file action twice
43
+ // or reload the picker while another input still uses its old document.
44
+ const result=(entry.inputQueue??Promise.resolve()).then(invoke);
45
+ entry.inputQueue=result.then(()=>{},()=>{});
46
+ return result;
47
+ }
48
+ async invokeEntry(entry,method,...args) {
39
49
  await entry.ready;
40
50
  if(this.active!==entry||!entry.host)return;
41
51
  if(method==='press' && (args[1]?.modifiers & 6) && String(args[0]).toLowerCase()==='c') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "buninu-browser",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Buninu Browser is a browser engine written in JavaScript and WebAssembly for Bun.",
5
5
  "keywords": [
6
6
  "buninu",
@@ -16,6 +16,14 @@ test('file input opens browser-owned picker, selects files, and FileReader emits
16
16
  const action=async value=>{await c.evaluate(`window.__fileAction=${JSON.stringify(value)}`);await c.send('Input.dispatchKeyEvent',{type:'keyDown',key:'Shift'});await c.send('Input.dispatchKeyEvent',{type:'keyUp',key:'Shift'});};
17
17
  await action({kind:'browse',path:dir});
18
18
  expect(await c.evaluate('document.body.textContent.includes("one.txt")')).toBe(true);
19
+ const point=await c.evaluate(`(()=>{const b=document.querySelector('button.entry');const r=b.getBoundingClientRect();return {x:r.x+20,y:r.y+r.height/2}})()`);
20
+ // Casty lets modal input bypass the page's blocked input turn. Down/up
21
+ // requests may overlap: one click must consume its picker action once.
22
+ for(const expected of ['one.txt','']) {
23
+ await Promise.all(['mousePressed','mouseReleased'].map(type=>c.send('Input.dispatchMouseEvent',{type,...point,button:'left',clickCount:1})));
24
+ expect(b.context.dialogState?.type).toBe('file');
25
+ expect(await c.evaluate('document.getElementById("chosen").textContent')).toBe(expected);
26
+ }
19
27
  await action({kind:'select',index:0});await action({kind:'select',index:1});await action({kind:'open'});
20
28
  for(let i=0;i<100;i++){if(await c.evaluate('window.text!==undefined'))break;await Bun.sleep(10);}
21
29
  expect(await c.evaluate('clickReturned')).toBe(true);expect(await c.evaluate('names')).toEqual(['one.txt','two.txt']);