├── .gitignore ├── README.md ├── bin └── pandora-dashboard-dir ├── index.js ├── package.json ├── procfile.js ├── public ├── .eslintrc └── src │ ├── Debugger.jsx │ ├── ErrorInspection.jsx │ ├── Home.jsx │ ├── Metrics.jsx │ ├── ProcessStructure.jsx │ ├── Stdout.jsx │ ├── Trace.jsx │ ├── TraceViewer.jsx │ ├── app.css │ ├── app.jsx │ ├── components │ ├── ApplicationItem.jsx │ ├── ApplicationPage.jsx │ ├── LayoutCpnt.jsx │ ├── PreView.jsx │ ├── ProcessTree.jsx │ └── SpanCostIndicator.jsx │ ├── consts.jsx │ └── utils │ ├── Actuator.jsx │ └── Common.jsx ├── resource └── chrome-devtools │ ├── InspectorBackendCommands.js │ └── SupportedCSSProperties.js ├── src ├── Dashboard.ts ├── WebServer.ts ├── impl │ ├── Actuator.ts │ ├── ChromeDevtools.ts │ ├── DebuggerProxy.ts │ ├── Home.ts │ ├── Static.ts │ └── Stdout.ts └── utils │ └── Common.ts ├── tsconfig.json ├── tslint.json └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | *.log.* 4 | logs 5 | .vscode 6 | dest 7 | dist 8 | coverage 9 | .idea 10 | .* 11 | docs/api-reference 12 | _book 13 | coverage 14 | public/build 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pandora Dashboard 2 | 3 | A local Dashboard for the Pandora.js. 4 | 5 | The Dashboard it is a standard Pandora.js Project, manage it like a normal Project. 6 | 7 | ## Usage 8 | 9 | ### Install globaly 10 | 11 | ```bash 12 | $ npm i pandora-dashboard -g # install pandora-dashboard globally 13 | $ pandora start --name dashboard `pandora-dashboard-dir` # start it 14 | ``` 15 | 16 | open `http://127.0.0.1:9081` 17 | 18 | ## Custom TCP Port and IP Address 19 | 20 | By default, The Dashboard listens to `http://127.0.0.1:9081`. But it also can tell The Dashboard a specific TCP Port and a specific IP Address to listen on. 21 | 22 | ```bash 23 | pandora start --name dashboard --env "DASHBOARD_PORT=9081 DASHBOARD_HOST=0.0.0.0" `pandora-dashboard-dir` 24 | ``` 25 | 26 | ## HTTP Auth 27 | 28 | Set a environment variable like below: 29 | 30 | ```bash 31 | pandora start --name dashboard --env "DASHBOARD_AUTH=admin:admin" `pandora-dashboard-dir` 32 | 33 | ``` 34 | 35 | ## How to Contribute 36 | 37 | ### Back-End 38 | 39 | Run `pandora dev`, that will start the project by TypeScript source files through `ts-node/register`. 40 | ### Front-End 41 | 42 | The front-end is a React application which relies on `[react-router](https://github.com/ReactTraining/react-router)` for navigation. `[webpack](https://github.com/webpack/webpack)` is being used as the module resolver and the build tool producing a single `bundle.js` for distribution. 43 | 44 | **webpack-dev-server** 45 | 46 | 1. Run `npm run dev-public`, that will start a `webpack-dev-server` to listens on default port `8080`. 47 | 2. Run `pandora dev --env="DASHBOARD_PUBLIC_BASE_URL=http://localhost:8080/public/build"` to tell back-end use `webpack-dev-server` as the bundle URL. 48 | 49 | **build** 50 | 51 | The source files in the folder `./public/src`, you can run `npm run build-public` to build it into `./public/build`. 52 | -------------------------------------------------------------------------------- /bin/pandora-dashboard-dir: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | const {join} = require('path'); 5 | console.log(join(__dirname, '../')); 6 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | throw new Error('The module pandora-dashboard can not been required'); 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pandora-dashboard", 3 | "version": "1.0.14", 4 | "description": "A local Dashboard for the Pandora.js.", 5 | "main": "index.js", 6 | "bin": { 7 | "pandora-dashboard-dir": "bin/pandora-dashboard-dir" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1", 11 | "build": "npm run lint && tsc && npm run build-public", 12 | "lint": "tslint --format prose -c tslint.json 'src/**/*.ts' 'test/**/*.ts' && npm run lint-public", 13 | "build-public": "webpack -p --optimize-minimize", 14 | "dev-public": "webpack-dev-server", 15 | "lint-public": "eslint -c public/.eslintrc 'public/src/**/*.jsx'", 16 | "prepublish": "npm run build" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/midwayjs/pandora-dashboard.git" 21 | }, 22 | "author": "", 23 | "license": "ISC", 24 | "bugs": { 25 | "url": "https://github.com/midwayjs/pandora-dashboard/issues" 26 | }, 27 | "homepage": "https://github.com/midwayjs/pandora-dashboard#readme", 28 | "dependencies": { 29 | "@types/mz": "0.0.32", 30 | "basic-auth": "^2.0.0", 31 | "chrome-devtools-frontend": "1.0.526395", 32 | "dorapan": "^1.0.5", 33 | "koa": "^2.4.1", 34 | "koa-error": "^3.1.0", 35 | "koa-mount": "^3.0.0", 36 | "koa-onerror": "^4.0.0", 37 | "koa-router": "^7.3.0", 38 | "koa-static": "^4.0.2", 39 | "koa-static-cache": "^5.1.1", 40 | "koa-websocket": "^4.1.0", 41 | "mz": "^2.7.0", 42 | "read-last-lines": "^1.3.0", 43 | "tail": "^1.2.3", 44 | "urllib": "^2.25.1" 45 | }, 46 | "files": [ 47 | "bin", 48 | "dist", 49 | "resource", 50 | "public/build", 51 | "procfile.js", 52 | "index.js" 53 | ], 54 | "devDependencies": { 55 | "@types/koa": "^2.0.41", 56 | "@types/koa-router": "^7.0.26", 57 | "@types/node": "^8.0.53", 58 | "@types/ws": "^3.2.1", 59 | "antd": "^2.13.10", 60 | "axios": "^0.17.1", 61 | "babel-core": "^6.26.0", 62 | "babel-eslint": "^8.0.2", 63 | "babel-loader": "^7.1.2", 64 | "babel-preset-env": "^1.6.1", 65 | "babel-preset-react": "^6.24.1", 66 | "compression-webpack-plugin": "^1.0.1", 67 | "css-loader": "^0.28.7", 68 | "duration": "^0.2.0", 69 | "eslint": "^4.12.0", 70 | "eslint-plugin-react": "^7.5.1", 71 | "extract-text-webpack-plugin": "^3.0.2", 72 | "lodash.throttle": "^4.0.8", 73 | "moment": "^2.19.3", 74 | "react": "^16.1.1", 75 | "react-autosize-textarea": "^3.0.2", 76 | "react-dom": "^16.1.1", 77 | "react-icons": "^2.2.7", 78 | "react-router": "^4.2.0", 79 | "react-router-dom": "^4.2.2", 80 | "regenerator-runtime": "^0.11.0", 81 | "style-loader": "^0.19.0", 82 | "ts-node": "^3.3.0", 83 | "tslint": "^4.5.1", 84 | "typescript": "^2.6.1", 85 | "webpack": "^3.8.1", 86 | "webpack-dev-server": "^2.9.5" 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /procfile.js: -------------------------------------------------------------------------------- 1 | module.exports = (pandora) => { 2 | pandora.process('worker').scale(1); 3 | if(pandora.dev) { 4 | pandora.process('worker').nodeArgs().push('-r', 'ts-node/register', '--trace-warnings'); 5 | pandora.service('dashboard', './src/Dashboard').process('worker'); 6 | } else { 7 | pandora.service('dashboard', './dist/Dashboard').process('worker'); 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /public/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": ["eslint:recommended", "plugin:react/recommended"], 4 | "env": { 5 | "browser": true 6 | }, 7 | "rules": { 8 | "react/prop-types": false, 9 | "react/display-name": false, 10 | "no-console": ["warn", { "allow": ["warn", "error"] }] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /public/src/Debugger.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Actuator} from './utils/Actuator'; 3 | import {ApplicationPage} from "./components/ApplicationPage"; 4 | import {ProcessTree} from './components/ProcessTree'; 5 | import {Button} from 'antd'; 6 | 7 | 8 | export class Debugger extends ApplicationPage { 9 | 10 | constructor(props) { 11 | super(props); 12 | this.state.processes = null; 13 | } 14 | 15 | componentDidMount() { 16 | super.componentDidMount(); 17 | this.fetchProcess().catch(alert); 18 | } 19 | 20 | async fetchProcess () { 21 | const processes = await Actuator.get('/process', { 22 | appName: this.appName 23 | }); 24 | this.setState({processes}); 25 | } 26 | 27 | renderPage () { 28 | const {processes, app} = this.state; 29 | const {structure} = app; 30 | if(!structure.inspector) { 31 | return
32 |

Debugger

33 |

Please restart this application with the --inspect option, like below.

34 |

pandora start --inspect

35 |
; 36 | } 37 | return
38 |

Debugger

39 | {processes ? { 40 | const debugUrl = '/chrome-devtools/inspector.html?experiments=true&v8only=true&ws=' + location.host + '/debugger-proxy/' + app.appName + '/' + process.pid; 41 | return { 42 | open(debugUrl); 43 | }} > 44 | }} /> : null} 45 |
; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /public/src/ErrorInspection.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Actuator} from './utils/Actuator'; 3 | import {ApplicationPage} from "./components/ApplicationPage"; 4 | import {Card, Tag, Pagination} from 'antd'; 5 | import moment from "moment"; 6 | 7 | const PAGE_SIZE = 20; 8 | 9 | export class ErrorInspection extends ApplicationPage { 10 | 11 | constructor(props) { 12 | super(props); 13 | this.state.items = null; 14 | this.state.count = null; 15 | this.state.pageNumber = null; 16 | } 17 | 18 | componentDidMount() { 19 | super.componentDidMount(); 20 | this.fetchError(1).catch(alert); 21 | } 22 | 23 | async fetchError(pageNumber) { 24 | const {count, items} = await Actuator.get('/error', { 25 | appName: this.appName, 26 | // by: 'date', // nerver use 27 | order: 'DESC', 28 | offset: (pageNumber - 1) * PAGE_SIZE, 29 | limit: PAGE_SIZE 30 | }); 31 | this.setState({count, items, pageNumber}); 32 | } 33 | 34 | renderPage () { 35 | 36 | const {count, items, pageNumber} = this.state; 37 | if(!items) { 38 | return null; 39 | } 40 | 41 | return
42 |

Recent Errors

43 | 44 | {items.length ? ( 45 | items.map((error, idx) => { 46 | return 47 | }) 48 | ) : ( 49 |

Empty

50 | )} 51 | 52 |
53 | { 54 | this.fetchError(pageNumber).catch(alert); 55 | }}/> 56 |
57 |
58 | } 59 | 60 | } 61 | 62 | const SingleMsg = (props) => { 63 | const {error} = props; 64 | 65 | const title =
66 | {error.errType} 67 |   68 | Time: {moment(error.timestamp).format('L LTS')} 69 |      70 | PID: {error.pid} 71 |      72 | Path: {error.path} 73 |
; 74 | 75 | return ( 76 | 77 | {title} 78 |
Error Message: {error.message}
79 | {error.stack ? ( 80 |
81 | Stack: 82 |
83 | {error.stack} 84 |
85 |
86 | ) : null} 87 |
88 | ) 89 | }; 90 | 91 | -------------------------------------------------------------------------------- /public/src/Home.jsx: -------------------------------------------------------------------------------- 1 | import {Breadcrumb} from 'antd'; 2 | import React, {Component} from 'react'; 3 | import {Row, Col} from 'antd'; 4 | import {ApplicationItem} from "./components/ApplicationItem"; 5 | import {Link} from 'react-router-dom'; 6 | import {Actuator} from "./utils/Actuator"; 7 | import {safe} from "./utils/Common"; 8 | 9 | export class Home extends Component { 10 | 11 | constructor(props) { 12 | super(props); 13 | this.state = { 14 | appList: null, 15 | daemonInfo: null 16 | } 17 | } 18 | 19 | componentDidMount() { 20 | this.fetchAppList().catch(alert); 21 | this.fetchDaemonInfo().catch(alert); 22 | } 23 | 24 | async fetchDaemonInfo() { 25 | const daemonInfo = await Actuator.get('/daemon'); 26 | this.setState({daemonInfo}); 27 | } 28 | 29 | async fetchAppList() { 30 | const infoRes = await Actuator.get('/info'); 31 | const appList = []; 32 | 33 | for(const appName of Object.keys(infoRes)) { 34 | const record = infoRes[appName]; 35 | const endPoint = {}; 36 | record[0].data.endPoint = endPoint; 37 | for(const item of record) { 38 | endPoint[item.key] = item.data; 39 | } 40 | appList.push(record[0].data); 41 | } 42 | const appList2nd = appList.sort((a, b) => { 43 | return a.uptime - b.uptime; 44 | }); 45 | 46 | this.setState({appList: appList2nd}); 47 | } 48 | 49 | render() { 50 | 51 | const breadcrumb = 52 | Pandora.js 53 | Home 54 | ; 55 | 56 | 57 | return ( 58 |
59 |
60 | {breadcrumb} 61 |
62 |
63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
73 |
74 | ); 75 | 76 | 77 | } 78 | } 79 | 80 | const AppList = (props) => { 81 | 82 | const {appList} = props; 83 | 84 | return
85 | {appList && appList.map((app) => { 86 | return 87 | })} 88 |
89 | 90 | }; 91 | 92 | const PandoraInfo = (props) => { 93 | 94 | const {daemonInfo} = props; 95 | 96 | return 97 | 98 |

Node.js Version: {safe(() => daemonInfo.versions.node, '-')}

99 |

Pandora.js Version: {safe(() => daemonInfo.versions.pandora, '-')}

100 |

Daemon PID: {safe(() => daemonInfo.pid, '-')}

101 |

Daemon Uptime: {safe(() => daemonInfo.uptime + ' seconds', '-')}

102 |

Daemon WorkDir: {safe(() => daemonInfo.cwd , '-')}

103 | 104 | 105 | 106 |

107 | Loaded Global Configs: 108 |
109 | {safe(() => daemonInfo.loadedGlobalConfigPaths.join(', ') , '-')} 110 |

111 | 112 |

113 | Loaded Endpoints: 114 |
115 | {safe(() => daemonInfo.loadedEndPoints.join(', ') , '-')} 116 |

117 | 118 |

119 | Loaded Reporters: 120 |
121 | {safe(() => daemonInfo.loadedReporters.join(', ') , '-')} 122 |

123 | 124 | 125 |
; 126 | }; 127 | 128 | 129 | const SimpleCube = (props) => { 130 | return
131 |

{props.title}

132 | {props.children} 133 |
134 | }; 135 | 136 | const styles = { 137 | pandoraInfoCol: { 138 | padding: '0 10px', 139 | lineHeight: '2' 140 | }, 141 | title: { 142 | borderBottom: '1px solid #ddd', 143 | paddingBottom: 15, 144 | marginBottom: 30 145 | } 146 | }; 147 | -------------------------------------------------------------------------------- /public/src/Metrics.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Actuator} from './utils/Actuator'; 3 | import {ApplicationPage} from "./components/ApplicationPage"; 4 | import {Card, Row, Col, Tag, Tabs} from 'antd'; 5 | import {ascendDimension, displayValue, humanizeMetricValue, sortMetrics, sortMetricsGroups} from "./utils/Common"; 6 | const TabPane = Tabs.TabPane; 7 | 8 | export class Metrics extends ApplicationPage { 9 | 10 | constructor (props) { 11 | super(props); 12 | this.state.displayList = null; 13 | this.interval = null; 14 | } 15 | 16 | componentDidMount() { 17 | super.componentDidMount(); 18 | this.fetchMetrics().then(() => { 19 | this.interval = setInterval(() => { 20 | this.fetchMetrics().catch(console.error); 21 | }, 10 * 1000) 22 | }).catch(alert); 23 | } 24 | 25 | componentWillUnmount() { 26 | if(this.interval) { 27 | clearInterval(this.interval); 28 | this.interval = null; 29 | } 30 | } 31 | 32 | async fetchMetrics() { 33 | const groups = await Actuator.get('/metrics/list', { 34 | appName: this.appName 35 | }); 36 | const groupNames = Object.keys(groups); 37 | const displayList = []; 38 | for(const group of groupNames) { 39 | const res = await Actuator.get('/metrics/' + group, { 40 | appName: this.appName 41 | }); 42 | displayList.push({ 43 | group: group, 44 | metrics: res 45 | }); 46 | } 47 | this.setState({displayList}); 48 | } 49 | 50 | renderPage () { 51 | 52 | const {displayList} = this.state; 53 | if(!this.state.displayList) { 54 | return null; 55 | } 56 | 57 | return
58 | 59 |

Metrics instantaneous values ( auto refresh for every 10 seconds )

60 | 61 | 62 | { 63 | sortMetricsGroups(displayList).map((single, idx) => { 64 | const name = single.group.replace(/^.{1}/, (firstChar) => firstChar.toUpperCase()); 65 | return 66 | 67 | 68 | }) 69 | } 70 | 71 |
72 | 73 | } 74 | 75 | } 76 | 77 | const GroupContent = (props) => { 78 | 79 | const {single, idx} = props; 80 | 81 | if(single.group === 'node') { 82 | return 83 | } 84 | 85 | return
86 | 87 |
88 | }; 89 | 90 | 91 | 92 | const NodeGroup = (props) => { 93 | const {single} = props; 94 | const {metrics} = single; 95 | const metricsSplitByPid = {}; 96 | 97 | for(const one of metrics) { 98 | if(one.tags && one.tags.pid) { 99 | const pid = one.tags.pid; 100 | const list = metricsSplitByPid[pid] = metricsSplitByPid[pid] || []; 101 | list.push(one); 102 | } else { 103 | const list = metricsSplitByPid['other'] = metricsSplitByPid['other'] || []; 104 | list.push(one); 105 | } 106 | } 107 | 108 | return
109 | 110 | {Object.keys(metricsSplitByPid).map((pid) => { 111 | const metricsForThisPid = metricsSplitByPid[pid]; 112 | return 113 | 114 | 115 | })} 116 | 117 |
; 118 | }; 119 | 120 | const GroupSubView = (props) => { 121 | 122 | const {metrics} = props; 123 | const obj = {}; 124 | const order = []; 125 | 126 | for(const one of sortMetrics(metrics)) { 127 | const name = one.metric; 128 | const first2part = name.split('.').slice(0, -1).slice(0, 3).join('.'); 129 | if(!obj[first2part]) { 130 | order.push(first2part); 131 | obj[first2part] = []; 132 | } 133 | const list = obj[first2part]; 134 | list.push(one); 135 | } 136 | 137 | return
138 | 139 | { 140 | order.map((name) => { 141 | 142 | return
143 |

🏆 Category: {name}

144 | 145 | {ascendDimension(sortMetrics(obj[name]), 3).map((row, idx) => { 146 | return 147 | { 148 | row.map((metric, idx) => { 149 | return 150 | 151 | 152 | }) 153 | } 154 | 155 | })} 156 |
; 157 | }) 158 | } 159 | 160 |
; 161 | 162 | }; 163 | 164 | const InstantaneousValue = (props) => { 165 | const {metric} = props; 166 | const tagKeys = Object.keys(metric.tags); 167 | return ( 168 | 169 |
{humanizeMetricValue(metric)}
170 |
171 | {metric.metric.toString()} 172 | { 173 | tagKeys.length ? tagKeys.map((key) => { 174 | const value = metric.tags[key]; 175 | return {key.toString()}: {displayValue(value)} 176 | }) : null 177 | } 178 |
179 |
180 | ) 181 | }; 182 | 183 | 184 | -------------------------------------------------------------------------------- /public/src/ProcessStructure.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Actuator} from './utils/Actuator'; 3 | import {ApplicationPage} from './components/ApplicationPage'; 4 | import {Tabs} from 'antd'; 5 | import {PreView} from './components/PreView'; 6 | import {ProcessTree} from './components/ProcessTree'; 7 | const { TabPane } = Tabs; 8 | 9 | export class ProcessStructure extends ApplicationPage { 10 | 11 | constructor(props) { 12 | super(props); 13 | this.state.processes = null; 14 | } 15 | 16 | componentDidMount() { 17 | super.componentDidMount(); 18 | this.fetchProcess().catch(alert); 19 | } 20 | 21 | async fetchProcess () { 22 | const processes = await Actuator.get('/process', { 23 | appName: this.appName 24 | }); 25 | this.setState({processes}); 26 | } 27 | 28 | renderPage () { 29 | 30 | const {processes} = this.state; 31 | 32 | return
33 |

Process Structures

34 | 35 | 36 | {processes ? : null} 37 | 38 | 39 | 43 | 44 | 45 |
46 | 47 | } 48 | 49 | } 50 | 51 | -------------------------------------------------------------------------------- /public/src/Stdout.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {ApplicationPage} from "./components/ApplicationPage"; 3 | import {PreView} from "./components/PreView"; 4 | import throttle from 'lodash.throttle'; 5 | 6 | const BUFFER_SIZE = 1000; 7 | 8 | export class Stdout extends ApplicationPage { 9 | 10 | 11 | constructor(props) { 12 | super(props); 13 | this.idx = 0; 14 | this.state.logs = []; 15 | this.state.loading = true; 16 | this.logs = []; 17 | this.syncState = throttle(() => { 18 | if(this.state.loading === true) { 19 | this.setState({ loading: false }); 20 | } 21 | this.setState({ logs: this.logs }); 22 | }, 700); 23 | } 24 | 25 | 26 | componentDidMount() { 27 | super.componentDidMount(); 28 | this.startWs(); 29 | } 30 | 31 | pushLog(log, shouldSplit) { 32 | 33 | if(shouldSplit) { 34 | const logs = log.split('\n').map(content => { 35 | return { key: ++this.idx, content } 36 | }); 37 | if(logs.length && logs[logs.length - 1].content === '\n') { 38 | logs.shift(); 39 | } 40 | this.logs = this.logs.concat(logs); 41 | } else { 42 | this.logs.push({ content: log, key: ++this.idx }); 43 | } 44 | 45 | if(this.logs.length > BUFFER_SIZE) { 46 | this.logs = this.logs.slice(-100); 47 | } 48 | 49 | this.syncState(); 50 | } 51 | 52 | startWs() { 53 | 54 | const wsURI = (location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host + '/stdout/' + this.appName; 55 | const ws = new WebSocket(wsURI); 56 | 57 | ws.onmessage = (event) => { 58 | 59 | const msg = JSON.parse(event.data); 60 | 61 | if(msg.type === 'error') { 62 | alert(msg.error); 63 | return ws.close(); 64 | } 65 | 66 | if(msg.type === 'batch') { 67 | this.pushLog(msg.content, true); 68 | return; 69 | } 70 | 71 | if(msg.type === 'line') { 72 | this.pushLog(msg.content, false); 73 | return; 74 | } 75 | 76 | }; 77 | 78 | } 79 | 80 | renderPage () { 81 | 82 | const logs = this.state.logs; 83 | 84 | return
85 |

Standard Output

86 | {this.state.loading ? ( 87 | 88 | ) : ( 89 | 90 | )} 91 |
92 | 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /public/src/Trace.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Actuator} from './utils/Actuator'; 3 | import {ApplicationPage} from "./components/ApplicationPage"; 4 | import {Table, Pagination} from 'antd'; 5 | import {Link} from "react-router-dom"; 6 | import moment from "moment"; 7 | import {displayDuration, getTraceStatus} from "./utils/Common"; 8 | 9 | const PAGE_SIZE = 20; 10 | 11 | export class Trace extends ApplicationPage { 12 | 13 | constructor(props) { 14 | super(props); 15 | this.state.items = null; 16 | this.state.count = null; 17 | this.state.pageNumber = null; 18 | } 19 | 20 | componentDidMount() { 21 | super.componentDidMount(); 22 | this.fetchTrace(1).catch(alert); 23 | } 24 | 25 | async fetchTrace(pageNumber) { 26 | const {count, items} = await Actuator.get('/trace', { 27 | appName: this.appName, 28 | // by: 'timestamp', // never use 29 | order: 'DESC', 30 | offset: (pageNumber - 1) * PAGE_SIZE, 31 | limit: PAGE_SIZE 32 | }); 33 | this.setState({count, items, pageNumber}); 34 | } 35 | 36 | renderPage () { 37 | 38 | const {count, items, pageNumber} = this.state; 39 | 40 | if(!items) { 41 | return null; 42 | } 43 | 44 | const columns = [ 45 | { 46 | title: 'Trace', 47 | dataIndex: 'name', 48 | key: 'name', 49 | render: (_, record) => { 50 | 51 | const statusPlan = getTraceStatus(record) || {}; 52 | const {color, label} = statusPlan; 53 | 54 | return
55 |
62 | {label ? `[${label.join('] [')}] ` : null}{record.name} 66 |
67 |
Trace ID: {record.traceId}
68 |
; 69 | 70 | } 71 | }, 72 | { 73 | title: 'Duration', 74 | width: '100px', 75 | dataIndex: 'duration', 76 | key: 'duration', 77 | render: displayDuration 78 | }, 79 | { 80 | title: 'Time', 81 | width: '180px', 82 | dataIndex: 'timestamp', 83 | key: 'timestamp', 84 | render(ts) { 85 | return moment(parseInt(ts)).format('L LTS'); 86 | } 87 | }, 88 | { 89 | title: 'PID', 90 | dataIndex: 'pid', 91 | key: 'pid', 92 | width: '110px' 93 | }, 94 | ]; 95 | 96 | return
97 |

Recent Traces

98 | 99 |
100 | { 101 | this.fetchTrace(pageNumber).catch(alert); 102 | }}/> 103 |
104 | ; 105 | 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /public/src/TraceViewer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Actuator} from './utils/Actuator'; 3 | import {ApplicationPage} from "./components/ApplicationPage"; 4 | import {Table, Tag, Tooltip, Modal} from 'antd'; 5 | import {SpanCostIndicator} from "./components/SpanCostIndicator"; 6 | import { 7 | attachChildrenTimeOrder, displayDuration, displayValue, getTraceStatus, isErrorSpan, 8 | orderTags 9 | } from "./utils/Common"; 10 | import TextareaAutosize from 'react-autosize-textarea'; 11 | import moment from "moment"; 12 | 13 | export class TraceViewer extends ApplicationPage { 14 | 15 | constructor(props) { 16 | super(props); 17 | this.state.trace = null; 18 | } 19 | 20 | get traceId () { 21 | return this.props.match.params.traceId; 22 | } 23 | 24 | componentDidMount() { 25 | super.componentDidMount(); 26 | this.fetchTrace().catch(alert); 27 | } 28 | 29 | async fetchTrace() { 30 | const trace = await Actuator.get('/trace/' + this.traceId, { 31 | appName: this.appName 32 | }); 33 | this.setState({trace}); 34 | } 35 | 36 | renderTitle() { 37 | 38 | const {trace: record} = this.state; 39 | 40 | const statusPlan = getTraceStatus(record) || {}; 41 | const {color, label} = statusPlan; 42 | 43 | return
44 |
45 | {label ? `[${label.join('] [')}] ` : null}{record.name} 46 |
47 |
48 | Trace ID: {this.traceId} 49 | Host: {record.host} 50 | PID: {record.pid} 51 | Duration: {displayDuration(record.duration)} 52 | Time: {moment(parseInt(record.timestamp)).format('L LTS')} 53 |
54 |
; 55 | } 56 | 57 | renderPage () { 58 | 59 | const {trace} = this.state; 60 | if(!trace) { 61 | return null; 62 | } 63 | 64 | const columns = [ 65 | { 66 | title: 'Span', 67 | dataIndex: 'name', 68 | width: '240px', 69 | key: 'name', 70 | render: (_, record) => { 71 | return
72 |
73 | Span: {record.name} 74 |
75 |
ID: {record.context && record.context.spanId}
76 |
; 77 | } 78 | }, 79 | { 80 | title: 'Duration', 81 | dataIndex: 'duration', 82 | key: 'duration', 83 | width: '100px', 84 | render: displayDuration 85 | }, 86 | { 87 | width: '25%', 88 | title: 'Timeline', 89 | key: 'timeline', 90 | render: (_, record) => { 91 | return ; 94 | } 95 | }, 96 | { 97 | title: 'Extension', 98 | dataIndex: 'tags', 99 | key: 'tags', 100 | width: '35%', 101 | render: (tags, record) => { 102 | let tagKeys = Object.keys(tags); 103 | if (!tags || !tagKeys.length) { 104 | return null; 105 | } 106 | tagKeys = orderTags(record.name, tagKeys); 107 | const eleTags = tagKeys.map((key, idx) => { 108 | if(!tags[key]) { 109 | return null; 110 | } 111 | const value = tags[key].value; 112 | const text = `${key}: ${displayValue(value)}`; 113 | const eleTag = {text}; 118 | return { 119 | prompt('Tag: ' + key, displayValue(value)); 120 | }} > 121 | {eleTag} 122 | ; 123 | }); 124 | 125 | const logsOnClick = () => { 126 | 127 | const logs = record.logs; 128 | 129 | const logsEle = logs.map((log, idx) => { 130 | return
131 |

Record Time: {moment(parseInt(log.timestamp)).format('L LTS')}

132 | { 133 | log.fields && log.fields.length ? ( 134 | log.fields.map((field, idx) => { 135 | return
136 |

Key: {field.key}

137 | 140 |
; 141 | }) 142 | ) : null 143 | } 144 |
; 145 | }); 146 | 147 | Modal.info({ 148 | zIndex: 9999, 149 | width: '800px', 150 | okText: 'OK', 151 | content:
152 | {logsEle} 153 |
154 | }); 155 | 156 | }; 157 | 158 | const logsEle = record.logs && record.logs.length ?
159 | 160 | { 161 | e.preventDefault(); 162 | logsOnClick(); 163 | }} > 164 | See all logs ( including { record.logs.map((log) => { 165 | if (!log.fields || !log.fields.length) { 166 | return null; 167 | } 168 | return log.fields.map((field) => { 169 | return field.key; 170 | }).join(', '); 171 | }).filter((text) => !!text).join(', ') } ) 172 | 173 | 174 |
: null; 175 | 176 | return
177 | {logsEle} 178 |
181 | {eleTags} 182 |
183 |
; 184 | } 185 | }, 186 | ]; 187 | 188 | const tree = [attachChildrenTimeOrder(trace.spans[0], trace.spans)]; 189 | 190 | return
191 |
192 | {this.renderTitle()} 193 |
194 |
196 | ; 197 | 198 | } 199 | 200 | } 201 | 202 | const styles = { 203 | majorTag: { 204 | color: '#666', 205 | marginBottom: 6, 206 | marginRight: 15, 207 | fontSize: 13 208 | } 209 | }; 210 | -------------------------------------------------------------------------------- /public/src/app.css: -------------------------------------------------------------------------------- 1 | @import '~antd/dist/antd.css'; 2 | body { 3 | color: #000; 4 | } 5 | .actionIcon { 6 | color: #476ad6; 7 | } 8 | .actionIcon:hover { 9 | color: #ff7a34; 10 | } 11 | 12 | .ant-card-head { 13 | padding: 0 15px !important; 14 | } 15 | 16 | .ant-table * { 17 | font-size: 12px; 18 | } 19 | 20 | 21 | body .ant-tabs-nav .ant-tabs-tab { 22 | height: auto; 23 | } 24 | 25 | body .ant-tooltip-inner { 26 | white-space: normal; 27 | word-break: break-all; 28 | max-width: 350px; 29 | } 30 | 31 | body .pandora-tag-namespace .ant-tag { 32 | height: auto; line-height: 1.4; 33 | padding-top: 2px; 34 | padding-bottom: 2px; 35 | } 36 | 37 | body .pandora-tag-namespace .ant-tag-text { 38 | word-break: break-all; 39 | white-space: normal; 40 | height: auto; 41 | } 42 | 43 | body .ApplicationPageSide { 44 | position: relative; 45 | min-height: 100vh; 46 | } 47 | body .ApplicationPageSide .ant-layout-sider-children { 48 | height: 100%; width: 100%; 49 | position: absolute; right: 0; top: 0; 50 | } 51 | 52 | .trace-container-pandora .ant-table { 53 | font-size: 13px; 54 | } 55 | .trace-container-pandora .ant-table .ant-table-thead > tr > th, 56 | .trace-container-pandora .ant-table .ant-table-tbody > tr > td { 57 | padding: 16px 10px; 58 | } 59 | 60 | .pandoraTagWrapper::-webkit-scrollbar { 61 | -webkit-appearance: none; 62 | width: 9px; 63 | } 64 | .pandoraTagWrapper::-webkit-scrollbar-thumb { 65 | border-radius: 4px; 66 | background-color: rgba(0, 0, 0, 0.3); 67 | -webkit-box-shadow: 0 0 1px rgba(255, 255, 255, 0.3); 68 | } 69 | 70 | -------------------------------------------------------------------------------- /public/src/app.jsx: -------------------------------------------------------------------------------- 1 | import 'regenerator-runtime/runtime'; 2 | import './app.css'; 3 | import React, {Component} from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | import { BrowserRouter, Route } from 'react-router-dom'; 6 | import {LayoutCpnt} from './components/LayoutCpnt'; 7 | import {Home} from './Home'; 8 | import {Stdout} from './Stdout'; 9 | import {ProcessStructure} from "./ProcessStructure"; 10 | import {ErrorInspection} from "./ErrorInspection"; 11 | import {Metrics} from "./Metrics"; 12 | import {Trace} from "./Trace"; 13 | import {TraceViewer} from "./TraceViewer"; 14 | import {Debugger} from './Debugger'; 15 | 16 | class ScrollToTop extends Component { 17 | 18 | componentWillReceiveProps(nextProps) { 19 | if(this.props.location.pathname === '/' || nextProps.location.pathname === '/') { 20 | window.scrollTo(0, 0); 21 | } 22 | } 23 | 24 | render () { 25 | return null; 26 | } 27 | 28 | } 29 | 30 | ReactDOM.render(( 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ), document.getElementById('DUMP_APP_HERE')); 45 | 46 | -------------------------------------------------------------------------------- /public/src/components/ApplicationItem.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import {Card} from 'antd'; 3 | import IconDvr from 'react-icons/lib/md/dvr'; 4 | import IconMap from 'react-icons/lib/md/map'; 5 | import IconTraffic from 'react-icons/lib/md/traffic'; 6 | import IconHighlight from 'react-icons/lib/md/highlight'; 7 | import IconStraighten from 'react-icons/lib/md/straighten'; 8 | import IconBugRport from 'react-icons/lib/md/bug-report'; 9 | import { Link } from 'react-router-dom'; 10 | import {displayDuration, stateToDisplay} from "../utils/Common"; 11 | 12 | 13 | export class ApplicationItem extends Component { 14 | 15 | render () { 16 | 17 | const {app} = this.props; 18 | 19 | const title =
20 |
21 |

{app.appName} [{stateToDisplay(app.state)}]

22 | At location {app.appDir} 23 |
24 | 25 |
26 |

27 | 28 | Uptime: {displayDuration(app.uptime * 1000)} 29 | 30 | 31 | PID: {app.pids.join(', ')} 32 | 33 | 34 | Restart Count: {app.restartCount} 35 | 36 |

37 |
38 | 39 |
; 40 | 41 | return 42 | {title} 43 | 44 |
45 | 46 | 47 |
48 | 49 |
50 | Standard Output 51 |
52 | 53 | 54 | 55 |
56 | 57 |
58 | Process Structure 59 |
60 | 61 | 62 |
63 | 64 | 65 |
66 | 67 |
68 | Error Inspection 69 |
70 | 71 | 72 | 73 |
74 | 75 |
76 | Metrics 77 |
78 | 79 | 80 | 81 |
82 | 83 |
84 | Trace 85 |
86 | 87 | 88 |
89 | 90 | 91 |
92 | 93 |
94 | Debugger 95 |
96 | 97 | 98 | 99 |
100 | 101 |
102 | 103 | } 104 | 105 | } 106 | 107 | 108 | const styles = { 109 | titleIndicator: { 110 | marginRight: 10 111 | }, 112 | actionIcon: { 113 | cursor: "pointer", 114 | verticalAlign: 'top', 115 | width: 60, 116 | padding: '5px 10px', 117 | boxSizing: 'content-box', 118 | display: 'inline-block', 119 | textAlign: 'center', 120 | lineHeight: 1.2 121 | }, 122 | actionIconText: { 123 | display: 'inline-block', 124 | paddingTop: 5 125 | }, 126 | actionSplitter: { 127 | display: 'inline-block', 128 | height: 75, 129 | margin: '0 15px', 130 | width: 1, 131 | overflow: 'hidden', 132 | background: '#ddd' 133 | 134 | } 135 | }; 136 | -------------------------------------------------------------------------------- /public/src/components/ApplicationPage.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Breadcrumb, Layout, Menu } from 'antd'; 3 | const {Sider, Content} = Layout; 4 | import { Link } from 'react-router-dom'; 5 | import {Actuator} from '../utils/Actuator'; 6 | import {displayDuration, safe, stateToDisplay} from "../utils/Common"; 7 | 8 | const noSiderMethods = [ 9 | 'traceViewer' 10 | ]; 11 | 12 | const appsCached = {}; 13 | 14 | export class ApplicationPage extends Component { 15 | 16 | constructor(props) { 17 | super(props); 18 | this.state = { 19 | app: appsCached[this.appName] || null 20 | }; 21 | } 22 | 23 | componentDidMount() { 24 | this.fetchApp().catch(alert); 25 | } 26 | 27 | async fetchApp() { 28 | const infoRes = await Actuator.get('/info', { 29 | appName: this.appName 30 | }); 31 | if(!infoRes || !infoRes.length) { 32 | throw new Error('Can\'t get an Application it named ' + this.appName); 33 | } 34 | const app = infoRes[0].data; 35 | appsCached[this.appName] = app; 36 | this.setState({app}); 37 | } 38 | 39 | get app() { 40 | return this.state.app; 41 | } 42 | 43 | get appName() { 44 | return this.props.match.params.appName; 45 | } 46 | 47 | get methodName() { 48 | return this.props.match.params.methodName; 49 | } 50 | 51 | renderBreadcrumb() { 52 | const breadcrumb = 53 | Pandora.js 54 | Application 55 | {this.appName} 56 | ; 57 | return breadcrumb; 58 | } 59 | 60 | renderPage() { 61 | return null; 62 | } 63 | 64 | renderOuter() { 65 | 66 | const methodName = this.methodName; 67 | 68 | const content = 69 | {this.app ? this.renderPage() : null} 70 | ; 71 | 72 | if(noSiderMethods.indexOf(methodName) > -1) { 73 | content.props.style.padding = '0 0 15px 0'; 74 | return content; 75 | } 76 | 77 | return 78 | 79 | 80 | 81 | Standard Output 82 | 83 | 84 | Process Structure 85 | 86 | 87 | Error Inspection 88 | 89 | 90 | Metrics 91 | 92 | 93 | Trace 94 | 95 | 96 | Debugger 97 | 98 | 99 | 100 | {content} 101 | 102 | 103 | } 104 | render () { 105 | 106 | const app = this.app; 107 | 108 | return
109 |
110 | {this.renderBreadcrumb()} 111 |
112 | 113 |
114 |

{safe(() => app.appName, '-')} [{safe(() => stateToDisplay(app.state), '-')}]

115 |

At location {safe(() => app.appDir)}

116 |

117 | 118 | Uptime: {safe(() => displayDuration(app.uptime * 1000), '-')} 119 | 120 | 121 | PID: {safe(() => app.pids.join(', '))} 122 | 123 | 124 | Restart Count: {safe(() => app.restartCount, '-')} 125 | 126 |

127 | 128 |
129 |
130 | { this.renderOuter() } 131 |
132 |
; 133 | } 134 | 135 | 136 | } 137 | 138 | const styles = { 139 | titleIndicator: { 140 | marginRight: 10 141 | }, 142 | } 143 | -------------------------------------------------------------------------------- /public/src/components/LayoutCpnt.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Layout } from 'antd'; 3 | const { Header, Content, Footer } = Layout; 4 | import { Link } from 'react-router-dom'; 5 | 6 | export class LayoutCpnt extends Component { 7 | render () { 8 | return 9 |
10 |

Pandora.js Dashboard

11 | 12 |
13 | Star me on GitHub: 14 | 18 |
19 | 20 |
21 | 22 | {this.props.children} 23 | 24 |
25 | Pandora.js 26 |
27 |
28 | 29 | } 30 | } 31 | 32 | const styles = { 33 | starUs: { 34 | color: '#fff', 35 | float: 'right', 36 | marginTop: 1 37 | }, 38 | title: { 39 | marginRight: 3, 40 | float: 'left', 41 | color: '#fff' 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /public/src/components/PreView.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | export class PreView extends Component { 3 | constructor(props) { 4 | super(props); 5 | this.autoScrollFlag = true; 6 | } 7 | 8 | componentWillUpdate() { 9 | const ownPreView = document.getElementById('ownPreView'); 10 | this.autoScrollFlag = !!(ownPreView.scrollTop + ownPreView.clientHeight + 10 > ownPreView.scrollHeight); 11 | } 12 | 13 | componentDidUpdate() { 14 | if(this.autoScrollFlag) { 15 | const ownPreView = document.getElementById('ownPreView'); 16 | ownPreView.scrollTop = ownPreView.scrollHeight; 17 | } 18 | } 19 | 20 | render() { 21 | const logs = this.props.logs || []; 22 | const ownStyle = Object.assign({}, styles.container, this.props.style); 23 | return
24 |
25 |         {logs.map((log) => {
26 |           return 

{log.content}

27 | })} 28 |
29 |
30 | } 31 | } 32 | 33 | const styles = { 34 | container: { 35 | background: '#000', 36 | overflow: 'auto' 37 | }, 38 | pre: { 39 | lineHeight: 2, 40 | fontSize: 12, 41 | padding: '12px 15px', 42 | color: '#fff', 43 | whiteSpace: 'pre-wrap' 44 | } 45 | }; -------------------------------------------------------------------------------- /public/src/components/ProcessTree.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Tree, Tag} from 'antd'; 3 | import {displayDuration, makeProcessTree} from '../utils/Common'; 4 | const { TreeNode } = Tree; 5 | export const ProcessTree = (props) => { 6 | const {appName, processes} = props; 7 | const leads = makeProcessTree(processes); 8 | return 9 | 10 | {subTreeWithoutLead({process: {children: leads}}, props)} 11 | 12 | ; 13 | }; 14 | 15 | const subTreeWithoutLead = (node, props) => { 16 | const process = node.process; 17 | const children = process.children; 18 | if(!children) { 19 | return null; 20 | } 21 | return children.map((process) => { 22 | 23 | const span = 24 | PID: {process.pid} 25 | Process Name: {process.processName} / Uptime: {displayDuration(process.uptime * 1000)} / CPU Usage: {process.cpu}% / Memory: {(process.memory / 1024 / 1014).toFixed(2)}MB{props.extPart && props.extPart(process)}; 26 | 27 | return 28 | {subTreeWithoutLead({process}, props)} 29 | 30 | }); 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /public/src/components/SpanCostIndicator.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const SpanCostIndicator = (props) => { 4 | 5 | const {start, duration, total, style} = props; 6 | 7 | const startPercent = start / total; 8 | const durationPercent = duration / total; 9 | 10 | const ownStyle = Object.assign({}, {background: '#eee', position: 'relative', height: 12, borderRadius: 5, overflow: 'hidden'}, style); 11 | 12 | return
13 |
21 |
; 22 | 23 | }; 24 | -------------------------------------------------------------------------------- /public/src/consts.jsx: -------------------------------------------------------------------------------- 1 | export const State = (function (State) { 2 | State[State["pending"] = 1] = "pending"; 3 | State[State["complete"] = 2] = "complete"; 4 | State[State["stopped"] = 3] = "stopped"; 5 | return State; 6 | })({}); 7 | -------------------------------------------------------------------------------- /public/src/utils/Actuator.jsx: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | export class Actuator { 3 | static async get (path, params) { 4 | const resp = await axios.get('/actuator' + path, {params}); 5 | if(!resp.data.success) { 6 | throw Error('Access Actuator API went wrong, course form server : ' + resp.data.message); 7 | } 8 | return resp.data.data; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /public/src/utils/Common.jsx: -------------------------------------------------------------------------------- 1 | import {State} from "../consts"; 2 | import Duration from "duration"; 3 | 4 | export function stateToDisplay (state) { 5 | state = State[state]; 6 | state = state === 'complete' ? 'Running' : state.replace(/^.{1}/, (firstChar) => firstChar.toUpperCase()); 7 | return state; 8 | } 9 | 10 | export const safe = (fn, x) => { 11 | try { 12 | return fn(); 13 | } catch (err) { 14 | return x || null; 15 | } 16 | }; 17 | 18 | export function makeProcessTree (processes) { 19 | const leads = []; 20 | for(const process of processes) { 21 | const parents = findByCertainKey(processes, 'pid', process.ppid); 22 | if(!parents) { 23 | expandChildren(processes, process); 24 | leads.push(process); 25 | } 26 | } 27 | return leads; 28 | } 29 | 30 | function expandChildren(processes, process) { 31 | const children = findByCertainKey(processes, 'ppid', process.pid); 32 | if(children) { 33 | process.children = children; 34 | for(const child of children) { 35 | expandChildren(processes, child); 36 | } 37 | } 38 | } 39 | 40 | function findByCertainKey (processes, key, eq) { 41 | const ret = []; 42 | for(const process of processes) { 43 | if((process[key] && process[key].toString()) === (eq && eq.toString())) { 44 | ret.push(process); 45 | } 46 | } 47 | if(!ret.length) { 48 | return null; 49 | } 50 | return ret; 51 | } 52 | 53 | export function ascendDimension(arr, n) { 54 | 55 | if(!arr.length) { 56 | return []; 57 | } 58 | 59 | const ret = [[]]; 60 | 61 | for(const x of arr) { 62 | if(ret[ret.length - 1].length >= n) { 63 | ret.push([]); 64 | } 65 | ret[ret.length - 1].push(x); 66 | } 67 | 68 | return ret; 69 | 70 | } 71 | export function displayDuration(ms) { 72 | if(ms == null) { 73 | return null; 74 | } 75 | const duration = new Duration(new Date(0), new Date(ms)); 76 | return duration.toString(1); 77 | } 78 | 79 | export function displayValue(value) { 80 | 81 | if(typeof value === 'string') { 82 | return value; 83 | } 84 | 85 | if(typeof value === 'number') { 86 | return value.toString().indexOf('.') > -1 ? value.toFixed(2) : value; 87 | } 88 | 89 | return JSON.stringify(value); 90 | 91 | } 92 | 93 | const metricsWeight = [ 94 | ['system.load.', 1], 95 | ['system.cpu.', 2], 96 | ['system.mem.', 3], 97 | ['system.disk.', 4], 98 | ['system.tcp.', 5], 99 | ['node.v8.total_heap_size', 1], 100 | ['node.v8.total_heap_size_executable', 2], 101 | ['node.v8.total_physical_size', 3], 102 | ['node.v8.total_available_size', 4], 103 | ['node.v8.used_heap_size', 5], 104 | ['node.v8.heap_size_limit', 6], 105 | ['node.v8.malloced_memory', 7], 106 | ['node.v8.peak_malloced_memory', 8], 107 | ['node.v8.does_zap_garbage', 9], 108 | ['node.v8.new_space', 10], 109 | ['node.v8.old_space', 11], 110 | ['node.v8.code_space', 12], 111 | ['node.v8.large_object_space', 13], 112 | ]; 113 | 114 | export function sortMetrics(metrics) { 115 | return metrics.sort((a, b) => { 116 | const aw = getMetricsWeight(a.metric); 117 | const bw = getMetricsWeight(b.metric); 118 | return aw - bw; 119 | }); 120 | } 121 | 122 | function getMetricsWeight(name) { 123 | for(const [prefix, weight] of metricsWeight) { 124 | if(name.startsWith(prefix)) { 125 | return weight; 126 | } 127 | } 128 | return Infinity; 129 | } 130 | 131 | 132 | export function bytesToSize(bytes) { 133 | var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; 134 | if (bytes == 0) return '0 Byte'; 135 | var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); 136 | return (bytes / Math.pow(1024, i)).toFixed(2) + ' ' + sizes[i]; 137 | } 138 | 139 | export function humanizeMetricValue(metric) { 140 | const name = metric.metric; 141 | const value = metric.value; 142 | if(typeof value === 'number') { 143 | if(name.startsWith('node.v8')) { 144 | return bytesToSize(metric.value); 145 | } 146 | if(name === 'system.disk.partition.total' || name === 'system.disk.partition.free') { 147 | return bytesToSize(metric.value * 1024); 148 | } 149 | if(name.startsWith('system.mem.') && metric.value > 1) { 150 | return bytesToSize(metric.value * 1024); 151 | } 152 | if(name.endsWith('bytes')) { 153 | return bytesToSize(metric.value); 154 | } 155 | } 156 | return displayValue(value); 157 | } 158 | 159 | export function attachChildren (lead, spans) { 160 | const spanId = lead.context.spanId; 161 | const children = []; 162 | lead.rowKey = spanId; 163 | for(const span of spans) { 164 | if(span.context.parentId && span.context.parentId === spanId) { 165 | attachChildren(span, spans); 166 | children.push(span); 167 | } 168 | } 169 | if(children.length) { 170 | lead.children = children; 171 | } 172 | return lead; 173 | } 174 | 175 | export function attachChildrenTimeOrder(lead, spans) { 176 | 177 | const children1st = []; 178 | lead.rowKey = lead.context.spanId; 179 | for (let idx = 0, len = spans.length; idx < len; idx++) { 180 | if (idx === 0) { 181 | continue; 182 | } 183 | const span = spans[idx]; 184 | span.rowKey = span.context.spanId; 185 | children1st.push({ order: idx, span }); 186 | } 187 | 188 | const children2nd = children1st.sort(function(a, b) { 189 | if (a.span.timestamp < b.span.timestamp) return -1; 190 | if (a.span.timestamp > b.span.timestamp) return 1; 191 | return a.order - b.order; 192 | }); 193 | 194 | const children3rd = children2nd.map((wrapper) => { 195 | return wrapper.span; 196 | }); 197 | 198 | if (children3rd.length) { 199 | lead.children = children3rd; 200 | } 201 | return lead; 202 | 203 | } 204 | 205 | const tagsOrderMap = { 206 | 'http': [ 207 | 'http.status_code', 208 | 'http.url', 209 | 'http.method', 210 | 'error', 211 | ], 212 | 'http-client': [ 213 | 'http.status_code', 214 | 'http.hostname', 215 | 'http.port', 216 | 'http.path', 217 | 'http.method', 218 | 'error', 219 | ] 220 | }; 221 | export function orderTags(type, tagKeys) { 222 | 223 | if (!tagsOrderMap.hasOwnProperty(type)) { 224 | return tagKeys; 225 | } 226 | const order = tagsOrderMap[type]; 227 | 228 | const ret = []; 229 | 230 | for (const one of order) { 231 | if (tagKeys.indexOf(one) > -1) { 232 | ret.push(one); 233 | } 234 | } 235 | for (const key of tagKeys) { 236 | if (order.indexOf(key) < 0) { 237 | ret.push(key); 238 | } 239 | } 240 | 241 | return ret; 242 | 243 | } 244 | 245 | export function isErrorSpan(record) { 246 | return !!record.tags && record.tags.error && record.tags.error.value; 247 | } 248 | 249 | const SLOW_TRACE = 2; 250 | const ERROR_TRACE = 8; 251 | export function getTraceStatus(record) { 252 | const {status} = record; 253 | if (typeof status !== 'number') { 254 | return null; 255 | } 256 | let label = []; 257 | let color; 258 | 259 | 260 | if (status & SLOW_TRACE) { 261 | label.unshift('Slow'); 262 | color = 'rgb(255, 145, 0)'; 263 | } 264 | 265 | if (status & ERROR_TRACE) { 266 | label.unshift('Error'); 267 | color = '#f50'; 268 | } 269 | return { 270 | label: label.length ? label : null, color 271 | }; 272 | } 273 | 274 | const metricsGroupWeights = { 275 | 'node': 1, 276 | 'error': 2, 277 | 'system': 3, 278 | 'nginx': 4, 279 | 'http': 5, 280 | } 281 | export function sortMetricsGroups(groups) { 282 | return groups.sort((a, b) => { 283 | const aw = metricsGroupWeights[a.group] || Infinity; 284 | const bw = metricsGroupWeights[b.group] || Infinity; 285 | return aw - bw; 286 | }); 287 | } 288 | 289 | -------------------------------------------------------------------------------- /resource/chrome-devtools/InspectorBackendCommands.js: -------------------------------------------------------------------------------- 1 | // File is generated by devtools-frontend/scripts/build/code_generator_frontend.py 2 | 3 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | 8 | // Debugger. 9 | Protocol.inspectorBackend.registerEnum("Debugger.ScopeType", {Global: "global", Local: "local", With: "with", Closure: "closure", Catch: "catch", Block: "block", Script: "script", Eval: "eval", Module: "module"}); 10 | Protocol.inspectorBackend.registerEnum("Debugger.BreakLocationType", {DebuggerStatement: "debuggerStatement", Call: "call", Return: "return"}); 11 | Protocol.inspectorBackend.registerEvent("Debugger.breakpointResolved", ["breakpointId", "location"]); 12 | Protocol.inspectorBackend.registerEvent("Debugger.paused", ["callFrames", "reason", "data", "hitBreakpoints", "asyncStackTrace", "asyncStackTraceId", "asyncCallStackTraceId"]); 13 | Protocol.inspectorBackend.registerEvent("Debugger.resumed", []); 14 | Protocol.inspectorBackend.registerEvent("Debugger.scriptFailedToParse", ["scriptId", "url", "startLine", "startColumn", "endLine", "endColumn", "executionContextId", "hash", "executionContextAuxData", "sourceMapURL", "hasSourceURL", "isModule", "length", "stackTrace"]); 15 | Protocol.inspectorBackend.registerEvent("Debugger.scriptParsed", ["scriptId", "url", "startLine", "startColumn", "endLine", "endColumn", "executionContextId", "hash", "executionContextAuxData", "isLiveEdit", "sourceMapURL", "hasSourceURL", "isModule", "length", "stackTrace"]); 16 | Protocol.inspectorBackend.registerCommand("Debugger.continueToLocation", [{"name": "location", "type": "object", "optional": false}, {"name": "targetCallFrames", "type": "string", "optional": true}], [], false); 17 | Protocol.inspectorBackend.registerCommand("Debugger.disable", [], [], false); 18 | Protocol.inspectorBackend.registerCommand("Debugger.enable", [], ["debuggerId"], false); 19 | Protocol.inspectorBackend.registerCommand("Debugger.evaluateOnCallFrame", [{"name": "callFrameId", "type": "string", "optional": false}, {"name": "expression", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "includeCommandLineAPI", "type": "boolean", "optional": true}, {"name": "silent", "type": "boolean", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}, {"name": "generatePreview", "type": "boolean", "optional": true}, {"name": "throwOnSideEffect", "type": "boolean", "optional": true}], ["result", "exceptionDetails"], false); 20 | Protocol.inspectorBackend.registerCommand("Debugger.getPossibleBreakpoints", [{"name": "start", "type": "object", "optional": false}, {"name": "end", "type": "object", "optional": true}, {"name": "restrictToFunction", "type": "boolean", "optional": true}], ["locations"], false); 21 | Protocol.inspectorBackend.registerCommand("Debugger.getScriptSource", [{"name": "scriptId", "type": "string", "optional": false}], ["scriptSource"], false); 22 | Protocol.inspectorBackend.registerCommand("Debugger.getStackTrace", [{"name": "stackTraceId", "type": "object", "optional": false}], ["stackTrace"], false); 23 | Protocol.inspectorBackend.registerCommand("Debugger.pause", [], [], false); 24 | Protocol.inspectorBackend.registerCommand("Debugger.pauseOnAsyncCall", [{"name": "parentStackTraceId", "type": "object", "optional": false}], [], false); 25 | Protocol.inspectorBackend.registerCommand("Debugger.removeBreakpoint", [{"name": "breakpointId", "type": "string", "optional": false}], [], false); 26 | Protocol.inspectorBackend.registerCommand("Debugger.restartFrame", [{"name": "callFrameId", "type": "string", "optional": false}], ["callFrames", "asyncStackTrace", "asyncStackTraceId"], false); 27 | Protocol.inspectorBackend.registerCommand("Debugger.resume", [], [], false); 28 | Protocol.inspectorBackend.registerCommand("Debugger.scheduleStepIntoAsync", [], [], false); 29 | Protocol.inspectorBackend.registerCommand("Debugger.searchInContent", [{"name": "scriptId", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"], false); 30 | Protocol.inspectorBackend.registerCommand("Debugger.setAsyncCallStackDepth", [{"name": "maxDepth", "type": "number", "optional": false}], [], false); 31 | Protocol.inspectorBackend.registerCommand("Debugger.setBlackboxPatterns", [{"name": "patterns", "type": "object", "optional": false}], [], false); 32 | Protocol.inspectorBackend.registerCommand("Debugger.setBlackboxedRanges", [{"name": "scriptId", "type": "string", "optional": false}, {"name": "positions", "type": "object", "optional": false}], [], false); 33 | Protocol.inspectorBackend.registerCommand("Debugger.setBreakpoint", [{"name": "location", "type": "object", "optional": false}, {"name": "condition", "type": "string", "optional": true}], ["breakpointId", "actualLocation"], false); 34 | Protocol.inspectorBackend.registerCommand("Debugger.setBreakpointByUrl", [{"name": "lineNumber", "type": "number", "optional": false}, {"name": "url", "type": "string", "optional": true}, {"name": "urlRegex", "type": "string", "optional": true}, {"name": "scriptHash", "type": "string", "optional": true}, {"name": "columnNumber", "type": "number", "optional": true}, {"name": "condition", "type": "string", "optional": true}], ["breakpointId", "locations"], false); 35 | Protocol.inspectorBackend.registerCommand("Debugger.setBreakpointsActive", [{"name": "active", "type": "boolean", "optional": false}], [], false); 36 | Protocol.inspectorBackend.registerCommand("Debugger.setPauseOnExceptions", [{"name": "state", "type": "string", "optional": false}], [], false); 37 | Protocol.inspectorBackend.registerCommand("Debugger.setReturnValue", [{"name": "newValue", "type": "object", "optional": false}], [], false); 38 | Protocol.inspectorBackend.registerCommand("Debugger.setScriptSource", [{"name": "scriptId", "type": "string", "optional": false}, {"name": "scriptSource", "type": "string", "optional": false}, {"name": "dryRun", "type": "boolean", "optional": true}], ["callFrames", "stackChanged", "asyncStackTrace", "asyncStackTraceId", "exceptionDetails"], false); 39 | Protocol.inspectorBackend.registerCommand("Debugger.setSkipAllPauses", [{"name": "skip", "type": "boolean", "optional": false}], [], false); 40 | Protocol.inspectorBackend.registerCommand("Debugger.setVariableValue", [{"name": "scopeNumber", "type": "number", "optional": false}, {"name": "variableName", "type": "string", "optional": false}, {"name": "newValue", "type": "object", "optional": false}, {"name": "callFrameId", "type": "string", "optional": false}], [], false); 41 | Protocol.inspectorBackend.registerCommand("Debugger.stepInto", [{"name": "breakOnAsyncCall", "type": "boolean", "optional": true}], [], false); 42 | Protocol.inspectorBackend.registerCommand("Debugger.stepOut", [], [], false); 43 | Protocol.inspectorBackend.registerCommand("Debugger.stepOver", [], [], false); 44 | 45 | // HeapProfiler. 46 | Protocol.inspectorBackend.registerEvent("HeapProfiler.addHeapSnapshotChunk", ["chunk"]); 47 | Protocol.inspectorBackend.registerEvent("HeapProfiler.heapStatsUpdate", ["statsUpdate"]); 48 | Protocol.inspectorBackend.registerEvent("HeapProfiler.lastSeenObjectId", ["lastSeenObjectId", "timestamp"]); 49 | Protocol.inspectorBackend.registerEvent("HeapProfiler.reportHeapSnapshotProgress", ["done", "total", "finished"]); 50 | Protocol.inspectorBackend.registerEvent("HeapProfiler.resetProfiles", []); 51 | Protocol.inspectorBackend.registerCommand("HeapProfiler.addInspectedHeapObject", [{"name": "heapObjectId", "type": "string", "optional": false}], [], false); 52 | Protocol.inspectorBackend.registerCommand("HeapProfiler.collectGarbage", [], [], false); 53 | Protocol.inspectorBackend.registerCommand("HeapProfiler.disable", [], [], false); 54 | Protocol.inspectorBackend.registerCommand("HeapProfiler.enable", [], [], false); 55 | Protocol.inspectorBackend.registerCommand("HeapProfiler.getHeapObjectId", [{"name": "objectId", "type": "string", "optional": false}], ["heapSnapshotObjectId"], false); 56 | Protocol.inspectorBackend.registerCommand("HeapProfiler.getObjectByHeapObjectId", [{"name": "objectId", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}], ["result"], false); 57 | Protocol.inspectorBackend.registerCommand("HeapProfiler.getSamplingProfile", [], ["profile"], false); 58 | Protocol.inspectorBackend.registerCommand("HeapProfiler.startSampling", [{"name": "samplingInterval", "type": "number", "optional": true}], [], false); 59 | Protocol.inspectorBackend.registerCommand("HeapProfiler.startTrackingHeapObjects", [{"name": "trackAllocations", "type": "boolean", "optional": true}], [], false); 60 | Protocol.inspectorBackend.registerCommand("HeapProfiler.stopSampling", [], ["profile"], false); 61 | Protocol.inspectorBackend.registerCommand("HeapProfiler.stopTrackingHeapObjects", [{"name": "reportProgress", "type": "boolean", "optional": true}], [], false); 62 | Protocol.inspectorBackend.registerCommand("HeapProfiler.takeHeapSnapshot", [{"name": "reportProgress", "type": "boolean", "optional": true}], [], false); 63 | 64 | // Profiler. 65 | Protocol.inspectorBackend.registerEvent("Profiler.consoleProfileFinished", ["id", "location", "profile", "title"]); 66 | Protocol.inspectorBackend.registerEvent("Profiler.consoleProfileStarted", ["id", "location", "title"]); 67 | Protocol.inspectorBackend.registerCommand("Profiler.disable", [], [], false); 68 | Protocol.inspectorBackend.registerCommand("Profiler.enable", [], [], false); 69 | Protocol.inspectorBackend.registerCommand("Profiler.getBestEffortCoverage", [], ["result"], false); 70 | Protocol.inspectorBackend.registerCommand("Profiler.setSamplingInterval", [{"name": "interval", "type": "number", "optional": false}], [], false); 71 | Protocol.inspectorBackend.registerCommand("Profiler.start", [], [], false); 72 | Protocol.inspectorBackend.registerCommand("Profiler.startPreciseCoverage", [{"name": "callCount", "type": "boolean", "optional": true}, {"name": "detailed", "type": "boolean", "optional": true}], [], false); 73 | Protocol.inspectorBackend.registerCommand("Profiler.startTypeProfile", [], [], false); 74 | Protocol.inspectorBackend.registerCommand("Profiler.stop", [], ["profile"], false); 75 | Protocol.inspectorBackend.registerCommand("Profiler.stopPreciseCoverage", [], [], false); 76 | Protocol.inspectorBackend.registerCommand("Profiler.stopTypeProfile", [], [], false); 77 | Protocol.inspectorBackend.registerCommand("Profiler.takePreciseCoverage", [], ["result"], false); 78 | Protocol.inspectorBackend.registerCommand("Profiler.takeTypeProfile", [], ["result"], false); 79 | 80 | // Runtime. 81 | Protocol.inspectorBackend.registerEnum("Runtime.UnserializableValue", {Infinity: "Infinity", NaN: "NaN", NegativeInfinity: "-Infinity", Negative0: "-0"}); 82 | Protocol.inspectorBackend.registerEnum("Runtime.RemoteObjectType", {Object: "object", Function: "function", Undefined: "undefined", String: "string", Number: "number", Boolean: "boolean", Symbol: "symbol"}); 83 | Protocol.inspectorBackend.registerEnum("Runtime.RemoteObjectSubtype", {Array: "array", Null: "null", Node: "node", Regexp: "regexp", Date: "date", Map: "map", Set: "set", Weakmap: "weakmap", Weakset: "weakset", Iterator: "iterator", Generator: "generator", Error: "error", Proxy: "proxy", Promise: "promise", Typedarray: "typedarray"}); 84 | Protocol.inspectorBackend.registerEnum("Runtime.ObjectPreviewType", {Object: "object", Function: "function", Undefined: "undefined", String: "string", Number: "number", Boolean: "boolean", Symbol: "symbol"}); 85 | Protocol.inspectorBackend.registerEnum("Runtime.ObjectPreviewSubtype", {Array: "array", Null: "null", Node: "node", Regexp: "regexp", Date: "date", Map: "map", Set: "set", Weakmap: "weakmap", Weakset: "weakset", Iterator: "iterator", Generator: "generator", Error: "error"}); 86 | Protocol.inspectorBackend.registerEnum("Runtime.PropertyPreviewType", {Object: "object", Function: "function", Undefined: "undefined", String: "string", Number: "number", Boolean: "boolean", Symbol: "symbol", Accessor: "accessor"}); 87 | Protocol.inspectorBackend.registerEnum("Runtime.PropertyPreviewSubtype", {Array: "array", Null: "null", Node: "node", Regexp: "regexp", Date: "date", Map: "map", Set: "set", Weakmap: "weakmap", Weakset: "weakset", Iterator: "iterator", Generator: "generator", Error: "error"}); 88 | Protocol.inspectorBackend.registerEvent("Runtime.consoleAPICalled", ["type", "args", "executionContextId", "timestamp", "stackTrace", "context"]); 89 | Protocol.inspectorBackend.registerEvent("Runtime.exceptionRevoked", ["reason", "exceptionId"]); 90 | Protocol.inspectorBackend.registerEvent("Runtime.exceptionThrown", ["timestamp", "exceptionDetails"]); 91 | Protocol.inspectorBackend.registerEvent("Runtime.executionContextCreated", ["context"]); 92 | Protocol.inspectorBackend.registerEvent("Runtime.executionContextDestroyed", ["executionContextId"]); 93 | Protocol.inspectorBackend.registerEvent("Runtime.executionContextsCleared", []); 94 | Protocol.inspectorBackend.registerEvent("Runtime.inspectRequested", ["object", "hints"]); 95 | Protocol.inspectorBackend.registerCommand("Runtime.awaitPromise", [{"name": "promiseObjectId", "type": "string", "optional": false}, {"name": "returnByValue", "type": "boolean", "optional": true}, {"name": "generatePreview", "type": "boolean", "optional": true}], ["result", "exceptionDetails"], false); 96 | Protocol.inspectorBackend.registerCommand("Runtime.callFunctionOn", [{"name": "functionDeclaration", "type": "string", "optional": false}, {"name": "objectId", "type": "string", "optional": true}, {"name": "arguments", "type": "object", "optional": true}, {"name": "silent", "type": "boolean", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}, {"name": "generatePreview", "type": "boolean", "optional": true}, {"name": "userGesture", "type": "boolean", "optional": true}, {"name": "awaitPromise", "type": "boolean", "optional": true}, {"name": "executionContextId", "type": "number", "optional": true}, {"name": "objectGroup", "type": "string", "optional": true}], ["result", "exceptionDetails"], false); 97 | Protocol.inspectorBackend.registerCommand("Runtime.compileScript", [{"name": "expression", "type": "string", "optional": false}, {"name": "sourceURL", "type": "string", "optional": false}, {"name": "persistScript", "type": "boolean", "optional": false}, {"name": "executionContextId", "type": "number", "optional": true}], ["scriptId", "exceptionDetails"], false); 98 | Protocol.inspectorBackend.registerCommand("Runtime.disable", [], [], false); 99 | Protocol.inspectorBackend.registerCommand("Runtime.discardConsoleEntries", [], [], false); 100 | Protocol.inspectorBackend.registerCommand("Runtime.enable", [], [], false); 101 | Protocol.inspectorBackend.registerCommand("Runtime.evaluate", [{"name": "expression", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "includeCommandLineAPI", "type": "boolean", "optional": true}, {"name": "silent", "type": "boolean", "optional": true}, {"name": "contextId", "type": "number", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}, {"name": "generatePreview", "type": "boolean", "optional": true}, {"name": "userGesture", "type": "boolean", "optional": true}, {"name": "awaitPromise", "type": "boolean", "optional": true}], ["result", "exceptionDetails"], false); 102 | Protocol.inspectorBackend.registerCommand("Runtime.getProperties", [{"name": "objectId", "type": "string", "optional": false}, {"name": "ownProperties", "type": "boolean", "optional": true}, {"name": "accessorPropertiesOnly", "type": "boolean", "optional": true}, {"name": "generatePreview", "type": "boolean", "optional": true}], ["result", "internalProperties", "exceptionDetails"], false); 103 | Protocol.inspectorBackend.registerCommand("Runtime.globalLexicalScopeNames", [{"name": "executionContextId", "type": "number", "optional": true}], ["names"], false); 104 | Protocol.inspectorBackend.registerCommand("Runtime.queryObjects", [{"name": "prototypeObjectId", "type": "string", "optional": false}], ["objects"], false); 105 | Protocol.inspectorBackend.registerCommand("Runtime.releaseObject", [{"name": "objectId", "type": "string", "optional": false}], [], false); 106 | Protocol.inspectorBackend.registerCommand("Runtime.releaseObjectGroup", [{"name": "objectGroup", "type": "string", "optional": false}], [], false); 107 | Protocol.inspectorBackend.registerCommand("Runtime.runIfWaitingForDebugger", [], [], false); 108 | Protocol.inspectorBackend.registerCommand("Runtime.runScript", [{"name": "scriptId", "type": "string", "optional": false}, {"name": "executionContextId", "type": "number", "optional": true}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "silent", "type": "boolean", "optional": true}, {"name": "includeCommandLineAPI", "type": "boolean", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}, {"name": "generatePreview", "type": "boolean", "optional": true}, {"name": "awaitPromise", "type": "boolean", "optional": true}], ["result", "exceptionDetails"], false); 109 | Protocol.inspectorBackend.registerCommand("Runtime.setCustomObjectFormatterEnabled", [{"name": "enabled", "type": "boolean", "optional": false}], [], false); 110 | 111 | // Schema. 112 | Protocol.inspectorBackend.registerCommand("Schema.getDomains", [], ["domains"], false); 113 | 114 | // Accessibility. 115 | Protocol.inspectorBackend.registerEnum("Accessibility.AXValueType", {Boolean: "boolean", Tristate: "tristate", BooleanOrUndefined: "booleanOrUndefined", Idref: "idref", IdrefList: "idrefList", Integer: "integer", Node: "node", NodeList: "nodeList", Number: "number", String: "string", ComputedString: "computedString", Token: "token", TokenList: "tokenList", DomRelation: "domRelation", Role: "role", InternalRole: "internalRole", ValueUndefined: "valueUndefined"}); 116 | Protocol.inspectorBackend.registerEnum("Accessibility.AXValueSourceType", {Attribute: "attribute", Implicit: "implicit", Style: "style", Contents: "contents", Placeholder: "placeholder", RelatedElement: "relatedElement"}); 117 | Protocol.inspectorBackend.registerEnum("Accessibility.AXValueNativeSourceType", {Figcaption: "figcaption", Label: "label", Labelfor: "labelfor", Labelwrapped: "labelwrapped", Legend: "legend", Tablecaption: "tablecaption", Title: "title", Other: "other"}); 118 | Protocol.inspectorBackend.registerEnum("Accessibility.AXPropertyName", {Busy: "busy", Disabled: "disabled", Hidden: "hidden", HiddenRoot: "hiddenRoot", Invalid: "invalid", Keyshortcuts: "keyshortcuts", Roledescription: "roledescription", Live: "live", Atomic: "atomic", Relevant: "relevant", Root: "root", Autocomplete: "autocomplete", Haspopup: "haspopup", Level: "level", Multiselectable: "multiselectable", Orientation: "orientation", Multiline: "multiline", Readonly: "readonly", Required: "required", Valuemin: "valuemin", Valuemax: "valuemax", Valuetext: "valuetext", Checked: "checked", Expanded: "expanded", Modal: "modal", Pressed: "pressed", Selected: "selected", Activedescendant: "activedescendant", Controls: "controls", Describedby: "describedby", Details: "details", Errormessage: "errormessage", Flowto: "flowto", Labelledby: "labelledby", Owns: "owns"}); 119 | Protocol.inspectorBackend.registerCommand("Accessibility.getPartialAXTree", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "fetchRelatives", "type": "boolean", "optional": true}], ["nodes"], false); 120 | 121 | // Animation. 122 | Protocol.inspectorBackend.registerEnum("Animation.AnimationType", {CSSTransition: "CSSTransition", CSSAnimation: "CSSAnimation", WebAnimation: "WebAnimation"}); 123 | Protocol.inspectorBackend.registerEvent("Animation.animationCanceled", ["id"]); 124 | Protocol.inspectorBackend.registerEvent("Animation.animationCreated", ["id"]); 125 | Protocol.inspectorBackend.registerEvent("Animation.animationStarted", ["animation"]); 126 | Protocol.inspectorBackend.registerCommand("Animation.disable", [], [], false); 127 | Protocol.inspectorBackend.registerCommand("Animation.enable", [], [], false); 128 | Protocol.inspectorBackend.registerCommand("Animation.getCurrentTime", [{"name": "id", "type": "string", "optional": false}], ["currentTime"], false); 129 | Protocol.inspectorBackend.registerCommand("Animation.getPlaybackRate", [], ["playbackRate"], false); 130 | Protocol.inspectorBackend.registerCommand("Animation.releaseAnimations", [{"name": "animations", "type": "object", "optional": false}], [], false); 131 | Protocol.inspectorBackend.registerCommand("Animation.resolveAnimation", [{"name": "animationId", "type": "string", "optional": false}], ["remoteObject"], false); 132 | Protocol.inspectorBackend.registerCommand("Animation.seekAnimations", [{"name": "animations", "type": "object", "optional": false}, {"name": "currentTime", "type": "number", "optional": false}], [], false); 133 | Protocol.inspectorBackend.registerCommand("Animation.setPaused", [{"name": "animations", "type": "object", "optional": false}, {"name": "paused", "type": "boolean", "optional": false}], [], false); 134 | Protocol.inspectorBackend.registerCommand("Animation.setPlaybackRate", [{"name": "playbackRate", "type": "number", "optional": false}], [], false); 135 | Protocol.inspectorBackend.registerCommand("Animation.setTiming", [{"name": "animationId", "type": "string", "optional": false}, {"name": "duration", "type": "number", "optional": false}, {"name": "delay", "type": "number", "optional": false}], [], false); 136 | 137 | // ApplicationCache. 138 | Protocol.inspectorBackend.registerEvent("ApplicationCache.applicationCacheStatusUpdated", ["frameId", "manifestURL", "status"]); 139 | Protocol.inspectorBackend.registerEvent("ApplicationCache.networkStateUpdated", ["isNowOnline"]); 140 | Protocol.inspectorBackend.registerCommand("ApplicationCache.enable", [], [], false); 141 | Protocol.inspectorBackend.registerCommand("ApplicationCache.getApplicationCacheForFrame", [{"name": "frameId", "type": "string", "optional": false}], ["applicationCache"], false); 142 | Protocol.inspectorBackend.registerCommand("ApplicationCache.getFramesWithManifests", [], ["frameIds"], false); 143 | Protocol.inspectorBackend.registerCommand("ApplicationCache.getManifestForFrame", [{"name": "frameId", "type": "string", "optional": false}], ["manifestURL"], false); 144 | 145 | // Audits. 146 | Protocol.inspectorBackend.registerCommand("Audits.getEncodedResponse", [{"name": "requestId", "type": "string", "optional": false}, {"name": "encoding", "type": "string", "optional": false}, {"name": "quality", "type": "number", "optional": true}, {"name": "sizeOnly", "type": "boolean", "optional": true}], ["body", "originalSize", "encodedSize"], false); 147 | 148 | // Browser. 149 | Protocol.inspectorBackend.registerEnum("Browser.WindowState", {Normal: "normal", Minimized: "minimized", Maximized: "maximized", Fullscreen: "fullscreen"}); 150 | Protocol.inspectorBackend.registerCommand("Browser.close", [], [], false); 151 | Protocol.inspectorBackend.registerCommand("Browser.getVersion", [], ["protocolVersion", "product", "revision", "userAgent", "jsVersion"], false); 152 | Protocol.inspectorBackend.registerCommand("Browser.getWindowBounds", [{"name": "windowId", "type": "number", "optional": false}], ["bounds"], false); 153 | Protocol.inspectorBackend.registerCommand("Browser.getWindowForTarget", [{"name": "targetId", "type": "string", "optional": false}], ["windowId", "bounds"], false); 154 | Protocol.inspectorBackend.registerCommand("Browser.setWindowBounds", [{"name": "windowId", "type": "number", "optional": false}, {"name": "bounds", "type": "object", "optional": false}], [], false); 155 | 156 | // CSS. 157 | Protocol.inspectorBackend.registerEnum("CSS.StyleSheetOrigin", {Injected: "injected", UserAgent: "user-agent", Inspector: "inspector", Regular: "regular"}); 158 | Protocol.inspectorBackend.registerEnum("CSS.CSSMediaSource", {MediaRule: "mediaRule", ImportRule: "importRule", LinkedSheet: "linkedSheet", InlineSheet: "inlineSheet"}); 159 | Protocol.inspectorBackend.registerEvent("CSS.fontsUpdated", []); 160 | Protocol.inspectorBackend.registerEvent("CSS.mediaQueryResultChanged", []); 161 | Protocol.inspectorBackend.registerEvent("CSS.styleSheetAdded", ["header"]); 162 | Protocol.inspectorBackend.registerEvent("CSS.styleSheetChanged", ["styleSheetId"]); 163 | Protocol.inspectorBackend.registerEvent("CSS.styleSheetRemoved", ["styleSheetId"]); 164 | Protocol.inspectorBackend.registerCommand("CSS.addRule", [{"name": "styleSheetId", "type": "string", "optional": false}, {"name": "ruleText", "type": "string", "optional": false}, {"name": "location", "type": "object", "optional": false}], ["rule"], false); 165 | Protocol.inspectorBackend.registerCommand("CSS.collectClassNames", [{"name": "styleSheetId", "type": "string", "optional": false}], ["classNames"], false); 166 | Protocol.inspectorBackend.registerCommand("CSS.createStyleSheet", [{"name": "frameId", "type": "string", "optional": false}], ["styleSheetId"], false); 167 | Protocol.inspectorBackend.registerCommand("CSS.disable", [], [], false); 168 | Protocol.inspectorBackend.registerCommand("CSS.enable", [], [], false); 169 | Protocol.inspectorBackend.registerCommand("CSS.forcePseudoState", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "forcedPseudoClasses", "type": "object", "optional": false}], [], false); 170 | Protocol.inspectorBackend.registerCommand("CSS.getBackgroundColors", [{"name": "nodeId", "type": "number", "optional": false}], ["backgroundColors", "computedFontSize", "computedFontWeight", "computedBodyFontSize"], false); 171 | Protocol.inspectorBackend.registerCommand("CSS.getComputedStyleForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["computedStyle"], false); 172 | Protocol.inspectorBackend.registerCommand("CSS.getInlineStylesForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["inlineStyle", "attributesStyle"], false); 173 | Protocol.inspectorBackend.registerCommand("CSS.getMatchedStylesForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["inlineStyle", "attributesStyle", "matchedCSSRules", "pseudoElements", "inherited", "cssKeyframesRules"], false); 174 | Protocol.inspectorBackend.registerCommand("CSS.getMediaQueries", [], ["medias"], false); 175 | Protocol.inspectorBackend.registerCommand("CSS.getPlatformFontsForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["fonts"], false); 176 | Protocol.inspectorBackend.registerCommand("CSS.getStyleSheetText", [{"name": "styleSheetId", "type": "string", "optional": false}], ["text"], false); 177 | Protocol.inspectorBackend.registerCommand("CSS.setEffectivePropertyValueForNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "propertyName", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}], [], false); 178 | Protocol.inspectorBackend.registerCommand("CSS.setKeyframeKey", [{"name": "styleSheetId", "type": "string", "optional": false}, {"name": "range", "type": "object", "optional": false}, {"name": "keyText", "type": "string", "optional": false}], ["keyText"], false); 179 | Protocol.inspectorBackend.registerCommand("CSS.setMediaText", [{"name": "styleSheetId", "type": "string", "optional": false}, {"name": "range", "type": "object", "optional": false}, {"name": "text", "type": "string", "optional": false}], ["media"], false); 180 | Protocol.inspectorBackend.registerCommand("CSS.setRuleSelector", [{"name": "styleSheetId", "type": "string", "optional": false}, {"name": "range", "type": "object", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["selectorList"], false); 181 | Protocol.inspectorBackend.registerCommand("CSS.setStyleSheetText", [{"name": "styleSheetId", "type": "string", "optional": false}, {"name": "text", "type": "string", "optional": false}], ["sourceMapURL"], false); 182 | Protocol.inspectorBackend.registerCommand("CSS.setStyleTexts", [{"name": "edits", "type": "object", "optional": false}], ["styles"], false); 183 | Protocol.inspectorBackend.registerCommand("CSS.startRuleUsageTracking", [], [], false); 184 | Protocol.inspectorBackend.registerCommand("CSS.stopRuleUsageTracking", [], ["ruleUsage"], false); 185 | Protocol.inspectorBackend.registerCommand("CSS.takeCoverageDelta", [], ["coverage"], false); 186 | 187 | // CacheStorage. 188 | Protocol.inspectorBackend.registerCommand("CacheStorage.deleteCache", [{"name": "cacheId", "type": "string", "optional": false}], [], false); 189 | Protocol.inspectorBackend.registerCommand("CacheStorage.deleteEntry", [{"name": "cacheId", "type": "string", "optional": false}, {"name": "request", "type": "string", "optional": false}], [], false); 190 | Protocol.inspectorBackend.registerCommand("CacheStorage.requestCacheNames", [{"name": "securityOrigin", "type": "string", "optional": false}], ["caches"], false); 191 | Protocol.inspectorBackend.registerCommand("CacheStorage.requestCachedResponse", [{"name": "cacheId", "type": "string", "optional": false}, {"name": "requestURL", "type": "string", "optional": false}], ["response"], false); 192 | Protocol.inspectorBackend.registerCommand("CacheStorage.requestEntries", [{"name": "cacheId", "type": "string", "optional": false}, {"name": "skipCount", "type": "number", "optional": false}, {"name": "pageSize", "type": "number", "optional": false}], ["cacheDataEntries", "hasMore"], false); 193 | 194 | // DOM. 195 | Protocol.inspectorBackend.registerEnum("DOM.PseudoType", {FirstLine: "first-line", FirstLetter: "first-letter", Before: "before", After: "after", Backdrop: "backdrop", Selection: "selection", FirstLineInherited: "first-line-inherited", Scrollbar: "scrollbar", ScrollbarThumb: "scrollbar-thumb", ScrollbarButton: "scrollbar-button", ScrollbarTrack: "scrollbar-track", ScrollbarTrackPiece: "scrollbar-track-piece", ScrollbarCorner: "scrollbar-corner", Resizer: "resizer", InputListButton: "input-list-button"}); 196 | Protocol.inspectorBackend.registerEnum("DOM.ShadowRootType", {UserAgent: "user-agent", Open: "open", Closed: "closed"}); 197 | Protocol.inspectorBackend.registerEvent("DOM.attributeModified", ["nodeId", "name", "value"]); 198 | Protocol.inspectorBackend.registerEvent("DOM.attributeRemoved", ["nodeId", "name"]); 199 | Protocol.inspectorBackend.registerEvent("DOM.characterDataModified", ["nodeId", "characterData"]); 200 | Protocol.inspectorBackend.registerEvent("DOM.childNodeCountUpdated", ["nodeId", "childNodeCount"]); 201 | Protocol.inspectorBackend.registerEvent("DOM.childNodeInserted", ["parentNodeId", "previousNodeId", "node"]); 202 | Protocol.inspectorBackend.registerEvent("DOM.childNodeRemoved", ["parentNodeId", "nodeId"]); 203 | Protocol.inspectorBackend.registerEvent("DOM.distributedNodesUpdated", ["insertionPointId", "distributedNodes"]); 204 | Protocol.inspectorBackend.registerEvent("DOM.documentUpdated", []); 205 | Protocol.inspectorBackend.registerEvent("DOM.inlineStyleInvalidated", ["nodeIds"]); 206 | Protocol.inspectorBackend.registerEvent("DOM.pseudoElementAdded", ["parentId", "pseudoElement"]); 207 | Protocol.inspectorBackend.registerEvent("DOM.pseudoElementRemoved", ["parentId", "pseudoElementId"]); 208 | Protocol.inspectorBackend.registerEvent("DOM.setChildNodes", ["parentId", "nodes"]); 209 | Protocol.inspectorBackend.registerEvent("DOM.shadowRootPopped", ["hostId", "rootId"]); 210 | Protocol.inspectorBackend.registerEvent("DOM.shadowRootPushed", ["hostId", "root"]); 211 | Protocol.inspectorBackend.registerCommand("DOM.collectClassNamesFromSubtree", [{"name": "nodeId", "type": "number", "optional": false}], ["classNames"], false); 212 | Protocol.inspectorBackend.registerCommand("DOM.copyTo", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "targetNodeId", "type": "number", "optional": false}, {"name": "insertBeforeNodeId", "type": "number", "optional": true}], ["nodeId"], false); 213 | Protocol.inspectorBackend.registerCommand("DOM.describeNode", [{"name": "nodeId", "type": "number", "optional": true}, {"name": "backendNodeId", "type": "number", "optional": true}, {"name": "objectId", "type": "string", "optional": true}, {"name": "depth", "type": "number", "optional": true}, {"name": "pierce", "type": "boolean", "optional": true}], ["node"], false); 214 | Protocol.inspectorBackend.registerCommand("DOM.disable", [], [], false); 215 | Protocol.inspectorBackend.registerCommand("DOM.discardSearchResults", [{"name": "searchId", "type": "string", "optional": false}], [], false); 216 | Protocol.inspectorBackend.registerCommand("DOM.enable", [], [], false); 217 | Protocol.inspectorBackend.registerCommand("DOM.focus", [{"name": "nodeId", "type": "number", "optional": true}, {"name": "backendNodeId", "type": "number", "optional": true}, {"name": "objectId", "type": "string", "optional": true}], [], false); 218 | Protocol.inspectorBackend.registerCommand("DOM.getAttributes", [{"name": "nodeId", "type": "number", "optional": false}], ["attributes"], false); 219 | Protocol.inspectorBackend.registerCommand("DOM.getBoxModel", [{"name": "nodeId", "type": "number", "optional": true}, {"name": "backendNodeId", "type": "number", "optional": true}, {"name": "objectId", "type": "string", "optional": true}], ["model"], false); 220 | Protocol.inspectorBackend.registerCommand("DOM.getDocument", [{"name": "depth", "type": "number", "optional": true}, {"name": "pierce", "type": "boolean", "optional": true}], ["root"], false); 221 | Protocol.inspectorBackend.registerCommand("DOM.getFlattenedDocument", [{"name": "depth", "type": "number", "optional": true}, {"name": "pierce", "type": "boolean", "optional": true}], ["nodes"], false); 222 | Protocol.inspectorBackend.registerCommand("DOM.getNodeForLocation", [{"name": "x", "type": "number", "optional": false}, {"name": "y", "type": "number", "optional": false}, {"name": "includeUserAgentShadowDOM", "type": "boolean", "optional": true}], ["nodeId"], false); 223 | Protocol.inspectorBackend.registerCommand("DOM.getOuterHTML", [{"name": "nodeId", "type": "number", "optional": true}, {"name": "backendNodeId", "type": "number", "optional": true}, {"name": "objectId", "type": "string", "optional": true}], ["outerHTML"], false); 224 | Protocol.inspectorBackend.registerCommand("DOM.getRelayoutBoundary", [{"name": "nodeId", "type": "number", "optional": false}], ["nodeId"], false); 225 | Protocol.inspectorBackend.registerCommand("DOM.getSearchResults", [{"name": "searchId", "type": "string", "optional": false}, {"name": "fromIndex", "type": "number", "optional": false}, {"name": "toIndex", "type": "number", "optional": false}], ["nodeIds"], false); 226 | Protocol.inspectorBackend.registerCommand("DOM.hideHighlight", [], [], false); 227 | Protocol.inspectorBackend.registerCommand("DOM.highlightNode", [], [], false); 228 | Protocol.inspectorBackend.registerCommand("DOM.highlightRect", [], [], false); 229 | Protocol.inspectorBackend.registerCommand("DOM.markUndoableState", [], [], false); 230 | Protocol.inspectorBackend.registerCommand("DOM.moveTo", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "targetNodeId", "type": "number", "optional": false}, {"name": "insertBeforeNodeId", "type": "number", "optional": true}], ["nodeId"], false); 231 | Protocol.inspectorBackend.registerCommand("DOM.performSearch", [{"name": "query", "type": "string", "optional": false}, {"name": "includeUserAgentShadowDOM", "type": "boolean", "optional": true}], ["searchId", "resultCount"], false); 232 | Protocol.inspectorBackend.registerCommand("DOM.pushNodeByPathToFrontend", [{"name": "path", "type": "string", "optional": false}], ["nodeId"], false); 233 | Protocol.inspectorBackend.registerCommand("DOM.pushNodesByBackendIdsToFrontend", [{"name": "backendNodeIds", "type": "object", "optional": false}], ["nodeIds"], false); 234 | Protocol.inspectorBackend.registerCommand("DOM.querySelector", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["nodeId"], false); 235 | Protocol.inspectorBackend.registerCommand("DOM.querySelectorAll", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["nodeIds"], false); 236 | Protocol.inspectorBackend.registerCommand("DOM.redo", [], [], false); 237 | Protocol.inspectorBackend.registerCommand("DOM.removeAttribute", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}], [], false); 238 | Protocol.inspectorBackend.registerCommand("DOM.removeNode", [{"name": "nodeId", "type": "number", "optional": false}], [], false); 239 | Protocol.inspectorBackend.registerCommand("DOM.requestChildNodes", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "depth", "type": "number", "optional": true}, {"name": "pierce", "type": "boolean", "optional": true}], [], false); 240 | Protocol.inspectorBackend.registerCommand("DOM.requestNode", [{"name": "objectId", "type": "string", "optional": false}], ["nodeId"], false); 241 | Protocol.inspectorBackend.registerCommand("DOM.resolveNode", [{"name": "nodeId", "type": "number", "optional": true}, {"name": "backendNodeId", "type": "number", "optional": true}, {"name": "objectGroup", "type": "string", "optional": true}], ["object"], false); 242 | Protocol.inspectorBackend.registerCommand("DOM.setAttributeValue", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}], [], false); 243 | Protocol.inspectorBackend.registerCommand("DOM.setAttributesAsText", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "text", "type": "string", "optional": false}, {"name": "name", "type": "string", "optional": true}], [], false); 244 | Protocol.inspectorBackend.registerCommand("DOM.setFileInputFiles", [{"name": "files", "type": "object", "optional": false}, {"name": "nodeId", "type": "number", "optional": true}, {"name": "backendNodeId", "type": "number", "optional": true}, {"name": "objectId", "type": "string", "optional": true}], [], false); 245 | Protocol.inspectorBackend.registerCommand("DOM.setInspectedNode", [{"name": "nodeId", "type": "number", "optional": false}], [], false); 246 | Protocol.inspectorBackend.registerCommand("DOM.setNodeName", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}], ["nodeId"], false); 247 | Protocol.inspectorBackend.registerCommand("DOM.setNodeValue", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "value", "type": "string", "optional": false}], [], false); 248 | Protocol.inspectorBackend.registerCommand("DOM.setOuterHTML", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "outerHTML", "type": "string", "optional": false}], [], false); 249 | Protocol.inspectorBackend.registerCommand("DOM.undo", [], [], false); 250 | 251 | // DOMDebugger. 252 | Protocol.inspectorBackend.registerEnum("DOMDebugger.DOMBreakpointType", {SubtreeModified: "subtree-modified", AttributeModified: "attribute-modified", NodeRemoved: "node-removed"}); 253 | Protocol.inspectorBackend.registerCommand("DOMDebugger.getEventListeners", [{"name": "objectId", "type": "string", "optional": false}, {"name": "depth", "type": "number", "optional": true}, {"name": "pierce", "type": "boolean", "optional": true}], ["listeners"], false); 254 | Protocol.inspectorBackend.registerCommand("DOMDebugger.removeDOMBreakpoint", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "type", "type": "string", "optional": false}], [], false); 255 | Protocol.inspectorBackend.registerCommand("DOMDebugger.removeEventListenerBreakpoint", [{"name": "eventName", "type": "string", "optional": false}, {"name": "targetName", "type": "string", "optional": true}], [], false); 256 | Protocol.inspectorBackend.registerCommand("DOMDebugger.removeInstrumentationBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], [], false); 257 | Protocol.inspectorBackend.registerCommand("DOMDebugger.removeXHRBreakpoint", [{"name": "url", "type": "string", "optional": false}], [], false); 258 | Protocol.inspectorBackend.registerCommand("DOMDebugger.setDOMBreakpoint", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "type", "type": "string", "optional": false}], [], false); 259 | Protocol.inspectorBackend.registerCommand("DOMDebugger.setEventListenerBreakpoint", [{"name": "eventName", "type": "string", "optional": false}, {"name": "targetName", "type": "string", "optional": true}], [], false); 260 | Protocol.inspectorBackend.registerCommand("DOMDebugger.setInstrumentationBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], [], false); 261 | Protocol.inspectorBackend.registerCommand("DOMDebugger.setXHRBreakpoint", [{"name": "url", "type": "string", "optional": false}], [], false); 262 | 263 | // DOMSnapshot. 264 | Protocol.inspectorBackend.registerCommand("DOMSnapshot.getSnapshot", [{"name": "computedStyleWhitelist", "type": "object", "optional": false}], ["domNodes", "layoutTreeNodes", "computedStyles"], false); 265 | 266 | // DOMStorage. 267 | Protocol.inspectorBackend.registerEvent("DOMStorage.domStorageItemAdded", ["storageId", "key", "newValue"]); 268 | Protocol.inspectorBackend.registerEvent("DOMStorage.domStorageItemRemoved", ["storageId", "key"]); 269 | Protocol.inspectorBackend.registerEvent("DOMStorage.domStorageItemUpdated", ["storageId", "key", "oldValue", "newValue"]); 270 | Protocol.inspectorBackend.registerEvent("DOMStorage.domStorageItemsCleared", ["storageId"]); 271 | Protocol.inspectorBackend.registerCommand("DOMStorage.clear", [{"name": "storageId", "type": "object", "optional": false}], [], false); 272 | Protocol.inspectorBackend.registerCommand("DOMStorage.disable", [], [], false); 273 | Protocol.inspectorBackend.registerCommand("DOMStorage.enable", [], [], false); 274 | Protocol.inspectorBackend.registerCommand("DOMStorage.getDOMStorageItems", [{"name": "storageId", "type": "object", "optional": false}], ["entries"], false); 275 | Protocol.inspectorBackend.registerCommand("DOMStorage.removeDOMStorageItem", [{"name": "storageId", "type": "object", "optional": false}, {"name": "key", "type": "string", "optional": false}], [], false); 276 | Protocol.inspectorBackend.registerCommand("DOMStorage.setDOMStorageItem", [{"name": "storageId", "type": "object", "optional": false}, {"name": "key", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}], [], false); 277 | 278 | // Database. 279 | Protocol.inspectorBackend.registerEvent("Database.addDatabase", ["database"]); 280 | Protocol.inspectorBackend.registerCommand("Database.disable", [], [], false); 281 | Protocol.inspectorBackend.registerCommand("Database.enable", [], [], false); 282 | Protocol.inspectorBackend.registerCommand("Database.executeSQL", [{"name": "databaseId", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["columnNames", "values", "sqlError"], false); 283 | Protocol.inspectorBackend.registerCommand("Database.getDatabaseTableNames", [{"name": "databaseId", "type": "string", "optional": false}], ["tableNames"], false); 284 | 285 | // DeviceOrientation. 286 | Protocol.inspectorBackend.registerCommand("DeviceOrientation.clearDeviceOrientationOverride", [], [], false); 287 | Protocol.inspectorBackend.registerCommand("DeviceOrientation.setDeviceOrientationOverride", [{"name": "alpha", "type": "number", "optional": false}, {"name": "beta", "type": "number", "optional": false}, {"name": "gamma", "type": "number", "optional": false}], [], false); 288 | 289 | // Emulation. 290 | Protocol.inspectorBackend.registerEnum("Emulation.ScreenOrientationType", {PortraitPrimary: "portraitPrimary", PortraitSecondary: "portraitSecondary", LandscapePrimary: "landscapePrimary", LandscapeSecondary: "landscapeSecondary"}); 291 | Protocol.inspectorBackend.registerEnum("Emulation.VirtualTimePolicy", {Advance: "advance", Pause: "pause", PauseIfNetworkFetchesPending: "pauseIfNetworkFetchesPending"}); 292 | Protocol.inspectorBackend.registerEvent("Emulation.virtualTimeAdvanced", ["virtualTimeElapsed"]); 293 | Protocol.inspectorBackend.registerEvent("Emulation.virtualTimeBudgetExpired", []); 294 | Protocol.inspectorBackend.registerEvent("Emulation.virtualTimePaused", ["virtualTimeElapsed"]); 295 | Protocol.inspectorBackend.registerCommand("Emulation.canEmulate", [], ["result"], false); 296 | Protocol.inspectorBackend.registerCommand("Emulation.clearDeviceMetricsOverride", [], [], false); 297 | Protocol.inspectorBackend.registerCommand("Emulation.clearGeolocationOverride", [], [], false); 298 | Protocol.inspectorBackend.registerCommand("Emulation.resetPageScaleFactor", [], [], false); 299 | Protocol.inspectorBackend.registerCommand("Emulation.setCPUThrottlingRate", [{"name": "rate", "type": "number", "optional": false}], [], false); 300 | Protocol.inspectorBackend.registerCommand("Emulation.setDefaultBackgroundColorOverride", [{"name": "color", "type": "object", "optional": true}], [], false); 301 | Protocol.inspectorBackend.registerCommand("Emulation.setDeviceMetricsOverride", [{"name": "width", "type": "number", "optional": false}, {"name": "height", "type": "number", "optional": false}, {"name": "deviceScaleFactor", "type": "number", "optional": false}, {"name": "mobile", "type": "boolean", "optional": false}, {"name": "scale", "type": "number", "optional": true}, {"name": "screenWidth", "type": "number", "optional": true}, {"name": "screenHeight", "type": "number", "optional": true}, {"name": "positionX", "type": "number", "optional": true}, {"name": "positionY", "type": "number", "optional": true}, {"name": "dontSetVisibleSize", "type": "boolean", "optional": true}, {"name": "screenOrientation", "type": "object", "optional": true}, {"name": "viewport", "type": "object", "optional": true}], [], false); 302 | Protocol.inspectorBackend.registerCommand("Emulation.setEmitTouchEventsForMouse", [{"name": "enabled", "type": "boolean", "optional": false}, {"name": "configuration", "type": "string", "optional": true}], [], false); 303 | Protocol.inspectorBackend.registerCommand("Emulation.setEmulatedMedia", [{"name": "media", "type": "string", "optional": false}], [], false); 304 | Protocol.inspectorBackend.registerCommand("Emulation.setGeolocationOverride", [{"name": "latitude", "type": "number", "optional": true}, {"name": "longitude", "type": "number", "optional": true}, {"name": "accuracy", "type": "number", "optional": true}], [], false); 305 | Protocol.inspectorBackend.registerCommand("Emulation.setNavigatorOverrides", [{"name": "platform", "type": "string", "optional": false}], [], false); 306 | Protocol.inspectorBackend.registerCommand("Emulation.setPageScaleFactor", [{"name": "pageScaleFactor", "type": "number", "optional": false}], [], false); 307 | Protocol.inspectorBackend.registerCommand("Emulation.setScriptExecutionDisabled", [{"name": "value", "type": "boolean", "optional": false}], [], false); 308 | Protocol.inspectorBackend.registerCommand("Emulation.setTouchEmulationEnabled", [{"name": "enabled", "type": "boolean", "optional": false}, {"name": "maxTouchPoints", "type": "number", "optional": true}], [], false); 309 | Protocol.inspectorBackend.registerCommand("Emulation.setVirtualTimePolicy", [{"name": "policy", "type": "string", "optional": false}, {"name": "budget", "type": "number", "optional": true}, {"name": "maxVirtualTimeTaskStarvationCount", "type": "number", "optional": true}], ["virtualTimeBase"], false); 310 | Protocol.inspectorBackend.registerCommand("Emulation.setVisibleSize", [{"name": "width", "type": "number", "optional": false}, {"name": "height", "type": "number", "optional": false}], [], false); 311 | 312 | // HeadlessExperimental. 313 | Protocol.inspectorBackend.registerEnum("HeadlessExperimental.ScreenshotParamsFormat", {Jpeg: "jpeg", Png: "png"}); 314 | Protocol.inspectorBackend.registerEvent("HeadlessExperimental.mainFrameReadyForScreenshots", []); 315 | Protocol.inspectorBackend.registerEvent("HeadlessExperimental.needsBeginFramesChanged", ["needsBeginFrames"]); 316 | Protocol.inspectorBackend.registerCommand("HeadlessExperimental.beginFrame", [{"name": "frameTime", "type": "number", "optional": true}, {"name": "deadline", "type": "number", "optional": true}, {"name": "interval", "type": "number", "optional": true}, {"name": "screenshot", "type": "object", "optional": true}], ["hasDamage", "mainFrameContentUpdated", "screenshotData"], false); 317 | Protocol.inspectorBackend.registerCommand("HeadlessExperimental.disable", [], [], false); 318 | Protocol.inspectorBackend.registerCommand("HeadlessExperimental.enable", [], [], false); 319 | 320 | // IO. 321 | Protocol.inspectorBackend.registerCommand("IO.close", [{"name": "handle", "type": "string", "optional": false}], [], false); 322 | Protocol.inspectorBackend.registerCommand("IO.read", [{"name": "handle", "type": "string", "optional": false}, {"name": "offset", "type": "number", "optional": true}, {"name": "size", "type": "number", "optional": true}], ["base64Encoded", "data", "eof"], false); 323 | Protocol.inspectorBackend.registerCommand("IO.resolveBlob", [{"name": "objectId", "type": "string", "optional": false}], ["uuid"], false); 324 | 325 | // IndexedDB. 326 | Protocol.inspectorBackend.registerEnum("IndexedDB.KeyType", {Number: "number", String: "string", Date: "date", Array: "array"}); 327 | Protocol.inspectorBackend.registerEnum("IndexedDB.KeyPathType", {Null: "null", String: "string", Array: "array"}); 328 | Protocol.inspectorBackend.registerCommand("IndexedDB.clearObjectStore", [{"name": "securityOrigin", "type": "string", "optional": false}, {"name": "databaseName", "type": "string", "optional": false}, {"name": "objectStoreName", "type": "string", "optional": false}], [], false); 329 | Protocol.inspectorBackend.registerCommand("IndexedDB.deleteDatabase", [{"name": "securityOrigin", "type": "string", "optional": false}, {"name": "databaseName", "type": "string", "optional": false}], [], false); 330 | Protocol.inspectorBackend.registerCommand("IndexedDB.deleteObjectStoreEntries", [{"name": "securityOrigin", "type": "string", "optional": false}, {"name": "databaseName", "type": "string", "optional": false}, {"name": "objectStoreName", "type": "string", "optional": false}, {"name": "keyRange", "type": "object", "optional": false}], [], false); 331 | Protocol.inspectorBackend.registerCommand("IndexedDB.disable", [], [], false); 332 | Protocol.inspectorBackend.registerCommand("IndexedDB.enable", [], [], false); 333 | Protocol.inspectorBackend.registerCommand("IndexedDB.requestData", [{"name": "securityOrigin", "type": "string", "optional": false}, {"name": "databaseName", "type": "string", "optional": false}, {"name": "objectStoreName", "type": "string", "optional": false}, {"name": "indexName", "type": "string", "optional": false}, {"name": "skipCount", "type": "number", "optional": false}, {"name": "pageSize", "type": "number", "optional": false}, {"name": "keyRange", "type": "object", "optional": true}], ["objectStoreDataEntries", "hasMore"], false); 334 | Protocol.inspectorBackend.registerCommand("IndexedDB.requestDatabase", [{"name": "securityOrigin", "type": "string", "optional": false}, {"name": "databaseName", "type": "string", "optional": false}], ["databaseWithObjectStores"], false); 335 | Protocol.inspectorBackend.registerCommand("IndexedDB.requestDatabaseNames", [{"name": "securityOrigin", "type": "string", "optional": false}], ["databaseNames"], false); 336 | 337 | // Input. 338 | Protocol.inspectorBackend.registerEnum("Input.GestureSourceType", {Default: "default", Touch: "touch", Mouse: "mouse"}); 339 | Protocol.inspectorBackend.registerCommand("Input.dispatchKeyEvent", [{"name": "type", "type": "string", "optional": false}, {"name": "modifiers", "type": "number", "optional": true}, {"name": "timestamp", "type": "number", "optional": true}, {"name": "text", "type": "string", "optional": true}, {"name": "unmodifiedText", "type": "string", "optional": true}, {"name": "keyIdentifier", "type": "string", "optional": true}, {"name": "code", "type": "string", "optional": true}, {"name": "key", "type": "string", "optional": true}, {"name": "windowsVirtualKeyCode", "type": "number", "optional": true}, {"name": "nativeVirtualKeyCode", "type": "number", "optional": true}, {"name": "autoRepeat", "type": "boolean", "optional": true}, {"name": "isKeypad", "type": "boolean", "optional": true}, {"name": "isSystemKey", "type": "boolean", "optional": true}, {"name": "location", "type": "number", "optional": true}], [], false); 340 | Protocol.inspectorBackend.registerCommand("Input.dispatchMouseEvent", [{"name": "type", "type": "string", "optional": false}, {"name": "x", "type": "number", "optional": false}, {"name": "y", "type": "number", "optional": false}, {"name": "modifiers", "type": "number", "optional": true}, {"name": "timestamp", "type": "number", "optional": true}, {"name": "button", "type": "string", "optional": true}, {"name": "clickCount", "type": "number", "optional": true}, {"name": "deltaX", "type": "number", "optional": true}, {"name": "deltaY", "type": "number", "optional": true}], [], false); 341 | Protocol.inspectorBackend.registerCommand("Input.dispatchTouchEvent", [{"name": "type", "type": "string", "optional": false}, {"name": "touchPoints", "type": "object", "optional": false}, {"name": "modifiers", "type": "number", "optional": true}, {"name": "timestamp", "type": "number", "optional": true}], [], false); 342 | Protocol.inspectorBackend.registerCommand("Input.emulateTouchFromMouseEvent", [{"name": "type", "type": "string", "optional": false}, {"name": "x", "type": "number", "optional": false}, {"name": "y", "type": "number", "optional": false}, {"name": "timestamp", "type": "number", "optional": false}, {"name": "button", "type": "string", "optional": false}, {"name": "deltaX", "type": "number", "optional": true}, {"name": "deltaY", "type": "number", "optional": true}, {"name": "modifiers", "type": "number", "optional": true}, {"name": "clickCount", "type": "number", "optional": true}], [], false); 343 | Protocol.inspectorBackend.registerCommand("Input.setIgnoreInputEvents", [{"name": "ignore", "type": "boolean", "optional": false}], [], false); 344 | Protocol.inspectorBackend.registerCommand("Input.synthesizePinchGesture", [{"name": "x", "type": "number", "optional": false}, {"name": "y", "type": "number", "optional": false}, {"name": "scaleFactor", "type": "number", "optional": false}, {"name": "relativeSpeed", "type": "number", "optional": true}, {"name": "gestureSourceType", "type": "string", "optional": true}], [], false); 345 | Protocol.inspectorBackend.registerCommand("Input.synthesizeScrollGesture", [{"name": "x", "type": "number", "optional": false}, {"name": "y", "type": "number", "optional": false}, {"name": "xDistance", "type": "number", "optional": true}, {"name": "yDistance", "type": "number", "optional": true}, {"name": "xOverscroll", "type": "number", "optional": true}, {"name": "yOverscroll", "type": "number", "optional": true}, {"name": "preventFling", "type": "boolean", "optional": true}, {"name": "speed", "type": "number", "optional": true}, {"name": "gestureSourceType", "type": "string", "optional": true}, {"name": "repeatCount", "type": "number", "optional": true}, {"name": "repeatDelayMs", "type": "number", "optional": true}, {"name": "interactionMarkerName", "type": "string", "optional": true}], [], false); 346 | Protocol.inspectorBackend.registerCommand("Input.synthesizeTapGesture", [{"name": "x", "type": "number", "optional": false}, {"name": "y", "type": "number", "optional": false}, {"name": "duration", "type": "number", "optional": true}, {"name": "tapCount", "type": "number", "optional": true}, {"name": "gestureSourceType", "type": "string", "optional": true}], [], false); 347 | 348 | // Inspector. 349 | Protocol.inspectorBackend.registerEvent("Inspector.detached", ["reason"]); 350 | Protocol.inspectorBackend.registerEvent("Inspector.targetCrashed", []); 351 | Protocol.inspectorBackend.registerCommand("Inspector.disable", [], [], false); 352 | Protocol.inspectorBackend.registerCommand("Inspector.enable", [], [], false); 353 | 354 | // LayerTree. 355 | Protocol.inspectorBackend.registerEnum("LayerTree.ScrollRectType", {RepaintsOnScroll: "RepaintsOnScroll", TouchEventHandler: "TouchEventHandler", WheelEventHandler: "WheelEventHandler"}); 356 | Protocol.inspectorBackend.registerEvent("LayerTree.layerPainted", ["layerId", "clip"]); 357 | Protocol.inspectorBackend.registerEvent("LayerTree.layerTreeDidChange", ["layers"]); 358 | Protocol.inspectorBackend.registerCommand("LayerTree.compositingReasons", [{"name": "layerId", "type": "string", "optional": false}], ["compositingReasons"], false); 359 | Protocol.inspectorBackend.registerCommand("LayerTree.disable", [], [], false); 360 | Protocol.inspectorBackend.registerCommand("LayerTree.enable", [], [], false); 361 | Protocol.inspectorBackend.registerCommand("LayerTree.loadSnapshot", [{"name": "tiles", "type": "object", "optional": false}], ["snapshotId"], false); 362 | Protocol.inspectorBackend.registerCommand("LayerTree.makeSnapshot", [{"name": "layerId", "type": "string", "optional": false}], ["snapshotId"], false); 363 | Protocol.inspectorBackend.registerCommand("LayerTree.profileSnapshot", [{"name": "snapshotId", "type": "string", "optional": false}, {"name": "minRepeatCount", "type": "number", "optional": true}, {"name": "minDuration", "type": "number", "optional": true}, {"name": "clipRect", "type": "object", "optional": true}], ["timings"], false); 364 | Protocol.inspectorBackend.registerCommand("LayerTree.releaseSnapshot", [{"name": "snapshotId", "type": "string", "optional": false}], [], false); 365 | Protocol.inspectorBackend.registerCommand("LayerTree.replaySnapshot", [{"name": "snapshotId", "type": "string", "optional": false}, {"name": "fromStep", "type": "number", "optional": true}, {"name": "toStep", "type": "number", "optional": true}, {"name": "scale", "type": "number", "optional": true}], ["dataURL"], false); 366 | Protocol.inspectorBackend.registerCommand("LayerTree.snapshotCommandLog", [{"name": "snapshotId", "type": "string", "optional": false}], ["commandLog"], false); 367 | 368 | // Log. 369 | Protocol.inspectorBackend.registerEnum("Log.LogEntrySource", {XML: "xml", Javascript: "javascript", Network: "network", Storage: "storage", Appcache: "appcache", Rendering: "rendering", Security: "security", Deprecation: "deprecation", Worker: "worker", Violation: "violation", Intervention: "intervention", Recommendation: "recommendation", Other: "other"}); 370 | Protocol.inspectorBackend.registerEnum("Log.LogEntryLevel", {Verbose: "verbose", Info: "info", Warning: "warning", Error: "error"}); 371 | Protocol.inspectorBackend.registerEnum("Log.ViolationSettingName", {LongTask: "longTask", LongLayout: "longLayout", BlockedEvent: "blockedEvent", BlockedParser: "blockedParser", DiscouragedAPIUse: "discouragedAPIUse", Handler: "handler", RecurringHandler: "recurringHandler"}); 372 | Protocol.inspectorBackend.registerEvent("Log.entryAdded", ["entry"]); 373 | Protocol.inspectorBackend.registerCommand("Log.clear", [], [], false); 374 | Protocol.inspectorBackend.registerCommand("Log.disable", [], [], false); 375 | Protocol.inspectorBackend.registerCommand("Log.enable", [], [], false); 376 | Protocol.inspectorBackend.registerCommand("Log.startViolationsReport", [{"name": "config", "type": "object", "optional": false}], [], false); 377 | Protocol.inspectorBackend.registerCommand("Log.stopViolationsReport", [], [], false); 378 | 379 | // Memory. 380 | Protocol.inspectorBackend.registerEnum("Memory.PressureLevel", {Moderate: "moderate", Critical: "critical"}); 381 | Protocol.inspectorBackend.registerCommand("Memory.getDOMCounters", [], ["documents", "nodes", "jsEventListeners"], false); 382 | Protocol.inspectorBackend.registerCommand("Memory.prepareForLeakDetection", [], [], false); 383 | Protocol.inspectorBackend.registerCommand("Memory.setPressureNotificationsSuppressed", [{"name": "suppressed", "type": "boolean", "optional": false}], [], false); 384 | Protocol.inspectorBackend.registerCommand("Memory.simulatePressureNotification", [{"name": "level", "type": "string", "optional": false}], [], false); 385 | 386 | // Network. 387 | Protocol.inspectorBackend.registerEnum("Network.ErrorReason", {Failed: "Failed", Aborted: "Aborted", TimedOut: "TimedOut", AccessDenied: "AccessDenied", ConnectionClosed: "ConnectionClosed", ConnectionReset: "ConnectionReset", ConnectionRefused: "ConnectionRefused", ConnectionAborted: "ConnectionAborted", ConnectionFailed: "ConnectionFailed", NameNotResolved: "NameNotResolved", InternetDisconnected: "InternetDisconnected", AddressUnreachable: "AddressUnreachable"}); 388 | Protocol.inspectorBackend.registerEnum("Network.ConnectionType", {None: "none", Cellular2g: "cellular2g", Cellular3g: "cellular3g", Cellular4g: "cellular4g", Bluetooth: "bluetooth", Ethernet: "ethernet", Wifi: "wifi", Wimax: "wimax", Other: "other"}); 389 | Protocol.inspectorBackend.registerEnum("Network.CookieSameSite", {Strict: "Strict", Lax: "Lax"}); 390 | Protocol.inspectorBackend.registerEnum("Network.ResourcePriority", {VeryLow: "VeryLow", Low: "Low", Medium: "Medium", High: "High", VeryHigh: "VeryHigh"}); 391 | Protocol.inspectorBackend.registerEnum("Network.RequestReferrerPolicy", {UnsafeUrl: "unsafe-url", NoReferrerWhenDowngrade: "no-referrer-when-downgrade", NoReferrer: "no-referrer", Origin: "origin", OriginWhenCrossOrigin: "origin-when-cross-origin", SameOrigin: "same-origin", StrictOrigin: "strict-origin", StrictOriginWhenCrossOrigin: "strict-origin-when-cross-origin"}); 392 | Protocol.inspectorBackend.registerEnum("Network.BlockedReason", {Csp: "csp", MixedContent: "mixed-content", Origin: "origin", Inspector: "inspector", SubresourceFilter: "subresource-filter", Other: "other"}); 393 | Protocol.inspectorBackend.registerEnum("Network.InitiatorType", {Parser: "parser", Script: "script", Preload: "preload", Other: "other"}); 394 | Protocol.inspectorBackend.registerEnum("Network.AuthChallengeSource", {Server: "Server", Proxy: "Proxy"}); 395 | Protocol.inspectorBackend.registerEnum("Network.AuthChallengeResponseResponse", {Default: "Default", CancelAuth: "CancelAuth", ProvideCredentials: "ProvideCredentials"}); 396 | Protocol.inspectorBackend.registerEnum("Network.InterceptionStage", {Request: "Request", HeadersReceived: "HeadersReceived"}); 397 | Protocol.inspectorBackend.registerEvent("Network.dataReceived", ["requestId", "timestamp", "dataLength", "encodedDataLength"]); 398 | Protocol.inspectorBackend.registerEvent("Network.eventSourceMessageReceived", ["requestId", "timestamp", "eventName", "eventId", "data"]); 399 | Protocol.inspectorBackend.registerEvent("Network.loadingFailed", ["requestId", "timestamp", "type", "errorText", "canceled", "blockedReason"]); 400 | Protocol.inspectorBackend.registerEvent("Network.loadingFinished", ["requestId", "timestamp", "encodedDataLength", "blockedCrossSiteDocument"]); 401 | Protocol.inspectorBackend.registerEvent("Network.requestIntercepted", ["interceptionId", "request", "frameId", "resourceType", "isNavigationRequest", "redirectUrl", "authChallenge", "responseErrorReason", "responseStatusCode", "responseHeaders"]); 402 | Protocol.inspectorBackend.registerEvent("Network.requestServedFromCache", ["requestId"]); 403 | Protocol.inspectorBackend.registerEvent("Network.requestWillBeSent", ["requestId", "loaderId", "documentURL", "request", "timestamp", "wallTime", "initiator", "redirectResponse", "type", "frameId"]); 404 | Protocol.inspectorBackend.registerEvent("Network.resourceChangedPriority", ["requestId", "newPriority", "timestamp"]); 405 | Protocol.inspectorBackend.registerEvent("Network.responseReceived", ["requestId", "loaderId", "timestamp", "type", "response", "frameId"]); 406 | Protocol.inspectorBackend.registerEvent("Network.webSocketClosed", ["requestId", "timestamp"]); 407 | Protocol.inspectorBackend.registerEvent("Network.webSocketCreated", ["requestId", "url", "initiator"]); 408 | Protocol.inspectorBackend.registerEvent("Network.webSocketFrameError", ["requestId", "timestamp", "errorMessage"]); 409 | Protocol.inspectorBackend.registerEvent("Network.webSocketFrameReceived", ["requestId", "timestamp", "response"]); 410 | Protocol.inspectorBackend.registerEvent("Network.webSocketFrameSent", ["requestId", "timestamp", "response"]); 411 | Protocol.inspectorBackend.registerEvent("Network.webSocketHandshakeResponseReceived", ["requestId", "timestamp", "response"]); 412 | Protocol.inspectorBackend.registerEvent("Network.webSocketWillSendHandshakeRequest", ["requestId", "timestamp", "wallTime", "request"]); 413 | Protocol.inspectorBackend.registerCommand("Network.canClearBrowserCache", [], ["result"], false); 414 | Protocol.inspectorBackend.registerCommand("Network.canClearBrowserCookies", [], ["result"], false); 415 | Protocol.inspectorBackend.registerCommand("Network.canEmulateNetworkConditions", [], ["result"], false); 416 | Protocol.inspectorBackend.registerCommand("Network.clearBrowserCache", [], [], false); 417 | Protocol.inspectorBackend.registerCommand("Network.clearBrowserCookies", [], [], false); 418 | Protocol.inspectorBackend.registerCommand("Network.continueInterceptedRequest", [{"name": "interceptionId", "type": "string", "optional": false}, {"name": "errorReason", "type": "string", "optional": true}, {"name": "rawResponse", "type": "string", "optional": true}, {"name": "url", "type": "string", "optional": true}, {"name": "method", "type": "string", "optional": true}, {"name": "postData", "type": "string", "optional": true}, {"name": "headers", "type": "object", "optional": true}, {"name": "authChallengeResponse", "type": "object", "optional": true}], [], false); 419 | Protocol.inspectorBackend.registerCommand("Network.deleteCookies", [{"name": "name", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": true}, {"name": "domain", "type": "string", "optional": true}, {"name": "path", "type": "string", "optional": true}], [], false); 420 | Protocol.inspectorBackend.registerCommand("Network.disable", [], [], false); 421 | Protocol.inspectorBackend.registerCommand("Network.emulateNetworkConditions", [{"name": "offline", "type": "boolean", "optional": false}, {"name": "latency", "type": "number", "optional": false}, {"name": "downloadThroughput", "type": "number", "optional": false}, {"name": "uploadThroughput", "type": "number", "optional": false}, {"name": "connectionType", "type": "string", "optional": true}], [], false); 422 | Protocol.inspectorBackend.registerCommand("Network.enable", [{"name": "maxTotalBufferSize", "type": "number", "optional": true}, {"name": "maxResourceBufferSize", "type": "number", "optional": true}], [], false); 423 | Protocol.inspectorBackend.registerCommand("Network.getAllCookies", [], ["cookies"], false); 424 | Protocol.inspectorBackend.registerCommand("Network.getCertificate", [{"name": "origin", "type": "string", "optional": false}], ["tableNames"], false); 425 | Protocol.inspectorBackend.registerCommand("Network.getCookies", [{"name": "urls", "type": "object", "optional": true}], ["cookies"], false); 426 | Protocol.inspectorBackend.registerCommand("Network.getResponseBody", [{"name": "requestId", "type": "string", "optional": false}], ["body", "base64Encoded"], false); 427 | Protocol.inspectorBackend.registerCommand("Network.getResponseBodyForInterception", [{"name": "interceptionId", "type": "string", "optional": false}], ["body", "base64Encoded"], false); 428 | Protocol.inspectorBackend.registerCommand("Network.replayXHR", [{"name": "requestId", "type": "string", "optional": false}], [], false); 429 | Protocol.inspectorBackend.registerCommand("Network.searchInResponseBody", [{"name": "requestId", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"], false); 430 | Protocol.inspectorBackend.registerCommand("Network.setBlockedURLs", [{"name": "urls", "type": "object", "optional": false}], [], false); 431 | Protocol.inspectorBackend.registerCommand("Network.setBypassServiceWorker", [{"name": "bypass", "type": "boolean", "optional": false}], [], false); 432 | Protocol.inspectorBackend.registerCommand("Network.setCacheDisabled", [{"name": "cacheDisabled", "type": "boolean", "optional": false}], [], false); 433 | Protocol.inspectorBackend.registerCommand("Network.setCookie", [{"name": "name", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": true}, {"name": "domain", "type": "string", "optional": true}, {"name": "path", "type": "string", "optional": true}, {"name": "secure", "type": "boolean", "optional": true}, {"name": "httpOnly", "type": "boolean", "optional": true}, {"name": "sameSite", "type": "string", "optional": true}, {"name": "expires", "type": "number", "optional": true}], ["success"], false); 434 | Protocol.inspectorBackend.registerCommand("Network.setCookies", [{"name": "cookies", "type": "object", "optional": false}], [], false); 435 | Protocol.inspectorBackend.registerCommand("Network.setDataSizeLimitsForTest", [{"name": "maxTotalSize", "type": "number", "optional": false}, {"name": "maxResourceSize", "type": "number", "optional": false}], [], false); 436 | Protocol.inspectorBackend.registerCommand("Network.setExtraHTTPHeaders", [{"name": "headers", "type": "object", "optional": false}], [], false); 437 | Protocol.inspectorBackend.registerCommand("Network.setRequestInterception", [{"name": "patterns", "type": "object", "optional": false}], [], false); 438 | Protocol.inspectorBackend.registerCommand("Network.setUserAgentOverride", [{"name": "userAgent", "type": "string", "optional": false}], [], false); 439 | 440 | // Overlay. 441 | Protocol.inspectorBackend.registerEnum("Overlay.InspectMode", {SearchForNode: "searchForNode", SearchForUAShadowDOM: "searchForUAShadowDOM", None: "none"}); 442 | Protocol.inspectorBackend.registerEvent("Overlay.inspectNodeRequested", ["backendNodeId"]); 443 | Protocol.inspectorBackend.registerEvent("Overlay.nodeHighlightRequested", ["nodeId"]); 444 | Protocol.inspectorBackend.registerEvent("Overlay.screenshotRequested", ["viewport"]); 445 | Protocol.inspectorBackend.registerCommand("Overlay.disable", [], [], false); 446 | Protocol.inspectorBackend.registerCommand("Overlay.enable", [], [], false); 447 | Protocol.inspectorBackend.registerCommand("Overlay.getHighlightObjectForTest", [{"name": "nodeId", "type": "number", "optional": false}], ["highlight"], false); 448 | Protocol.inspectorBackend.registerCommand("Overlay.hideHighlight", [], [], false); 449 | Protocol.inspectorBackend.registerCommand("Overlay.highlightFrame", [{"name": "frameId", "type": "string", "optional": false}, {"name": "contentColor", "type": "object", "optional": true}, {"name": "contentOutlineColor", "type": "object", "optional": true}], [], false); 450 | Protocol.inspectorBackend.registerCommand("Overlay.highlightNode", [{"name": "highlightConfig", "type": "object", "optional": false}, {"name": "nodeId", "type": "number", "optional": true}, {"name": "backendNodeId", "type": "number", "optional": true}, {"name": "objectId", "type": "string", "optional": true}], [], false); 451 | Protocol.inspectorBackend.registerCommand("Overlay.highlightQuad", [{"name": "quad", "type": "object", "optional": false}, {"name": "color", "type": "object", "optional": true}, {"name": "outlineColor", "type": "object", "optional": true}], [], false); 452 | Protocol.inspectorBackend.registerCommand("Overlay.highlightRect", [{"name": "x", "type": "number", "optional": false}, {"name": "y", "type": "number", "optional": false}, {"name": "width", "type": "number", "optional": false}, {"name": "height", "type": "number", "optional": false}, {"name": "color", "type": "object", "optional": true}, {"name": "outlineColor", "type": "object", "optional": true}], [], false); 453 | Protocol.inspectorBackend.registerCommand("Overlay.setInspectMode", [{"name": "mode", "type": "string", "optional": false}, {"name": "highlightConfig", "type": "object", "optional": true}], [], false); 454 | Protocol.inspectorBackend.registerCommand("Overlay.setPausedInDebuggerMessage", [{"name": "message", "type": "string", "optional": true}], [], false); 455 | Protocol.inspectorBackend.registerCommand("Overlay.setShowDebugBorders", [{"name": "show", "type": "boolean", "optional": false}], [], false); 456 | Protocol.inspectorBackend.registerCommand("Overlay.setShowFPSCounter", [{"name": "show", "type": "boolean", "optional": false}], [], false); 457 | Protocol.inspectorBackend.registerCommand("Overlay.setShowPaintRects", [{"name": "result", "type": "boolean", "optional": false}], [], false); 458 | Protocol.inspectorBackend.registerCommand("Overlay.setShowScrollBottleneckRects", [{"name": "show", "type": "boolean", "optional": false}], [], false); 459 | Protocol.inspectorBackend.registerCommand("Overlay.setShowViewportSizeOnResize", [{"name": "show", "type": "boolean", "optional": false}], [], false); 460 | Protocol.inspectorBackend.registerCommand("Overlay.setSuspended", [{"name": "suspended", "type": "boolean", "optional": false}], [], false); 461 | 462 | // Page. 463 | Protocol.inspectorBackend.registerEnum("Page.ResourceType", {Document: "Document", Stylesheet: "Stylesheet", Image: "Image", Media: "Media", Font: "Font", Script: "Script", TextTrack: "TextTrack", XHR: "XHR", Fetch: "Fetch", EventSource: "EventSource", WebSocket: "WebSocket", Manifest: "Manifest", Other: "Other"}); 464 | Protocol.inspectorBackend.registerEnum("Page.TransitionType", {Link: "link", Typed: "typed", Auto_bookmark: "auto_bookmark", Auto_subframe: "auto_subframe", Manual_subframe: "manual_subframe", Generated: "generated", Auto_toplevel: "auto_toplevel", Form_submit: "form_submit", Reload: "reload", Keyword: "keyword", Keyword_generated: "keyword_generated", Other: "other"}); 465 | Protocol.inspectorBackend.registerEnum("Page.DialogType", {Alert: "alert", Confirm: "confirm", Prompt: "prompt", Beforeunload: "beforeunload"}); 466 | Protocol.inspectorBackend.registerEvent("Page.domContentEventFired", ["timestamp"]); 467 | Protocol.inspectorBackend.registerEvent("Page.frameAttached", ["frameId", "parentFrameId", "stack"]); 468 | Protocol.inspectorBackend.registerEvent("Page.frameClearedScheduledNavigation", ["frameId"]); 469 | Protocol.inspectorBackend.registerEvent("Page.frameDetached", ["frameId"]); 470 | Protocol.inspectorBackend.registerEvent("Page.frameNavigated", ["frame"]); 471 | Protocol.inspectorBackend.registerEvent("Page.frameResized", []); 472 | Protocol.inspectorBackend.registerEvent("Page.frameScheduledNavigation", ["frameId", "delay", "reason", "url"]); 473 | Protocol.inspectorBackend.registerEvent("Page.frameStartedLoading", ["frameId"]); 474 | Protocol.inspectorBackend.registerEvent("Page.frameStoppedLoading", ["frameId"]); 475 | Protocol.inspectorBackend.registerEvent("Page.interstitialHidden", []); 476 | Protocol.inspectorBackend.registerEvent("Page.interstitialShown", []); 477 | Protocol.inspectorBackend.registerEvent("Page.javascriptDialogClosed", ["result", "userInput"]); 478 | Protocol.inspectorBackend.registerEvent("Page.javascriptDialogOpening", ["url", "message", "type", "defaultPrompt"]); 479 | Protocol.inspectorBackend.registerEvent("Page.lifecycleEvent", ["frameId", "loaderId", "name", "timestamp"]); 480 | Protocol.inspectorBackend.registerEvent("Page.loadEventFired", ["timestamp"]); 481 | Protocol.inspectorBackend.registerEvent("Page.screencastFrame", ["data", "metadata", "sessionId"]); 482 | Protocol.inspectorBackend.registerEvent("Page.screencastVisibilityChanged", ["visible"]); 483 | Protocol.inspectorBackend.registerEvent("Page.windowOpen", ["url", "windowName", "windowFeatures", "userGesture"]); 484 | Protocol.inspectorBackend.registerCommand("Page.addScriptToEvaluateOnLoad", [{"name": "scriptSource", "type": "string", "optional": false}], ["identifier"], false); 485 | Protocol.inspectorBackend.registerCommand("Page.addScriptToEvaluateOnNewDocument", [{"name": "source", "type": "string", "optional": false}], ["identifier"], false); 486 | Protocol.inspectorBackend.registerCommand("Page.bringToFront", [], [], false); 487 | Protocol.inspectorBackend.registerCommand("Page.captureScreenshot", [{"name": "format", "type": "string", "optional": true}, {"name": "quality", "type": "number", "optional": true}, {"name": "clip", "type": "object", "optional": true}, {"name": "fromSurface", "type": "boolean", "optional": true}], ["data"], false); 488 | Protocol.inspectorBackend.registerCommand("Page.clearDeviceMetricsOverride", [], [], false); 489 | Protocol.inspectorBackend.registerCommand("Page.clearDeviceOrientationOverride", [], [], false); 490 | Protocol.inspectorBackend.registerCommand("Page.clearGeolocationOverride", [], [], false); 491 | Protocol.inspectorBackend.registerCommand("Page.createIsolatedWorld", [{"name": "frameId", "type": "string", "optional": false}, {"name": "worldName", "type": "string", "optional": true}, {"name": "grantUniveralAccess", "type": "boolean", "optional": true}], ["executionContextId"], false); 492 | Protocol.inspectorBackend.registerCommand("Page.deleteCookie", [{"name": "cookieName", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}], [], false); 493 | Protocol.inspectorBackend.registerCommand("Page.disable", [], [], false); 494 | Protocol.inspectorBackend.registerCommand("Page.enable", [], [], false); 495 | Protocol.inspectorBackend.registerCommand("Page.getAppManifest", [], ["url", "errors", "data"], false); 496 | Protocol.inspectorBackend.registerCommand("Page.getCookies", [], ["cookies"], false); 497 | Protocol.inspectorBackend.registerCommand("Page.getFrameTree", [], ["frameTree"], false); 498 | Protocol.inspectorBackend.registerCommand("Page.getLayoutMetrics", [], ["layoutViewport", "visualViewport", "contentSize"], false); 499 | Protocol.inspectorBackend.registerCommand("Page.getNavigationHistory", [], ["currentIndex", "entries"], false); 500 | Protocol.inspectorBackend.registerCommand("Page.getResourceContent", [{"name": "frameId", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}], ["content", "base64Encoded"], false); 501 | Protocol.inspectorBackend.registerCommand("Page.getResourceTree", [], ["frameTree"], false); 502 | Protocol.inspectorBackend.registerCommand("Page.handleJavaScriptDialog", [{"name": "accept", "type": "boolean", "optional": false}, {"name": "promptText", "type": "string", "optional": true}], [], false); 503 | Protocol.inspectorBackend.registerCommand("Page.navigate", [{"name": "url", "type": "string", "optional": false}, {"name": "referrer", "type": "string", "optional": true}, {"name": "transitionType", "type": "string", "optional": true}], ["frameId", "loaderId", "errorText"], false); 504 | Protocol.inspectorBackend.registerCommand("Page.navigateToHistoryEntry", [{"name": "entryId", "type": "number", "optional": false}], [], false); 505 | Protocol.inspectorBackend.registerCommand("Page.printToPDF", [{"name": "landscape", "type": "boolean", "optional": true}, {"name": "displayHeaderFooter", "type": "boolean", "optional": true}, {"name": "printBackground", "type": "boolean", "optional": true}, {"name": "scale", "type": "number", "optional": true}, {"name": "paperWidth", "type": "number", "optional": true}, {"name": "paperHeight", "type": "number", "optional": true}, {"name": "marginTop", "type": "number", "optional": true}, {"name": "marginBottom", "type": "number", "optional": true}, {"name": "marginLeft", "type": "number", "optional": true}, {"name": "marginRight", "type": "number", "optional": true}, {"name": "pageRanges", "type": "string", "optional": true}, {"name": "ignoreInvalidPageRanges", "type": "boolean", "optional": true}, {"name": "headerTemplate", "type": "string", "optional": true}, {"name": "footerTemplate", "type": "string", "optional": true}], ["data"], false); 506 | Protocol.inspectorBackend.registerCommand("Page.reload", [{"name": "ignoreCache", "type": "boolean", "optional": true}, {"name": "scriptToEvaluateOnLoad", "type": "string", "optional": true}], [], false); 507 | Protocol.inspectorBackend.registerCommand("Page.removeScriptToEvaluateOnLoad", [{"name": "identifier", "type": "string", "optional": false}], [], false); 508 | Protocol.inspectorBackend.registerCommand("Page.removeScriptToEvaluateOnNewDocument", [{"name": "identifier", "type": "string", "optional": false}], [], false); 509 | Protocol.inspectorBackend.registerCommand("Page.requestAppBanner", [], [], false); 510 | Protocol.inspectorBackend.registerCommand("Page.screencastFrameAck", [{"name": "sessionId", "type": "number", "optional": false}], [], false); 511 | Protocol.inspectorBackend.registerCommand("Page.searchInResource", [{"name": "frameId", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"], false); 512 | Protocol.inspectorBackend.registerCommand("Page.setAdBlockingEnabled", [{"name": "enabled", "type": "boolean", "optional": false}], [], false); 513 | Protocol.inspectorBackend.registerCommand("Page.setDeviceMetricsOverride", [{"name": "width", "type": "number", "optional": false}, {"name": "height", "type": "number", "optional": false}, {"name": "deviceScaleFactor", "type": "number", "optional": false}, {"name": "mobile", "type": "boolean", "optional": false}, {"name": "scale", "type": "number", "optional": true}, {"name": "screenWidth", "type": "number", "optional": true}, {"name": "screenHeight", "type": "number", "optional": true}, {"name": "positionX", "type": "number", "optional": true}, {"name": "positionY", "type": "number", "optional": true}, {"name": "dontSetVisibleSize", "type": "boolean", "optional": true}, {"name": "screenOrientation", "type": "object", "optional": true}, {"name": "viewport", "type": "object", "optional": true}], [], false); 514 | Protocol.inspectorBackend.registerCommand("Page.setDeviceOrientationOverride", [{"name": "alpha", "type": "number", "optional": false}, {"name": "beta", "type": "number", "optional": false}, {"name": "gamma", "type": "number", "optional": false}], [], false); 515 | Protocol.inspectorBackend.registerCommand("Page.setDocumentContent", [{"name": "frameId", "type": "string", "optional": false}, {"name": "html", "type": "string", "optional": false}], [], false); 516 | Protocol.inspectorBackend.registerCommand("Page.setDownloadBehavior", [{"name": "behavior", "type": "string", "optional": false}, {"name": "downloadPath", "type": "string", "optional": true}], [], false); 517 | Protocol.inspectorBackend.registerCommand("Page.setGeolocationOverride", [{"name": "latitude", "type": "number", "optional": true}, {"name": "longitude", "type": "number", "optional": true}, {"name": "accuracy", "type": "number", "optional": true}], [], false); 518 | Protocol.inspectorBackend.registerCommand("Page.setLifecycleEventsEnabled", [{"name": "enabled", "type": "boolean", "optional": false}], [], false); 519 | Protocol.inspectorBackend.registerCommand("Page.setTouchEmulationEnabled", [{"name": "enabled", "type": "boolean", "optional": false}, {"name": "configuration", "type": "string", "optional": true}], [], false); 520 | Protocol.inspectorBackend.registerCommand("Page.startScreencast", [{"name": "format", "type": "string", "optional": true}, {"name": "quality", "type": "number", "optional": true}, {"name": "maxWidth", "type": "number", "optional": true}, {"name": "maxHeight", "type": "number", "optional": true}, {"name": "everyNthFrame", "type": "number", "optional": true}], [], false); 521 | Protocol.inspectorBackend.registerCommand("Page.stopLoading", [], [], false); 522 | Protocol.inspectorBackend.registerCommand("Page.stopScreencast", [], [], false); 523 | 524 | // Performance. 525 | Protocol.inspectorBackend.registerEvent("Performance.metrics", ["metrics", "title"]); 526 | Protocol.inspectorBackend.registerCommand("Performance.disable", [], [], false); 527 | Protocol.inspectorBackend.registerCommand("Performance.enable", [], [], false); 528 | Protocol.inspectorBackend.registerCommand("Performance.getMetrics", [], ["metrics"], false); 529 | 530 | // Security. 531 | Protocol.inspectorBackend.registerEnum("Security.MixedContentType", {Blockable: "blockable", OptionallyBlockable: "optionally-blockable", None: "none"}); 532 | Protocol.inspectorBackend.registerEnum("Security.SecurityState", {Unknown: "unknown", Neutral: "neutral", Insecure: "insecure", Secure: "secure", Info: "info"}); 533 | Protocol.inspectorBackend.registerEnum("Security.CertificateErrorAction", {Continue: "continue", Cancel: "cancel"}); 534 | Protocol.inspectorBackend.registerEvent("Security.certificateError", ["eventId", "errorType", "requestURL"]); 535 | Protocol.inspectorBackend.registerEvent("Security.securityStateChanged", ["securityState", "schemeIsCryptographic", "explanations", "insecureContentStatus", "summary"]); 536 | Protocol.inspectorBackend.registerCommand("Security.disable", [], [], false); 537 | Protocol.inspectorBackend.registerCommand("Security.enable", [], [], false); 538 | Protocol.inspectorBackend.registerCommand("Security.setIgnoreCertificateErrors", [{"name": "ignore", "type": "boolean", "optional": false}], [], false); 539 | Protocol.inspectorBackend.registerCommand("Security.handleCertificateError", [{"name": "eventId", "type": "number", "optional": false}, {"name": "action", "type": "string", "optional": false}], [], false); 540 | Protocol.inspectorBackend.registerCommand("Security.setOverrideCertificateErrors", [{"name": "override", "type": "boolean", "optional": false}], [], false); 541 | 542 | // ServiceWorker. 543 | Protocol.inspectorBackend.registerEnum("ServiceWorker.ServiceWorkerVersionRunningStatus", {Stopped: "stopped", Starting: "starting", Running: "running", Stopping: "stopping"}); 544 | Protocol.inspectorBackend.registerEnum("ServiceWorker.ServiceWorkerVersionStatus", {New: "new", Installing: "installing", Installed: "installed", Activating: "activating", Activated: "activated", Redundant: "redundant"}); 545 | Protocol.inspectorBackend.registerEvent("ServiceWorker.workerErrorReported", ["errorMessage"]); 546 | Protocol.inspectorBackend.registerEvent("ServiceWorker.workerRegistrationUpdated", ["registrations"]); 547 | Protocol.inspectorBackend.registerEvent("ServiceWorker.workerVersionUpdated", ["versions"]); 548 | Protocol.inspectorBackend.registerCommand("ServiceWorker.deliverPushMessage", [{"name": "origin", "type": "string", "optional": false}, {"name": "registrationId", "type": "string", "optional": false}, {"name": "data", "type": "string", "optional": false}], [], false); 549 | Protocol.inspectorBackend.registerCommand("ServiceWorker.disable", [], [], false); 550 | Protocol.inspectorBackend.registerCommand("ServiceWorker.dispatchSyncEvent", [{"name": "origin", "type": "string", "optional": false}, {"name": "registrationId", "type": "string", "optional": false}, {"name": "tag", "type": "string", "optional": false}, {"name": "lastChance", "type": "boolean", "optional": false}], [], false); 551 | Protocol.inspectorBackend.registerCommand("ServiceWorker.enable", [], [], false); 552 | Protocol.inspectorBackend.registerCommand("ServiceWorker.inspectWorker", [{"name": "versionId", "type": "string", "optional": false}], [], false); 553 | Protocol.inspectorBackend.registerCommand("ServiceWorker.setForceUpdateOnPageLoad", [{"name": "forceUpdateOnPageLoad", "type": "boolean", "optional": false}], [], false); 554 | Protocol.inspectorBackend.registerCommand("ServiceWorker.skipWaiting", [{"name": "scopeURL", "type": "string", "optional": false}], [], false); 555 | Protocol.inspectorBackend.registerCommand("ServiceWorker.startWorker", [{"name": "scopeURL", "type": "string", "optional": false}], [], false); 556 | Protocol.inspectorBackend.registerCommand("ServiceWorker.stopAllWorkers", [], [], false); 557 | Protocol.inspectorBackend.registerCommand("ServiceWorker.stopWorker", [{"name": "versionId", "type": "string", "optional": false}], [], false); 558 | Protocol.inspectorBackend.registerCommand("ServiceWorker.unregister", [{"name": "scopeURL", "type": "string", "optional": false}], [], false); 559 | Protocol.inspectorBackend.registerCommand("ServiceWorker.updateRegistration", [{"name": "scopeURL", "type": "string", "optional": false}], [], false); 560 | 561 | // Storage. 562 | Protocol.inspectorBackend.registerEnum("Storage.StorageType", {Appcache: "appcache", Cookies: "cookies", File_systems: "file_systems", Indexeddb: "indexeddb", Local_storage: "local_storage", Shader_cache: "shader_cache", Websql: "websql", Service_workers: "service_workers", Cache_storage: "cache_storage", All: "all", Other: "other"}); 563 | Protocol.inspectorBackend.registerEvent("Storage.cacheStorageContentUpdated", ["origin", "cacheName"]); 564 | Protocol.inspectorBackend.registerEvent("Storage.cacheStorageListUpdated", ["origin"]); 565 | Protocol.inspectorBackend.registerEvent("Storage.indexedDBContentUpdated", ["origin", "databaseName", "objectStoreName"]); 566 | Protocol.inspectorBackend.registerEvent("Storage.indexedDBListUpdated", ["origin"]); 567 | Protocol.inspectorBackend.registerCommand("Storage.clearDataForOrigin", [{"name": "origin", "type": "string", "optional": false}, {"name": "storageTypes", "type": "string", "optional": false}], [], false); 568 | Protocol.inspectorBackend.registerCommand("Storage.getUsageAndQuota", [{"name": "origin", "type": "string", "optional": false}], ["usage", "quota", "usageBreakdown"], false); 569 | Protocol.inspectorBackend.registerCommand("Storage.trackCacheStorageForOrigin", [{"name": "origin", "type": "string", "optional": false}], [], false); 570 | Protocol.inspectorBackend.registerCommand("Storage.trackIndexedDBForOrigin", [{"name": "origin", "type": "string", "optional": false}], [], false); 571 | Protocol.inspectorBackend.registerCommand("Storage.untrackCacheStorageForOrigin", [{"name": "origin", "type": "string", "optional": false}], [], false); 572 | Protocol.inspectorBackend.registerCommand("Storage.untrackIndexedDBForOrigin", [{"name": "origin", "type": "string", "optional": false}], [], false); 573 | 574 | // SystemInfo. 575 | Protocol.inspectorBackend.registerCommand("SystemInfo.getInfo", [], ["gpu", "modelName", "modelVersion", "commandLine"], false); 576 | 577 | // Target. 578 | Protocol.inspectorBackend.registerEvent("Target.attachedToTarget", ["sessionId", "targetInfo", "waitingForDebugger"]); 579 | Protocol.inspectorBackend.registerEvent("Target.detachedFromTarget", ["sessionId", "targetId"]); 580 | Protocol.inspectorBackend.registerEvent("Target.receivedMessageFromTarget", ["sessionId", "message", "targetId"]); 581 | Protocol.inspectorBackend.registerEvent("Target.targetCreated", ["targetInfo"]); 582 | Protocol.inspectorBackend.registerEvent("Target.targetDestroyed", ["targetId"]); 583 | Protocol.inspectorBackend.registerEvent("Target.targetInfoChanged", ["targetInfo"]); 584 | Protocol.inspectorBackend.registerCommand("Target.activateTarget", [{"name": "targetId", "type": "string", "optional": false}], [], false); 585 | Protocol.inspectorBackend.registerCommand("Target.attachToTarget", [{"name": "targetId", "type": "string", "optional": false}], ["sessionId"], false); 586 | Protocol.inspectorBackend.registerCommand("Target.closeTarget", [{"name": "targetId", "type": "string", "optional": false}], ["success"], false); 587 | Protocol.inspectorBackend.registerCommand("Target.createBrowserContext", [], ["browserContextId"], false); 588 | Protocol.inspectorBackend.registerCommand("Target.createTarget", [{"name": "url", "type": "string", "optional": false}, {"name": "width", "type": "number", "optional": true}, {"name": "height", "type": "number", "optional": true}, {"name": "browserContextId", "type": "string", "optional": true}, {"name": "enableBeginFrameControl", "type": "boolean", "optional": true}], ["targetId"], false); 589 | Protocol.inspectorBackend.registerCommand("Target.detachFromTarget", [{"name": "sessionId", "type": "string", "optional": true}, {"name": "targetId", "type": "string", "optional": true}], [], false); 590 | Protocol.inspectorBackend.registerCommand("Target.disposeBrowserContext", [{"name": "browserContextId", "type": "string", "optional": false}], ["success"], false); 591 | Protocol.inspectorBackend.registerCommand("Target.getTargetInfo", [{"name": "targetId", "type": "string", "optional": false}], ["targetInfo"], false); 592 | Protocol.inspectorBackend.registerCommand("Target.getTargets", [], ["targetInfos"], false); 593 | Protocol.inspectorBackend.registerCommand("Target.sendMessageToTarget", [{"name": "message", "type": "string", "optional": false}, {"name": "sessionId", "type": "string", "optional": true}, {"name": "targetId", "type": "string", "optional": true}], [], false); 594 | Protocol.inspectorBackend.registerCommand("Target.setAttachToFrames", [{"name": "value", "type": "boolean", "optional": false}], [], false); 595 | Protocol.inspectorBackend.registerCommand("Target.setAutoAttach", [{"name": "autoAttach", "type": "boolean", "optional": false}, {"name": "waitForDebuggerOnStart", "type": "boolean", "optional": false}], [], false); 596 | Protocol.inspectorBackend.registerCommand("Target.setDiscoverTargets", [{"name": "discover", "type": "boolean", "optional": false}], [], false); 597 | Protocol.inspectorBackend.registerCommand("Target.setRemoteLocations", [{"name": "locations", "type": "object", "optional": false}], [], false); 598 | 599 | // Tethering. 600 | Protocol.inspectorBackend.registerEvent("Tethering.accepted", ["port", "connectionId"]); 601 | Protocol.inspectorBackend.registerCommand("Tethering.bind", [{"name": "port", "type": "number", "optional": false}], [], false); 602 | Protocol.inspectorBackend.registerCommand("Tethering.unbind", [{"name": "port", "type": "number", "optional": false}], [], false); 603 | 604 | // Tracing. 605 | Protocol.inspectorBackend.registerEnum("Tracing.TraceConfigRecordMode", {RecordUntilFull: "recordUntilFull", RecordContinuously: "recordContinuously", RecordAsMuchAsPossible: "recordAsMuchAsPossible", EchoToConsole: "echoToConsole"}); 606 | Protocol.inspectorBackend.registerEnum("Tracing.StreamCompression", {None: "none", Gzip: "gzip"}); 607 | Protocol.inspectorBackend.registerEvent("Tracing.bufferUsage", ["percentFull", "eventCount", "value"]); 608 | Protocol.inspectorBackend.registerEvent("Tracing.dataCollected", ["value"]); 609 | Protocol.inspectorBackend.registerEvent("Tracing.tracingComplete", ["stream", "streamCompression"]); 610 | Protocol.inspectorBackend.registerCommand("Tracing.end", [], [], false); 611 | Protocol.inspectorBackend.registerCommand("Tracing.getCategories", [], ["categories"], false); 612 | Protocol.inspectorBackend.registerCommand("Tracing.recordClockSyncMarker", [{"name": "syncId", "type": "string", "optional": false}], [], false); 613 | Protocol.inspectorBackend.registerCommand("Tracing.requestMemoryDump", [], ["dumpGuid", "success"], false); 614 | Protocol.inspectorBackend.registerCommand("Tracing.start", [{"name": "categories", "type": "string", "optional": true}, {"name": "options", "type": "string", "optional": true}, {"name": "bufferUsageReportingInterval", "type": "number", "optional": true}, {"name": "transferMode", "type": "string", "optional": true}, {"name": "streamCompression", "type": "string", "optional": true}, {"name": "traceConfig", "type": "object", "optional": true}], [], false); 615 | 616 | 617 | -------------------------------------------------------------------------------- /resource/chrome-devtools/SupportedCSSProperties.js: -------------------------------------------------------------------------------- 1 | SDK.CSSMetadata._generatedProperties = [{"name": "-webkit-app-region"}, {"name": "-webkit-appearance"}, {"name": "-webkit-background-clip"}, {"name": "-webkit-background-origin"}, {"longhands": ["-webkit-border-after-width", "-webkit-border-after-style", "-webkit-border-after-color"], "name": "-webkit-border-after"}, {"name": "-webkit-border-after-color"}, {"name": "-webkit-border-after-style"}, {"name": "-webkit-border-after-width"}, {"longhands": ["-webkit-border-before-width", "-webkit-border-before-style", "-webkit-border-before-color"], "name": "-webkit-border-before"}, {"name": "-webkit-border-before-color"}, {"name": "-webkit-border-before-style"}, {"name": "-webkit-border-before-width"}, {"longhands": ["-webkit-border-end-width", "-webkit-border-end-style", "-webkit-border-end-color"], "name": "-webkit-border-end"}, {"name": "-webkit-border-end-color"}, {"name": "-webkit-border-end-style"}, {"name": "-webkit-border-end-width"}, {"name": "-webkit-border-horizontal-spacing", "inherited": true}, {"name": "-webkit-border-image"}, {"longhands": ["-webkit-border-start-width", "-webkit-border-start-style", "-webkit-border-start-color"], "name": "-webkit-border-start"}, {"name": "-webkit-border-start-color"}, {"name": "-webkit-border-start-style"}, {"name": "-webkit-border-start-width"}, {"name": "-webkit-border-vertical-spacing", "inherited": true}, {"name": "-webkit-box-align"}, {"name": "-webkit-box-decoration-break"}, {"name": "-webkit-box-direction", "inherited": true}, {"name": "-webkit-box-flex"}, {"name": "-webkit-box-flex-group"}, {"name": "-webkit-box-lines"}, {"name": "-webkit-box-ordinal-group"}, {"name": "-webkit-box-orient"}, {"name": "-webkit-box-pack"}, {"name": "-webkit-box-reflect"}, {"longhands": ["break-after"], "name": "-webkit-column-break-after"}, {"longhands": ["break-before"], "name": "-webkit-column-break-before"}, {"longhands": ["break-inside"], "name": "-webkit-column-break-inside"}, {"name": "-webkit-font-size-delta"}, {"name": "-webkit-font-smoothing", "inherited": true}, {"name": "-webkit-highlight", "inherited": true}, {"name": "-webkit-hyphenate-character", "inherited": true}, {"name": "-webkit-line-break", "inherited": true}, {"name": "-webkit-line-clamp"}, {"name": "-webkit-locale", "inherited": true}, {"name": "-webkit-logical-height"}, {"name": "-webkit-logical-width"}, {"name": "-webkit-margin-after"}, {"name": "-webkit-margin-after-collapse"}, {"name": "-webkit-margin-before"}, {"name": "-webkit-margin-before-collapse"}, {"name": "-webkit-margin-bottom-collapse"}, {"longhands": ["-webkit-margin-before-collapse", "-webkit-margin-after-collapse"], "name": "-webkit-margin-collapse"}, {"name": "-webkit-margin-end"}, {"name": "-webkit-margin-start"}, {"name": "-webkit-margin-top-collapse"}, {"longhands": ["-webkit-mask-image", "-webkit-mask-position-x", "-webkit-mask-position-y", "-webkit-mask-size", "-webkit-mask-repeat-x", "-webkit-mask-repeat-y", "-webkit-mask-origin", "-webkit-mask-clip"], "name": "-webkit-mask"}, {"longhands": ["-webkit-mask-box-image-source", "-webkit-mask-box-image-slice", "-webkit-mask-box-image-width", "-webkit-mask-box-image-outset", "-webkit-mask-box-image-repeat"], "name": "-webkit-mask-box-image"}, {"name": "-webkit-mask-box-image-outset"}, {"name": "-webkit-mask-box-image-repeat"}, {"name": "-webkit-mask-box-image-slice"}, {"name": "-webkit-mask-box-image-source"}, {"name": "-webkit-mask-box-image-width"}, {"name": "-webkit-mask-clip"}, {"name": "-webkit-mask-composite"}, {"name": "-webkit-mask-image"}, {"name": "-webkit-mask-origin"}, {"longhands": ["-webkit-mask-position-x", "-webkit-mask-position-y"], "name": "-webkit-mask-position"}, {"name": "-webkit-mask-position-x"}, {"name": "-webkit-mask-position-y"}, {"longhands": ["-webkit-mask-repeat-x", "-webkit-mask-repeat-y"], "name": "-webkit-mask-repeat"}, {"name": "-webkit-mask-repeat-x"}, {"name": "-webkit-mask-repeat-y"}, {"name": "-webkit-mask-size"}, {"name": "-webkit-max-logical-height"}, {"name": "-webkit-max-logical-width"}, {"name": "-webkit-min-logical-height"}, {"name": "-webkit-min-logical-width"}, {"name": "-webkit-padding-after"}, {"name": "-webkit-padding-before"}, {"name": "-webkit-padding-end"}, {"name": "-webkit-padding-start"}, {"name": "-webkit-perspective-origin-x"}, {"name": "-webkit-perspective-origin-y"}, {"name": "-webkit-print-color-adjust", "inherited": true}, {"name": "-webkit-rtl-ordering", "inherited": true}, {"name": "-webkit-ruby-position", "inherited": true}, {"name": "-webkit-tap-highlight-color", "inherited": true}, {"name": "-webkit-text-combine", "inherited": true}, {"name": "-webkit-text-decorations-in-effect", "inherited": true}, {"longhands": ["-webkit-text-emphasis-style", "-webkit-text-emphasis-color"], "name": "-webkit-text-emphasis"}, {"name": "-webkit-text-emphasis-color", "inherited": true}, {"name": "-webkit-text-emphasis-position", "inherited": true}, {"inherited": true, "name": "-webkit-text-emphasis-style"}, {"name": "-webkit-text-fill-color", "inherited": true}, {"name": "-webkit-text-orientation", "inherited": true}, {"name": "-webkit-text-security", "inherited": true}, {"longhands": ["-webkit-text-stroke-width", "-webkit-text-stroke-color"], "name": "-webkit-text-stroke"}, {"name": "-webkit-text-stroke-color", "inherited": true}, {"name": "-webkit-text-stroke-width", "inherited": true}, {"name": "-webkit-transform-origin-x"}, {"name": "-webkit-transform-origin-y"}, {"name": "-webkit-transform-origin-z"}, {"name": "-webkit-user-drag"}, {"name": "-webkit-user-modify", "inherited": true}, {"name": "-webkit-writing-mode", "inherited": true}, {"name": "align-content"}, {"name": "align-items"}, {"name": "align-self"}, {"svg": true, "name": "alignment-baseline"}, {"name": "all"}, {"longhands": ["animation-name", "animation-duration", "animation-timing-function", "animation-delay", "animation-iteration-count", "animation-direction", "animation-fill-mode", "animation-play-state"], "name": "animation"}, {"name": "animation-delay"}, {"name": "animation-direction"}, {"name": "animation-duration"}, {"name": "animation-fill-mode"}, {"name": "animation-iteration-count"}, {"name": "animation-name"}, {"name": "animation-play-state"}, {"name": "animation-timing-function"}, {"name": "backdrop-filter"}, {"name": "backface-visibility"}, {"longhands": ["background-image", "background-position-x", "background-position-y", "background-size", "background-repeat-x", "background-repeat-y", "background-attachment", "background-origin", "background-clip", "background-color"], "name": "background"}, {"name": "background-attachment"}, {"name": "background-blend-mode"}, {"name": "background-clip"}, {"name": "background-color"}, {"name": "background-image"}, {"name": "background-origin"}, {"longhands": ["background-position-x", "background-position-y"], "name": "background-position"}, {"name": "background-position-x"}, {"name": "background-position-y"}, {"longhands": ["background-repeat-x", "background-repeat-y"], "name": "background-repeat"}, {"name": "background-repeat-x"}, {"name": "background-repeat-y"}, {"name": "background-size"}, {"name": "baseline-shift", "svg": true}, {"name": "block-size"}, {"longhands": ["border-top-color", "border-top-style", "border-top-width", "border-right-color", "border-right-style", "border-right-width", "border-bottom-color", "border-bottom-style", "border-bottom-width", "border-left-color", "border-left-style", "border-left-width", "border-image-source", "border-image-slice", "border-image-width", "border-image-outset", "border-image-repeat"], "name": "border"}, {"longhands": ["border-bottom-width", "border-bottom-style", "border-bottom-color"], "name": "border-bottom"}, {"name": "border-bottom-color"}, {"name": "border-bottom-left-radius"}, {"name": "border-bottom-right-radius"}, {"name": "border-bottom-style"}, {"name": "border-bottom-width"}, {"name": "border-collapse", "inherited": true}, {"longhands": ["border-top-color", "border-right-color", "border-bottom-color", "border-left-color"], "name": "border-color"}, {"longhands": ["border-image-source", "border-image-slice", "border-image-width", "border-image-outset", "border-image-repeat"], "name": "border-image"}, {"name": "border-image-outset"}, {"name": "border-image-repeat"}, {"name": "border-image-slice"}, {"name": "border-image-source"}, {"name": "border-image-width"}, {"longhands": ["border-left-width", "border-left-style", "border-left-color"], "name": "border-left"}, {"name": "border-left-color"}, {"name": "border-left-style"}, {"name": "border-left-width"}, {"longhands": ["border-top-left-radius", "border-top-right-radius", "border-bottom-right-radius", "border-bottom-left-radius"], "name": "border-radius"}, {"longhands": ["border-right-width", "border-right-style", "border-right-color"], "name": "border-right"}, {"name": "border-right-color"}, {"name": "border-right-style"}, {"name": "border-right-width"}, {"longhands": ["-webkit-border-horizontal-spacing", "-webkit-border-vertical-spacing"], "name": "border-spacing"}, {"name": "border-style", "longhands": ["border-top-style", "border-right-style", "border-bottom-style", "border-left-style"]}, {"longhands": ["border-top-width", "border-top-style", "border-top-color"], "name": "border-top"}, {"name": "border-top-color"}, {"name": "border-top-left-radius"}, {"name": "border-top-right-radius"}, {"name": "border-top-style"}, {"name": "border-top-width"}, {"longhands": ["border-top-width", "border-right-width", "border-bottom-width", "border-left-width"], "name": "border-width"}, {"name": "bottom"}, {"name": "box-shadow"}, {"name": "box-sizing"}, {"name": "break-after"}, {"name": "break-before"}, {"name": "break-inside"}, {"svg": true, "name": "buffered-rendering"}, {"name": "caption-side", "inherited": true}, {"name": "caret-color", "inherited": true}, {"name": "clear"}, {"name": "clip"}, {"name": "clip-path"}, {"svg": true, "name": "clip-rule", "inherited": true}, {"name": "color", "inherited": true}, {"svg": true, "name": "color-interpolation", "inherited": true}, {"svg": true, "name": "color-interpolation-filters", "inherited": true}, {"svg": true, "name": "color-rendering", "inherited": true}, {"name": "column-count"}, {"name": "column-fill"}, {"name": "column-gap"}, {"longhands": ["column-rule-width", "column-rule-style", "column-rule-color"], "name": "column-rule"}, {"name": "column-rule-color"}, {"name": "column-rule-style"}, {"name": "column-rule-width"}, {"name": "column-span"}, {"name": "column-width"}, {"longhands": ["column-width", "column-count"], "name": "columns"}, {"name": "contain"}, {"name": "content"}, {"name": "counter-increment"}, {"name": "counter-reset"}, {"name": "cursor", "inherited": true}, {"name": "cx", "svg": true}, {"name": "cy", "svg": true}, {"name": "d", "svg": true}, {"name": "direction", "inherited": true}, {"name": "display"}, {"svg": true, "name": "dominant-baseline", "inherited": true}, {"name": "empty-cells", "inherited": true}, {"name": "fill", "svg": true, "inherited": true}, {"name": "fill-opacity", "svg": true, "inherited": true}, {"svg": true, "name": "fill-rule", "inherited": true}, {"name": "filter"}, {"longhands": ["flex-grow", "flex-shrink", "flex-basis"], "name": "flex"}, {"name": "flex-basis"}, {"name": "flex-direction"}, {"longhands": ["flex-direction", "flex-wrap"], "name": "flex-flow"}, {"name": "flex-grow"}, {"name": "flex-shrink"}, {"name": "flex-wrap"}, {"name": "float"}, {"name": "flood-color", "svg": true}, {"name": "flood-opacity", "svg": true}, {"longhands": ["font-style", "font-variant-ligatures", "font-variant-caps", "font-variant-numeric", "font-variant-east-asian", "font-weight", "font-stretch", "font-size", "line-height", "font-family"], "name": "font"}, {"name": "font-display"}, {"name": "font-family", "inherited": true}, {"name": "font-feature-settings", "inherited": true}, {"name": "font-kerning", "inherited": true}, {"name": "font-size", "inherited": true}, {"name": "font-size-adjust", "inherited": true}, {"name": "font-stretch", "inherited": true}, {"name": "font-style", "inherited": true}, {"longhands": ["font-variant-ligatures", "font-variant-caps", "font-variant-numeric", "font-variant-east-asian"], "name": "font-variant"}, {"name": "font-variant-caps", "inherited": true}, {"name": "font-variant-east-asian", "inherited": true}, {"name": "font-variant-ligatures", "inherited": true}, {"name": "font-variant-numeric", "inherited": true}, {"name": "font-variation-settings", "inherited": true}, {"name": "font-weight", "inherited": true}, {"longhands": ["grid-template-rows", "grid-template-columns", "grid-template-areas", "grid-auto-flow", "grid-auto-rows", "grid-auto-columns"], "name": "grid"}, {"longhands": ["grid-row-start", "grid-column-start", "grid-row-end", "grid-column-end"], "name": "grid-area"}, {"name": "grid-auto-columns"}, {"name": "grid-auto-flow"}, {"name": "grid-auto-rows"}, {"longhands": ["grid-column-start", "grid-column-end"], "name": "grid-column"}, {"name": "grid-column-end"}, {"name": "grid-column-gap"}, {"name": "grid-column-start"}, {"longhands": ["grid-row-gap", "grid-column-gap"], "name": "grid-gap"}, {"longhands": ["grid-row-start", "grid-row-end"], "name": "grid-row"}, {"name": "grid-row-end"}, {"name": "grid-row-gap"}, {"name": "grid-row-start"}, {"longhands": ["grid-template-rows", "grid-template-columns", "grid-template-areas"], "name": "grid-template"}, {"name": "grid-template-areas"}, {"name": "grid-template-columns"}, {"name": "grid-template-rows"}, {"name": "height"}, {"name": "hyphens", "inherited": true}, {"name": "image-orientation", "inherited": true}, {"name": "image-rendering", "inherited": true}, {"name": "inline-size"}, {"name": "isolation"}, {"name": "justify-content"}, {"name": "justify-items"}, {"name": "justify-self"}, {"name": "left"}, {"name": "letter-spacing", "inherited": true}, {"name": "lighting-color", "svg": true}, {"name": "line-break", "inherited": true}, {"name": "line-height", "inherited": true}, {"name": "line-height-step", "inherited": true}, {"longhands": ["list-style-type", "list-style-position", "list-style-image"], "name": "list-style"}, {"name": "list-style-image", "inherited": true}, {"name": "list-style-position", "inherited": true}, {"name": "list-style-type", "inherited": true}, {"longhands": ["margin-top", "margin-right", "margin-bottom", "margin-left"], "name": "margin"}, {"name": "margin-bottom"}, {"name": "margin-left"}, {"name": "margin-right"}, {"name": "margin-top"}, {"longhands": ["marker-start", "marker-mid", "marker-end"], "name": "marker"}, {"name": "marker-end", "svg": true, "inherited": true}, {"name": "marker-mid", "svg": true, "inherited": true}, {"name": "marker-start", "svg": true, "inherited": true}, {"name": "mask", "svg": true}, {"name": "mask-source-type"}, {"svg": true, "name": "mask-type"}, {"name": "max-block-size"}, {"name": "max-height"}, {"name": "max-inline-size"}, {"name": "max-width"}, {"name": "max-zoom"}, {"name": "min-block-size"}, {"name": "min-height"}, {"name": "min-inline-size"}, {"name": "min-width"}, {"name": "min-zoom"}, {"name": "mix-blend-mode"}, {"name": "object-fit"}, {"name": "object-position"}, {"longhands": ["offset-position", "offset-path", "offset-distance", "offset-rotate", "offset-anchor"], "name": "offset"}, {"name": "offset-anchor"}, {"name": "offset-distance"}, {"name": "offset-path"}, {"name": "offset-position"}, {"name": "offset-rotate"}, {"name": "opacity"}, {"name": "order"}, {"name": "orientation"}, {"name": "orphans", "inherited": true}, {"longhands": ["outline-color", "outline-style", "outline-width"], "name": "outline"}, {"name": "outline-color"}, {"name": "outline-offset"}, {"name": "outline-style"}, {"name": "outline-width"}, {"longhands": ["overflow-x", "overflow-y"], "name": "overflow"}, {"name": "overflow-anchor", "inherited": false}, {"name": "overflow-wrap", "inherited": true}, {"name": "overflow-x"}, {"name": "overflow-y"}, {"longhands": ["overscroll-behavior-x", "overscroll-behavior-y"], "name": "overscroll-behavior"}, {"name": "overscroll-behavior-x"}, {"name": "overscroll-behavior-y"}, {"longhands": ["padding-top", "padding-right", "padding-bottom", "padding-left"], "name": "padding"}, {"name": "padding-bottom"}, {"name": "padding-left"}, {"name": "padding-right"}, {"name": "padding-top"}, {"name": "page"}, {"longhands": ["break-after"], "name": "page-break-after"}, {"longhands": ["break-before"], "name": "page-break-before"}, {"longhands": ["break-inside"], "name": "page-break-inside"}, {"name": "paint-order", "svg": true, "inherited": true}, {"name": "perspective"}, {"name": "perspective-origin"}, {"longhands": ["align-content", "justify-content"], "name": "place-content"}, {"longhands": ["align-items", "justify-items"], "name": "place-items"}, {"longhands": ["align-self", "justify-self"], "name": "place-self"}, {"name": "pointer-events", "inherited": true}, {"name": "position"}, {"name": "quotes", "inherited": true}, {"name": "r", "svg": true}, {"name": "resize"}, {"name": "right"}, {"name": "rotate"}, {"name": "rx", "svg": true}, {"name": "ry", "svg": true}, {"name": "scale"}, {"name": "scroll-behavior"}, {"longhands": ["scroll-padding-top", "scroll-padding-right", "scroll-padding-bottom", "scroll-padding-left"], "name": "scroll-padding"}, {"longhands": ["scroll-padding-block-start", "scroll-padding-block-end"], "name": "scroll-padding-block"}, {"name": "scroll-padding-block-end"}, {"name": "scroll-padding-block-start"}, {"name": "scroll-padding-bottom"}, {"longhands": ["scroll-padding-inline-start", "scroll-padding-inline-end"], "name": "scroll-padding-inline"}, {"name": "scroll-padding-inline-end"}, {"name": "scroll-padding-inline-start"}, {"name": "scroll-padding-left"}, {"name": "scroll-padding-right"}, {"name": "scroll-padding-top"}, {"name": "scroll-snap-align"}, {"longhands": ["scroll-snap-margin-top", "scroll-snap-margin-right", "scroll-snap-margin-bottom", "scroll-snap-margin-left"], "name": "scroll-snap-margin"}, {"longhands": ["scroll-snap-margin-block-start", "scroll-snap-margin-block-end"], "name": "scroll-snap-margin-block"}, {"name": "scroll-snap-margin-block-end"}, {"name": "scroll-snap-margin-block-start"}, {"name": "scroll-snap-margin-bottom"}, {"longhands": ["scroll-snap-margin-inline-start", "scroll-snap-margin-inline-end"], "name": "scroll-snap-margin-inline"}, {"name": "scroll-snap-margin-inline-end"}, {"name": "scroll-snap-margin-inline-start"}, {"name": "scroll-snap-margin-left"}, {"name": "scroll-snap-margin-right"}, {"name": "scroll-snap-margin-top"}, {"name": "scroll-snap-stop"}, {"name": "scroll-snap-type"}, {"name": "shape-image-threshold"}, {"name": "shape-margin"}, {"name": "shape-outside"}, {"svg": true, "name": "shape-rendering", "inherited": true}, {"name": "size"}, {"name": "speak", "inherited": true}, {"name": "src"}, {"name": "stop-color", "svg": true}, {"name": "stop-opacity", "svg": true}, {"name": "stroke", "svg": true, "inherited": true}, {"name": "stroke-dasharray", "svg": true, "inherited": true}, {"name": "stroke-dashoffset", "svg": true, "inherited": true}, {"name": "stroke-linecap", "svg": true, "inherited": true}, {"name": "stroke-linejoin", "svg": true, "inherited": true}, {"name": "stroke-miterlimit", "svg": true, "inherited": true}, {"name": "stroke-opacity", "svg": true, "inherited": true}, {"name": "stroke-width", "svg": true, "inherited": true}, {"name": "tab-size", "inherited": true}, {"name": "table-layout"}, {"name": "text-align", "inherited": true}, {"name": "text-align-last", "inherited": true}, {"svg": true, "name": "text-anchor", "inherited": true}, {"name": "text-combine-upright", "inherited": true}, {"longhands": ["text-decoration-line", "text-decoration-style", "text-decoration-color"], "name": "text-decoration"}, {"name": "text-decoration-color"}, {"name": "text-decoration-line"}, {"name": "text-decoration-skip", "inherited": true}, {"name": "text-decoration-style"}, {"name": "text-indent", "inherited": true}, {"name": "text-justify", "inherited": true}, {"name": "text-orientation", "inherited": true}, {"name": "text-overflow"}, {"name": "text-rendering", "inherited": true}, {"name": "text-shadow", "inherited": true}, {"name": "text-size-adjust", "inherited": true}, {"name": "text-transform", "inherited": true}, {"name": "text-underline-position", "inherited": true}, {"name": "top"}, {"name": "touch-action"}, {"name": "transform"}, {"name": "transform-box"}, {"name": "transform-origin"}, {"name": "transform-style"}, {"longhands": ["transition-property", "transition-duration", "transition-timing-function", "transition-delay"], "name": "transition"}, {"name": "transition-delay"}, {"name": "transition-duration"}, {"name": "transition-property"}, {"name": "transition-timing-function"}, {"name": "translate"}, {"name": "unicode-bidi"}, {"name": "unicode-range"}, {"name": "user-select", "inherited": true}, {"name": "user-zoom"}, {"svg": true, "name": "vector-effect"}, {"name": "vertical-align"}, {"name": "visibility", "inherited": true}, {"name": "white-space", "inherited": true}, {"name": "widows", "inherited": true}, {"name": "width"}, {"name": "will-change"}, {"name": "word-break", "inherited": true}, {"name": "word-spacing", "inherited": true}, {"name": "word-wrap", "inherited": true}, {"name": "writing-mode", "inherited": true}, {"name": "x", "svg": true}, {"name": "y", "svg": true}, {"name": "z-index"}, {"name": "zoom"}]; 2 | -------------------------------------------------------------------------------- /src/Dashboard.ts: -------------------------------------------------------------------------------- 1 | import {WebServer} from './WebServer'; 2 | import {Home} from './impl/Home'; 3 | import {Static} from './impl/Static'; 4 | import {Actuator} from './impl/Actuator'; 5 | import {Stdout} from './impl/Stdout'; 6 | import {ChromeDevtools} from './impl/ChromeDevtools'; 7 | import {DebuggerProxy} from './impl/DebuggerProxy'; 8 | import * as auth from 'basic-auth'; 9 | 10 | export default class Dashboard extends WebServer { 11 | 12 | setup() { 13 | const DASHBOARD_AUTH = process.env.DASHBOARD_AUTH; 14 | let authName, authPass; 15 | if(typeof DASHBOARD_AUTH === 'string') { 16 | [authName, authPass] = DASHBOARD_AUTH.split(':'); 17 | } 18 | if(authName && authPass) { 19 | this.use( async (ctx, next) => { 20 | const credentials = auth(ctx.req); 21 | if (!credentials || credentials.name !== authName || credentials.pass !== authPass) { 22 | ctx.status = 401; 23 | ctx.set('WWW-Authenticate', 'Basic'); 24 | ctx.body = 'Access denied'; 25 | } else { 26 | await next(); 27 | } 28 | }); 29 | } 30 | super.setup(); 31 | } 32 | 33 | getRoutes() { 34 | return [ ChromeDevtools, DebuggerProxy, Stdout, Actuator, Static, Home ]; 35 | } 36 | 37 | getPort() { 38 | const port: number = process.env.DASHBOARD_PORT ? Number(process.env.DASHBOARD_PORT) : 9081; 39 | const host: string = process.env.DASHBOARD_HOST || '127.0.0.1'; 40 | return { port, host }; 41 | } 42 | 43 | async start () { 44 | await super.start(); 45 | const {port, host} = this.getPort(); 46 | console.log(`Pandora.js Dashboard started, open http://${host}:${port}/`); 47 | // this.echoTestErrors().catch(console.error); 48 | } 49 | 50 | async echoTestErrors () { 51 | for(let idx = 0; idx < 100; idx++) { 52 | await new Promise(resolve => { 53 | setTimeout(resolve, 200); 54 | }); 55 | console.error(new Error('Test Errror ' + (idx + 1))); 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/WebServer.ts: -------------------------------------------------------------------------------- 1 | import * as Koa from 'koa'; 2 | import * as Router from 'koa-router'; 3 | 4 | import {createServer, Server} from 'http'; 5 | 6 | const methods = ['get', 'put', 'post', 'patch', 'delete', 'del']; 7 | 8 | export abstract class WebServer extends Koa { 9 | 10 | server: Server; 11 | router: any; 12 | 13 | pandoraContext; 14 | 15 | constructor(pandoraContext) { 16 | super(); 17 | this.pandoraContext = pandoraContext; 18 | this.router = new Router; 19 | this.server = createServer(this.callback()); 20 | this.setup(); 21 | this.use(this.router.routes()); 22 | this.use(this.router.allowedMethods()); 23 | } 24 | 25 | setup() { 26 | const router = this.router; 27 | const routes: any[] = this.getRoutes(); 28 | for(const Route of routes) { 29 | const routePath = Route.route; 30 | const route = new Route(this); 31 | if(route.setup) { 32 | route.setup(); 33 | } 34 | for(const method of methods) { 35 | if(route[method]) { 36 | router[method](routePath, route[method].bind(route)); 37 | } 38 | } 39 | } 40 | this.server.on('upgrade', (request, socket) => { 41 | if(!socket.wsHasBeenTaken) { 42 | socket.end(); 43 | } 44 | }); 45 | } 46 | 47 | abstract getRoutes(); 48 | abstract getPort(): {port: number, host: string}; 49 | 50 | async start() { 51 | const {port, host} = this.getPort(); 52 | await new Promise((resolve, reject) => { 53 | this.server.listen({ port, host }, (err) => { 54 | if(err) { 55 | reject(err); 56 | return; 57 | } 58 | resolve(); 59 | }); 60 | }); 61 | } 62 | 63 | async stop() { 64 | await new Promise((resolve) => { 65 | this.server.close(resolve); 66 | }); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/impl/Actuator.ts: -------------------------------------------------------------------------------- 1 | import Dashboard from '../Dashboard'; 2 | import urllib = require('urllib'); 3 | import {attachPPID} from '../utils/Common'; 4 | const {GlobalConfigProcessor} = require('dorapan'); 5 | const globalConfig = GlobalConfigProcessor.getInstance().getAllProperties(); 6 | const actuatorPort = globalConfig.actuator.http.port; 7 | 8 | export class Actuator { 9 | 10 | static route = '/actuator/*'; 11 | 12 | app: Dashboard; 13 | constructor(app) { 14 | this.app = app; 15 | } 16 | 17 | async get(ctx) { 18 | const url: string = /^\/actuator(.*)/.exec(ctx.request.url)[1]; 19 | ctx.body = await Actuator.get(url); 20 | } 21 | 22 | static async get(url) { 23 | const backend = process.env.DASHBOARD_BACKEND || 'http://127.0.0.1:' + actuatorPort; 24 | // http://testgw.proxy.taobao.org/ 25 | const remoteUrl = backend + url; 26 | const res = await urllib.request(remoteUrl, { 27 | timeout: 5000, 28 | dataType: 'json' 29 | }); 30 | if(/^\/process/.test(url) && res.data.success && res.data.data) { 31 | try { 32 | await attachPPID(res.data.data); 33 | } catch(err) { 34 | // pass 35 | } 36 | } 37 | return res.data; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/impl/ChromeDevtools.ts: -------------------------------------------------------------------------------- 1 | import Dashboard from '../Dashboard'; 2 | import {dirname, join} from 'path'; 3 | import staticCache = require('koa-static-cache'); 4 | import * as fs from 'fs'; 5 | import * as util from 'util'; 6 | const readFile = util.promisify(fs.readFile); 7 | 8 | 9 | export class ChromeDevtools { 10 | 11 | app: Dashboard; 12 | constructor(app) { 13 | this.app = app; 14 | } 15 | 16 | setup () { 17 | 18 | this.app.router.get('/chrome-devtools/InspectorBackendCommands.js', async (ctx) => { 19 | ctx.type = 'application/javascript'; 20 | ctx.body = await readFile(join(__dirname, '../../resource/chrome-devtools/InspectorBackendCommands.js')); 21 | }); 22 | 23 | this.app.router.get('/chrome-devtools/SupportedCSSProperties.js', async (ctx) => { 24 | ctx.type = 'application/javascript'; 25 | ctx.body = await readFile(join(__dirname, '../../resource/chrome-devtools/SupportedCSSProperties.js')); 26 | }); 27 | 28 | this.app.use(staticCache({ 29 | dir: dirname(require.resolve('chrome-devtools-frontend/front_end/inspector.html')), 30 | prefix: '/chrome-devtools' 31 | })); 32 | 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/impl/DebuggerProxy.ts: -------------------------------------------------------------------------------- 1 | 2 | import Dashboard from '../Dashboard'; 3 | import urllib = require('urllib'); 4 | import {Server as WSServer} from 'ws'; 5 | import * as WebSocket from 'ws'; 6 | import {Actuator} from './Actuator'; 7 | 8 | 9 | export class DebuggerProxy { 10 | 11 | app: Dashboard; 12 | wss: WSServer; 13 | constructor(app) { 14 | this.app = app; 15 | this.wss = new WSServer({ noServer: true }); 16 | } 17 | 18 | setup () { 19 | 20 | this.app.server.on('upgrade', (request, socket, head) => { 21 | 22 | const regRes = /^\/debugger-proxy\/([^\/]*)\/([^\/]*)/.exec(request.url); 23 | if(!regRes) { 24 | return; 25 | } 26 | socket.wsHasBeenTaken = true; 27 | 28 | const appName = regRes[1]; 29 | const pid = parseInt(regRes[2], 10); 30 | 31 | this.wss.handleUpgrade(request, socket, head, (ws) => { 32 | this.handleConnection(appName, pid, ws).catch((error) => { 33 | ws.terminate(); 34 | throw error; 35 | }).catch(console.error); 36 | }); 37 | }); 38 | 39 | } 40 | 41 | async handleConnection(appName, pid, ws) { 42 | 43 | ws.pause(); 44 | 45 | const res = await Actuator.get('/process?appName=' + encodeURIComponent(appName)); 46 | if(!res.success) { 47 | throw new Error(res.message); 48 | } 49 | const processes = res.data; 50 | 51 | let process; 52 | for(const item of processes) { 53 | if(item.pid === pid) { 54 | process = item; 55 | } 56 | } 57 | 58 | if(!process) { 59 | throw new Error('Cannot found process [ pid: ' + pid + ' ]'); 60 | } 61 | 62 | const debugPort = process.debugPort; 63 | 64 | const listUrl = `http://127.0.0.1:${debugPort}/json/list`; 65 | const listRes = await urllib.request(listUrl, { timeout: 5000, dataType: 'json' }); 66 | if(!listRes.data || !listRes.data.length) { 67 | throw new Error('Cannot found any instance at ' + listUrl); 68 | } 69 | const uuid = listRes.data[0].id; 70 | const wsUrl = `ws://127.0.0.1:${debugPort}/${uuid}`; 71 | console.log(wsUrl); 72 | 73 | const targetWs = new WebSocket(wsUrl); 74 | targetWs.on('open', () => { 75 | ws.resume(); 76 | }); 77 | 78 | ws.on('message', function (data) { 79 | try { 80 | targetWs.send(data); 81 | } catch (err) { 82 | console.error(err); 83 | } 84 | }); 85 | 86 | targetWs.on('message', function(data) { 87 | try { 88 | ws.send(data); 89 | } catch (err) { 90 | console.error(err); 91 | } 92 | }); 93 | 94 | const close = () => { 95 | try { 96 | ws.close(); 97 | } catch(err) { } 98 | try { 99 | targetWs.close(); 100 | } catch(err) { } 101 | }; 102 | targetWs.on('error', close); 103 | targetWs.on('close', close); 104 | ws.on('close', close); 105 | ws.on('error', close); 106 | 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/impl/Home.ts: -------------------------------------------------------------------------------- 1 | import Dashboard from '../Dashboard'; 2 | 3 | export class Home { 4 | 5 | static route = '*'; 6 | 7 | app: Dashboard; 8 | constructor(app) { 9 | this.app = app; 10 | } 11 | 12 | async get(ctx) { 13 | 14 | const publicBaseURL = process.env.DASHBOARD_PUBLIC_BASE_URL || '/public'; 15 | 16 | ctx.set('Content-Type', 'text/html'); 17 | ctx.body = ` 18 | 19 | 20 | Pandora.js Dashboard 21 | 22 | 23 |
24 | 25 | 26 | 27 | `; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /src/impl/Static.ts: -------------------------------------------------------------------------------- 1 | import Dashboard from '../Dashboard'; 2 | import mount = require('koa-mount'); 3 | import serve = require('koa-static'); 4 | import {join} from 'path'; 5 | 6 | export class Static { 7 | 8 | app: Dashboard; 9 | constructor(app) { 10 | this.app = app; 11 | } 12 | 13 | setup() { 14 | this.app.use(mount('/public', serve( 15 | join(__dirname, '../../public/build'), 16 | { 17 | gzip: true 18 | } 19 | ))); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/impl/Stdout.ts: -------------------------------------------------------------------------------- 1 | import Dashboard from '../Dashboard'; 2 | import {Server as WSServer} from 'ws'; 3 | import {Actuator} from './Actuator'; 4 | import tailPkg = require('tail'); 5 | import readLastLines = require('read-last-lines'); 6 | const {Tail} = tailPkg; 7 | 8 | 9 | export class Stdout { 10 | 11 | app: Dashboard; 12 | wss: WSServer; 13 | constructor(app) { 14 | this.app = app; 15 | this.wss = new WSServer({ noServer: true }); 16 | } 17 | 18 | setup () { 19 | 20 | this.app.server.on('upgrade', (request, socket, head) => { 21 | 22 | const regRes = /^\/stdout\/(.*)$/.exec(request.url); 23 | if(!regRes) { 24 | return; 25 | } 26 | socket.wsHasBeenTaken = true; 27 | 28 | const appName = regRes[1]; 29 | this.wss.handleUpgrade(request, socket, head, (ws) => { 30 | this.handleConnection(appName, ws).catch((error) => { 31 | ws.send(JSON.stringify({ type: 'error', error: String(error) })); 32 | ws.terminate(); 33 | }).catch(console.error); 34 | }); 35 | }); 36 | 37 | } 38 | 39 | async handleConnection(appName, ws) { 40 | 41 | const res = await Actuator.get('/info?appName=' + encodeURIComponent(appName)); 42 | if(!res.success) { 43 | throw new Error(res.message); 44 | } 45 | const app = res.data; 46 | const introspection = app[0].data; 47 | const stdoutLogPath = introspection.stdoutLogPath; 48 | const lastLines = await readLastLines.read(stdoutLogPath, 100); 49 | const tail = new Tail(stdoutLogPath); 50 | ws.on('close', () => { 51 | tail.unwatch(); 52 | }); 53 | ws.send(JSON.stringify({ type: 'batch', content: lastLines })); 54 | tail.on('line', line => { 55 | ws.send(JSON.stringify({ type: 'line', content: line })); 56 | }); 57 | tail.on('error', err => { 58 | console.error(err); 59 | ws.terminate(); 60 | }); 61 | 62 | } 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/utils/Common.ts: -------------------------------------------------------------------------------- 1 | import cp = require('mz/child_process'); 2 | 3 | export async function attachPPID (processes) { 4 | const relations = await getPPIDRelations(); 5 | for(const process of processes) { 6 | if(!process.ppid) { 7 | process.ppid = relations.get(Number(process.pid)); 8 | } 9 | } 10 | return processes; 11 | } 12 | 13 | export async function getPPIDRelations () { 14 | const stdout = await cp.exec('ps -A -o pid,ppid'); 15 | const ps = stdout.toString().split('\n'); 16 | // get rid of the header 17 | ps.shift(); 18 | // get rid of the last empty line 19 | ps.pop(); 20 | 21 | const relations: Map = new Map; 22 | ps.forEach(line => { 23 | line = line.trim(); 24 | const matches = line.match(/^(\d+)\s+(\d+)/); 25 | matches.shift(); 26 | const [pid, ppid] = matches; 27 | relations.set(Number(pid), Number(ppid)); 28 | }); 29 | return relations; 30 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": false, 4 | "target": "ES6", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "experimentalDecorators": true, 8 | "noImplicitThis": true, 9 | "noUnusedLocals": true, 10 | "stripInternal": true, 11 | "pretty": true, 12 | "declaration": true, 13 | "sourceMap": true, 14 | "outDir": "dist" 15 | }, 16 | "files": [ 17 | "src/Dashboard.ts" 18 | ], 19 | "exclude": [ 20 | "node_modules", 21 | "doc" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": [ 3 | "**/dist/**" 4 | ], 5 | "rules": { 6 | "jsdoc-format": true, 7 | "class-name": true, 8 | "comment-format": [ 9 | true, 10 | "check-space" 11 | ], 12 | "indent": [ 13 | true, 14 | "spaces" 15 | ], 16 | "no-duplicate-variable": true, 17 | "no-eval": true, 18 | "no-internal-module": true, 19 | "no-trailing-whitespace": true, 20 | "no-unsafe-finally": true, 21 | "no-var-keyword": true, 22 | "one-line": [ 23 | true, 24 | "check-open-brace", 25 | "check-whitespace" 26 | ], 27 | "quotemark": [ 28 | true, 29 | "single" 30 | ], 31 | "semicolon": [ 32 | true, 33 | "always" 34 | ], 35 | "triple-equals": [ 36 | true, 37 | "allow-null-check" 38 | ], 39 | "typedef-whitespace": [ 40 | true, 41 | { 42 | "call-signature": "nospace", 43 | "index-signature": "nospace", 44 | "parameter": "nospace", 45 | "property-declaration": "nospace", 46 | "variable-declaration": "nospace" 47 | } 48 | ], 49 | "variable-name": [ 50 | true, 51 | "ban-keywords" 52 | ], 53 | "whitespace": [ 54 | true, 55 | "check-decl", 56 | "check-operator", 57 | "check-separator", 58 | "check-type" 59 | ] 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const CompressionPlugin = require("compression-webpack-plugin"); 3 | 4 | module.exports = { 5 | entry: './public/src/app.jsx', 6 | output: { 7 | path: path.join(__dirname, './public/build'), 8 | filename: 'bundle.js' 9 | }, 10 | resolve: { 11 | extensions: ['.js', '.jsx'] 12 | }, 13 | module: { 14 | rules: [ 15 | { 16 | test: /\.css$/, 17 | use: [ 'style-loader', 'css-loader' ] 18 | }, 19 | { 20 | test: /\.(js|jsx)$/, 21 | exclude: /(node_modules|bower_components)/, 22 | use: { 23 | loader: 'babel-loader', 24 | options: { 25 | presets: ['env', 'react'] 26 | } 27 | } 28 | } 29 | ] 30 | }, 31 | plugins: [ 32 | new CompressionPlugin({ 33 | asset: "[path].gz[query]", 34 | algorithm: "gzip", 35 | test: /\.js$|\.css$|\.html$/, 36 | threshold: 10240, 37 | minRatio: 0 38 | }) 39 | ] 40 | }; --------------------------------------------------------------------------------