Skip to content

Commit

Permalink
feat: upgrade to Playwright 0.12.1 and update other deps (#71)
Browse files Browse the repository at this point in the history
- Updated new typings
- Updated dependencies
  • Loading branch information
renovate[bot] committed Mar 24, 2020
1 parent 361da93 commit 3a008e5
Show file tree
Hide file tree
Showing 11 changed files with 4,528 additions and 3,463 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ node_modules/
.DS_Store
.env
data/
*.sqlite
241 changes: 92 additions & 149 deletions backend/package-lock.json

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@
"author": "Max Schmitt <max@schmitt.mx>",
"license": "MIT",
"dependencies": {
"@sentry/node": "^5.13.0",
"@sentry/node": "^5.15.0",
"bottleneck": "^2.19.5",
"express": "^4.17.1",
"ffmpeg-static": "^4.0.1",
"mime-types": "^2.1.26",
"playwright": "^0.11.1-next.1583993157193",
"playwright-core": "^0.11.1-next.1583993157193",
"playwright-video": "^0.5.0",
"sqlite": "^3.0.3",
"playwright": "^0.12.1",
"playwright-core": "^0.12.1",
"playwright-video": "^0.12.0",
"sqlite": "^3.0.6",
"sqlite3": "^4.1.1",
"typescript": "^3.8.3",
"uuid": "^7.0.1",
"vm2": "^3.8.4"
"uuid": "^7.0.2",
"vm2": "^3.9.0"
},
"scripts": {
"build": "tsc",
Expand All @@ -29,12 +29,12 @@
"test": "jest"
},
"devDependencies": {
"@sentry/types": "5.14.2",
"@sentry/types": "5.15.0",
"@types/debug": "4.1.5",
"@types/express": "4.17.3",
"@types/jest": "25.1.4",
"@types/mime-types": "2.1.0",
"@types/node": "13.9.1",
"@types/node": "13.9.3",
"@types/sqlite3": "3.1.6",
"@types/uuid": "7.0.2",
"jest": "25.1.0",
Expand Down
53 changes: 30 additions & 23 deletions backend/src/playwright.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import path from 'path'
import { EventEmitter } from 'events'
import { v4 as uuidv4 } from 'uuid'
import { Browser, WebKitBrowser } from 'playwright-core'
import playwright from 'playwright-core'
import { Browser, WebKitBrowser, BrowserTypeLaunchOptions, PagePdfOptions, PageScreenshotOptions, ChromiumBrowser, FirefoxBrowser, Page as PageType } from 'playwright-core'
// @ts-ignore
import { Playwright } from 'playwright-core/lib/server/playwright'
import { CRBrowser } from 'playwright-core/lib/chromium/crBrowser';
// @ts-ignore
import { CRPage } from 'playwright-core/lib/chromium/crPage';
import { Page, FirefoxBrowser } from 'playwright-core/lib/api';
import { ScreenshotOptions, PDFOptions } from 'playwright-core/lib/types';
import { BufferType } from 'playwright-core/lib/platform';
import { LaunchOptions } from 'playwright-core/lib/server/browserType';
// @ts-ignore
import { Page } from 'playwright-core/lib/api';
// @ts-ignore
import { downloadOptionsFromENV } from 'playwright-core/download-browser';

import { saveVideo, PageVideoCapture } from 'playwright-video'

const BROWSER_ID = Symbol('BROWSER_ID');
Expand All @@ -27,7 +30,7 @@ export const registerFileListener = (browserId: string): (() => FileWrapper[]) =
}
}

const superScreenshot = Page.prototype.screenshot;
const superScreenshot: PageType["screenshot"] = Page.prototype.screenshot;

export const emitNewFile = (browserId: string, originalFileName: string): string => {
const ext = path.extname(originalFileName)
Expand All @@ -41,7 +44,7 @@ export const emitNewFile = (browserId: string, originalFileName: string): string
return publicPath
}

Page.prototype.screenshot = async function (options?: ScreenshotOptions): Promise<BufferType> {
Page.prototype.screenshot = async function (this: PageType, options?: PageScreenshotOptions): Promise<Buffer> {
if (options?.path) {
// @ts-ignore
const browserId = this.context()._browser[BROWSER_ID];
Expand All @@ -55,12 +58,12 @@ Page.prototype.screenshot = async function (options?: ScreenshotOptions): Promis
return Buffer.from([]);
}

const superCRPDF = CRPage.prototype.pdf;
const superCRPDF: PageType["pdf"] = CRPage.prototype.pdf;

CRPage.prototype.pdf = async function (options?: PDFOptions): Promise<BufferType> {
CRPage.prototype.pdf = async function (this: PageType, options?: PagePdfOptions): Promise<Buffer> {
if (options?.path && superCRPDF) {
// @ts-ignore
const browserId = this.page().context()._browser[BROWSER_ID];
const browserId = this._page.context()._browser[BROWSER_ID];
const publicPath = emitNewFile(browserId, options.path)
const buffer = await superCRPDF.call(this, {
...options,
Expand All @@ -82,16 +85,24 @@ const preBrowserLaunch = async (browser: Browser, id: string): Promise<void> =>
browser[BROWSER_ID] = id
}

export const getPlaywright = (id: string): Playwright => {
const pw = new Playwright({
downloadPath: path.join(__dirname, "..", "node_modules", "playwright"),
const pwDirname = path.join(__dirname, "..", "node_modules", "playwright")
const crExecutablePath = downloadOptionsFromENV(pwDirname, 'chromium').executablePath
const ffExecutablePath = downloadOptionsFromENV(pwDirname, 'firefox').executablePath
const wkExecutablePath = downloadOptionsFromENV(pwDirname, 'webkit').executablePath

export const getPlaywright = (id: string): typeof playwright => {
const pw: typeof playwright = new Playwright({
browsers: ['webkit', 'chromium', 'firefox'],
respectEnvironmentVariables: false,
});
// @ts-ignore
const originalChromiumLaunch = pw.chromium.launch
pw.chromium._executablePath = crExecutablePath;
// @ts-ignore
pw.chromium.launch = async (options: LaunchOptions = {}): Promise<CRBrowser> => {
pw.webkit._executablePath = wkExecutablePath;
// @ts-ignore
pw.firefox._executablePath = ffExecutablePath;

const originalChromiumLaunch = pw.chromium.launch
pw.chromium.launch = async (options: BrowserTypeLaunchOptions = {}): Promise<ChromiumBrowser> => {
const browser = await originalChromiumLaunch.apply(pw.chromium, [{
...options,
args: [...(options.args !== undefined ? options.args : []), "--no-sandbox"]
Expand All @@ -100,19 +111,15 @@ export const getPlaywright = (id: string): Playwright => {
return browser
}

// @ts-ignore
const originalWebKitLaunch = pw.webkit.launch
// @ts-ignore
pw.webkit.launch = async (options: LaunchOptions = {}): Promise<WebKitBrowser> => {
pw.webkit.launch = async (options: BrowserTypeLaunchOptions = {}): Promise<WebKitBrowser> => {
const browser = await originalWebKitLaunch.apply(pw.webkit, [options])
await preBrowserLaunch(browser, id)
return browser
}

// @ts-ignore
const originalFirefoxLaunch = pw.firefox.launch
// @ts-ignore
pw.firefox.launch = async (options: LaunchOptions = {}): Promise<FirefoxBrowser> => {
pw.firefox.launch = async (options: BrowserTypeLaunchOptions = {}): Promise<FirefoxBrowser> => {
const browser = await originalFirefoxLaunch.apply(pw.firefox, [options])
await preBrowserLaunch(browser, id)
return browser
Expand Down
21 changes: 0 additions & 21 deletions backend/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,6 @@ const limiter = new Bottleneck({
maxConcurrent: 5
});

// https://github.com/patriksimek/vm2/issues/268#issuecomment-593536163
const vm2SecurityPatch = (vm: VM): void => {
// @ts-ignore
const internal = vm._internal;
const old = internal.Decontextify.object;
const handler = { __proto__: null };
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
internal.Decontextify.object = (object, traps, deepTraps, flags, mock) => {
const value = old(object, traps, deepTraps, flags, mock);
// @ts-ignore
const better = new Proxy(value, handler);
internal.Decontextify.proxies.set(object, better);
internal.Contextify.proxies.set(better, object);
return better;
};
};


export const runUntrustedCode = async (code: string): Promise<APIResponse> => {
if (!code) {
throw new Error("no code specified")
Expand Down Expand Up @@ -94,8 +75,6 @@ export const runUntrustedCode = async (code: string): Promise<APIResponse> => {
sandbox,
})

vm2SecurityPatch(vm)

await limiter.schedule(() => vm.run(code));

const files = getFiles()
Expand Down

0 comments on commit 3a008e5

Please sign in to comment.