Fix Editor/Debugger script listing after page load
This commit is contained in:
@@ -1,5 +1,14 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.0.29
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- **Fixed Editor/Debugger script listing after page load**: `listScripts()` and `list()` now work correctly even when called after page has loaded
|
||||||
|
- `enable()` now disables first then re-enables to force CDP to emit `scriptParsed` and `styleSheetAdded` events
|
||||||
|
- Added 100ms debounced wait for events to arrive before returning
|
||||||
|
- `listScripts()` and `list()` are now async and auto-call `enable()`
|
||||||
|
|
||||||
## 0.0.28
|
## 0.0.28
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "playwriter",
|
"name": "playwriter",
|
||||||
"description": "",
|
"description": "",
|
||||||
"version": "0.0.28",
|
"version": "0.0.29",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ async function listScriptsAndSetBreakpoint() {
|
|||||||
const dbg = createDebugger({ cdp })
|
const dbg = createDebugger({ cdp })
|
||||||
await dbg.enable()
|
await dbg.enable()
|
||||||
|
|
||||||
const scripts = dbg.listScripts({ search: 'app' })
|
const scripts = await dbg.listScripts({ search: 'app' })
|
||||||
console.log(scripts)
|
console.log(scripts)
|
||||||
|
|
||||||
if (scripts.length > 0) {
|
if (scripts.length > 0) {
|
||||||
|
|||||||
@@ -108,9 +108,28 @@ export class Debugger {
|
|||||||
if (this.debuggerEnabled) {
|
if (this.debuggerEnabled) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
await this.cdp.send('Debugger.disable')
|
||||||
|
await this.cdp.send('Runtime.disable')
|
||||||
|
this.scripts.clear()
|
||||||
|
const scriptsReady = new Promise<void>((resolve) => {
|
||||||
|
let timeout: ReturnType<typeof setTimeout>
|
||||||
|
const listener = () => {
|
||||||
|
clearTimeout(timeout)
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
this.cdp.off('Debugger.scriptParsed', listener)
|
||||||
|
resolve()
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
this.cdp.on('Debugger.scriptParsed', listener)
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
this.cdp.off('Debugger.scriptParsed', listener)
|
||||||
|
resolve()
|
||||||
|
}, 100)
|
||||||
|
})
|
||||||
await this.cdp.send('Debugger.enable')
|
await this.cdp.send('Debugger.enable')
|
||||||
await this.cdp.send('Runtime.enable')
|
await this.cdp.send('Runtime.enable')
|
||||||
await this.cdp.send('Runtime.runIfWaitingForDebugger')
|
await this.cdp.send('Runtime.runIfWaitingForDebugger')
|
||||||
|
await scriptsReady
|
||||||
this.debuggerEnabled = true
|
this.debuggerEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,8 +512,7 @@ export class Debugger {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists available scripts where breakpoints can be set.
|
* Lists available scripts where breakpoints can be set.
|
||||||
* Scripts are collected from Debugger.scriptParsed events after enable() is called.
|
* Automatically enables the debugger if not already enabled.
|
||||||
* Reload the page after enabling to capture all scripts.
|
|
||||||
*
|
*
|
||||||
* @param options - Options
|
* @param options - Options
|
||||||
* @param options.search - Optional string to filter scripts by URL (case-insensitive)
|
* @param options.search - Optional string to filter scripts by URL (case-insensitive)
|
||||||
@@ -503,15 +521,16 @@ export class Debugger {
|
|||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* // List all scripts
|
* // List all scripts
|
||||||
* const scripts = dbg.listScripts()
|
* const scripts = await dbg.listScripts()
|
||||||
* // [{ scriptId: '1', url: 'https://example.com/app.js' }, ...]
|
* // [{ scriptId: '1', url: 'https://example.com/app.js' }, ...]
|
||||||
*
|
*
|
||||||
* // Search for specific files
|
* // Search for specific files
|
||||||
* const handlers = dbg.listScripts({ search: 'handler' })
|
* const handlers = await dbg.listScripts({ search: 'handler' })
|
||||||
* // [{ scriptId: '5', url: 'https://example.com/handlers.js' }]
|
* // [{ scriptId: '5', url: 'https://example.com/handlers.js' }]
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
listScripts({ search }: { search?: string } = {}): ScriptInfo[] {
|
async listScripts({ search }: { search?: string } = {}): Promise<ScriptInfo[]> {
|
||||||
|
await this.enable()
|
||||||
const scripts = Array.from(this.scripts.values())
|
const scripts = Array.from(this.scripts.values())
|
||||||
const filtered = search
|
const filtered = search
|
||||||
? scripts.filter((s) => s.url.toLowerCase().includes(search.toLowerCase()))
|
? scripts.filter((s) => s.url.toLowerCase().includes(search.toLowerCase()))
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ async function readStylesheet() {
|
|||||||
const editor = createEditor({ cdp })
|
const editor = createEditor({ cdp })
|
||||||
await editor.enable()
|
await editor.enable()
|
||||||
|
|
||||||
const stylesheets = editor.list({ pattern: /\.css/ })
|
const stylesheets = await editor.list({ pattern: /\.css/ })
|
||||||
console.log('Stylesheets:', stylesheets)
|
console.log('Stylesheets:', stylesheets)
|
||||||
|
|
||||||
if (stylesheets.length > 0) {
|
if (stylesheets.length > 0) {
|
||||||
|
|||||||
@@ -86,9 +86,33 @@ export class Editor {
|
|||||||
if (this.enabled) {
|
if (this.enabled) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
await this.cdp.send('Debugger.disable')
|
||||||
|
await this.cdp.send('CSS.disable')
|
||||||
|
this.scripts.clear()
|
||||||
|
this.stylesheets.clear()
|
||||||
|
this.sourceCache.clear()
|
||||||
|
const resourcesReady = new Promise<void>((resolve) => {
|
||||||
|
let timeout: ReturnType<typeof setTimeout>
|
||||||
|
const listener = () => {
|
||||||
|
clearTimeout(timeout)
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
this.cdp.off('Debugger.scriptParsed', listener)
|
||||||
|
this.cdp.off('CSS.styleSheetAdded', listener)
|
||||||
|
resolve()
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
this.cdp.on('Debugger.scriptParsed', listener)
|
||||||
|
this.cdp.on('CSS.styleSheetAdded', listener)
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
this.cdp.off('Debugger.scriptParsed', listener)
|
||||||
|
this.cdp.off('CSS.styleSheetAdded', listener)
|
||||||
|
resolve()
|
||||||
|
}, 100)
|
||||||
|
})
|
||||||
await this.cdp.send('Debugger.enable')
|
await this.cdp.send('Debugger.enable')
|
||||||
await this.cdp.send('DOM.enable')
|
await this.cdp.send('DOM.enable')
|
||||||
await this.cdp.send('CSS.enable')
|
await this.cdp.send('CSS.enable')
|
||||||
|
await resourcesReady
|
||||||
this.enabled = true
|
this.enabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +132,7 @@ export class Editor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists available script and stylesheet URLs. Use pattern to filter by regex.
|
* Lists available script and stylesheet URLs. Use pattern to filter by regex.
|
||||||
|
* Automatically enables the editor if not already enabled.
|
||||||
*
|
*
|
||||||
* @param options - Options
|
* @param options - Options
|
||||||
* @param options.pattern - Optional regex to filter URLs
|
* @param options.pattern - Optional regex to filter URLs
|
||||||
@@ -116,19 +141,20 @@ export class Editor {
|
|||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* // List all scripts and stylesheets
|
* // List all scripts and stylesheets
|
||||||
* const urls = editor.list()
|
* const urls = await editor.list()
|
||||||
*
|
*
|
||||||
* // List only JS files
|
* // List only JS files
|
||||||
* const jsFiles = editor.list({ pattern: /\.js/ })
|
* const jsFiles = await editor.list({ pattern: /\.js/ })
|
||||||
*
|
*
|
||||||
* // List only CSS files
|
* // List only CSS files
|
||||||
* const cssFiles = editor.list({ pattern: /\.css/ })
|
* const cssFiles = await editor.list({ pattern: /\.css/ })
|
||||||
*
|
*
|
||||||
* // Search for specific scripts
|
* // Search for specific scripts
|
||||||
* const appScripts = editor.list({ pattern: /app/ })
|
* const appScripts = await editor.list({ pattern: /app/ })
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
list({ pattern }: { pattern?: RegExp } = {}): string[] {
|
async list({ pattern }: { pattern?: RegExp } = {}): Promise<string[]> {
|
||||||
|
await this.enable()
|
||||||
const urls = [...Array.from(this.scripts.keys()), ...Array.from(this.stylesheets.keys())]
|
const urls = [...Array.from(this.scripts.keys()), ...Array.from(this.stylesheets.keys())]
|
||||||
|
|
||||||
if (!pattern) {
|
if (!pattern) {
|
||||||
@@ -319,7 +345,7 @@ export class Editor {
|
|||||||
await this.enable()
|
await this.enable()
|
||||||
|
|
||||||
const matches: SearchMatch[] = []
|
const matches: SearchMatch[] = []
|
||||||
const urls = this.list({ pattern })
|
const urls = await this.list({ pattern })
|
||||||
|
|
||||||
for (const url of urls) {
|
for (const url of urls) {
|
||||||
let source: string
|
let source: string
|
||||||
|
|||||||
@@ -2094,19 +2094,12 @@ describe('CDP Session Tests', () => {
|
|||||||
const cdpSession = await getCDPSessionForPage({ page: cdpPage!, wsUrl })
|
const cdpSession = await getCDPSessionForPage({ page: cdpPage!, wsUrl })
|
||||||
const dbg = new Debugger({ cdp: cdpSession })
|
const dbg = new Debugger({ cdp: cdpSession })
|
||||||
|
|
||||||
await dbg.enable()
|
const scripts = await dbg.listScripts()
|
||||||
|
|
||||||
for (let i = 0; i < 20; i++) {
|
|
||||||
if (dbg.listScripts().length > 0) break
|
|
||||||
await new Promise(r => setTimeout(r, 100))
|
|
||||||
}
|
|
||||||
|
|
||||||
const scripts = dbg.listScripts()
|
|
||||||
expect(scripts.length).toBeGreaterThan(0)
|
expect(scripts.length).toBeGreaterThan(0)
|
||||||
expect(scripts[0]).toHaveProperty('scriptId')
|
expect(scripts[0]).toHaveProperty('scriptId')
|
||||||
expect(scripts[0]).toHaveProperty('url')
|
expect(scripts[0]).toHaveProperty('url')
|
||||||
|
|
||||||
const dataScripts = dbg.listScripts({ search: 'data:' })
|
const dataScripts = await dbg.listScripts({ search: 'data:' })
|
||||||
expect(dataScripts.length).toBeGreaterThan(0)
|
expect(dataScripts.length).toBeGreaterThan(0)
|
||||||
|
|
||||||
cdpSession.close()
|
cdpSession.close()
|
||||||
@@ -2698,8 +2691,7 @@ describe('CDP Session Tests', () => {
|
|||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
await new Promise(r => setTimeout(r, 100))
|
await new Promise(r => setTimeout(r, 100))
|
||||||
|
const scripts = await editor.list()
|
||||||
const scripts = editor.list()
|
|
||||||
expect(scripts.length).toBeGreaterThan(0)
|
expect(scripts.length).toBeGreaterThan(0)
|
||||||
|
|
||||||
const matches = await editor.grep({ regex: /greetUser/ })
|
const matches = await editor.grep({ regex: /greetUser/ })
|
||||||
@@ -2766,8 +2758,7 @@ describe('CDP Session Tests', () => {
|
|||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
await new Promise(r => setTimeout(r, 100))
|
await new Promise(r => setTimeout(r, 100))
|
||||||
|
const stylesheets = await editor.list({ pattern: /inline-css:/ })
|
||||||
const stylesheets = editor.list({ pattern: /inline-css:/ })
|
|
||||||
expect(stylesheets.length).toBeGreaterThan(0)
|
expect(stylesheets.length).toBeGreaterThan(0)
|
||||||
|
|
||||||
const cssMatches = await editor.grep({ regex: /editor-test-element/, pattern: /inline-css:/ })
|
const cssMatches = await editor.grep({ regex: /editor-test-element/, pattern: /inline-css:/ })
|
||||||
|
|||||||
Reference in New Issue
Block a user