chore: introduce injected source lazily evaluated by execution context (#42)

This commit is contained in:
Dmitry Gozman 2019-11-21 14:43:30 -08:00 committed by GitHub
parent e3dcac1d46
commit 57bbd81824
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 88 additions and 5 deletions

View File

@ -9,4 +9,5 @@ node6-testrunner/*
lib/
*.js
src/chromium/protocol.d.ts
src/injected/injectedSource.ts
src/webkit/protocol.d.ts

1
.gitignore vendored
View File

@ -14,6 +14,7 @@ package-lock.json
yarn.lock
/node6
/src/chromium/protocol.d.ts
/src/injected/injectedSource.ts
/src/webkit/protocol.d.ts
/utils/browser/playwright-web.js
/index.d.ts

View File

@ -24,8 +24,8 @@
"doc": "node utils/doclint/cli.js",
"coverage": "cross-env COVERAGE=true npm run unit",
"tsc": "tsc -p .",
"build": "tsc -p .",
"watch": "tsc -w -p .",
"build": "npx webpack --config src/injected/webpack-injected.config.js --mode='production' && tsc -p .",
"watch": "npx webpack --config src/injected/webpack-injected.config.js --mode='development' --watch --silent | tsc -w -p .",
"apply-next-version": "node utils/apply_next_version.js",
"bundle": "npx browserify -r ./index.js:playwright -o utils/browser/playwright-web.js",
"test-types": "node utils/doclint/generate_types && npx -p typescript@2.1 tsc -p utils/doclint/generate_types/test/",
@ -62,7 +62,10 @@
"pixelmatch": "^4.0.2",
"pngjs": "^3.3.3",
"text-diff": "^1.0.1",
"typescript": "3.6.3"
"ts-loader": "^6.1.2",
"typescript": "3.6.3",
"webpack": "^4.41.0",
"webpack-cli": "^3.3.9"
},
"browser": {
"./lib/BrowserFetcher.js": false,

View File

@ -22,7 +22,7 @@ import { assert, helper } from '../helper';
import { valueFromRemoteObject, getExceptionMessage } from './protocolHelper';
import { createJSHandle, ElementHandle, JSHandle } from './JSHandle';
import { Protocol } from './protocol';
import { injectedSource } from '../injected/injectedSource';
export const EVALUATION_SCRIPT_URL = '__playwright_evaluation_script__';
const SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m;
@ -30,6 +30,7 @@ const SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m;
export class ExecutionContext {
_client: CDPSession;
_world: DOMWorld;
private _injectedPromise: Promise<JSHandle> | null = null;
private _contextId: number;
constructor(client: CDPSession, contextPayload: Protocol.Runtime.ExecutionContextDescription, world: DOMWorld | null) {
@ -159,4 +160,10 @@ export class ExecutionContext {
});
return createJSHandle(this, object) as ElementHandle;
}
_injected(): Promise<JSHandle> {
if (!this._injectedPromise)
this._injectedPromise = this.evaluateHandle(injectedSource);
return this._injectedPromise;
}
}

28
src/injected/injected.ts Normal file
View File

@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
class Utils {
parentElementOrShadowHost(element: Element): Element | undefined {
if (element.parentElement)
return element.parentElement;
if (!element.parentNode)
return;
if (element.parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE && (element.parentNode as ShadowRoot).host)
return (element.parentNode as ShadowRoot).host;
}
deepElementFromPoint(document: Document, x: number, y: number): Element | undefined {
let container: Document | ShadowRoot | null = document;
let element: Element | undefined;
while (container) {
const innerElement = container.elementFromPoint(x, y) as Element | undefined;
if (!innerElement || element === innerElement)
break;
element = innerElement;
container = element.shadowRoot;
}
return element;
}
}
export const utils = new Utils();

View File

@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
const fs = require('fs');
const path = require('path');
class InlineInjectedSource {
apply(compiler) {
compiler.hooks.emit.tapAsync('InlineInjectedSource', (compilation, callback) => {
const source = compilation.assets['injectedSource.js'].source();
const newSource = 'export const injectedSource = ' + JSON.stringify(source) + ';';
fs.writeFileSync(path.join(__dirname, 'injectedSource.ts'), newSource);
callback();
});
}
}
module.exports = {
entry: path.join(__dirname, 'injected.ts'),
devtool: 'source-map',
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
transpileOnly: true
},
exclude: /node_modules/
}
]
},
resolve: {
extensions: [ '.tsx', '.ts', '.js' ]
},
output: {
filename: 'injectedSource.js',
path: path.resolve(__dirname, '../../lib/injected')
},
plugins: [
new InlineInjectedSource(),
]
};