UNPKG

@remotion/renderer

Version:

Render Remotion videos using Node.js or Bun

450 lines (449 loc) • 20.9 kB
"use strict"; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var _Page_instances, _Page_client, _Page_target, _Page_timeoutSettings, _Page_frameManager, _Page_pageBindings, _Page_onConsole, _Page_initialize, _Page_onTargetCrashed, _Page_onLogEntryAdded, _Page_onConsoleAPI, _Page_onBindingCalled, _Page_addConsoleMessage; Object.defineProperty(exports, "__esModule", { value: true }); exports.Page = void 0; /** * Copyright 2017 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const no_react_1 = require("remotion/no-react"); const format_logs_1 = require("../format-logs"); const logger_1 = require("../logger"); const truthy_1 = require("../truthy"); const ConsoleMessage_1 = require("./ConsoleMessage"); const EventEmitter_1 = require("./EventEmitter"); const FrameManager_1 = require("./FrameManager"); const JSHandle_1 = require("./JSHandle"); const TaskQueue_1 = require("./TaskQueue"); const TimeoutSettings_1 = require("./TimeoutSettings"); const assert_1 = require("./assert"); const util_1 = require("./util"); const shouldHideWarning = (log) => { // Mixed Content warnings caused by localhost should not be displayed if (log.text.includes('Mixed Content:') && log.text.includes('http://localhost:')) { return true; } return false; }; const format = (eventType, args) => { var _a, _b, _c, _d, _e, _f, _g, _h; const previewString = args .filter((a) => { var _a; return !(a.type === 'symbol' && ((_a = a.description) === null || _a === void 0 ? void 0 : _a.includes(`__remotion_`))); }) .map((a) => (0, format_logs_1.formatRemoteObject)(a)) .filter(Boolean) .join(' '); let logLevelFromRemotionLog = null; let tag = null; for (const a of args) { if (a.type === 'symbol' && ((_a = a.description) === null || _a === void 0 ? void 0 : _a.includes(`__remotion_level_`))) { logLevelFromRemotionLog = (_d = (_c = (_b = a.description) === null || _b === void 0 ? void 0 : _b.split('__remotion_level_')) === null || _c === void 0 ? void 0 : _c[1]) === null || _d === void 0 ? void 0 : _d.replace(')', ''); } if (a.type === 'symbol' && ((_e = a.description) === null || _e === void 0 ? void 0 : _e.includes(`__remotion_tag_`))) { tag = (_h = (_g = (_f = a.description) === null || _f === void 0 ? void 0 : _f.split('__remotion_tag_')) === null || _g === void 0 ? void 0 : _g[1]) === null || _h === void 0 ? void 0 : _h.replace(')', ''); } } const logLevelFromEvent = eventType === 'debug' ? 'verbose' : eventType === 'error' ? 'error' : eventType === 'warning' ? 'warn' : 'verbose'; return { previewString, logLevelFromRemotionLog, logLevelFromEvent, tag }; }; class Page extends EventEmitter_1.EventEmitter { static async _create({ client, target, defaultViewport, browser, sourceMapGetter, logLevel, indent, pageIndex, onBrowserLog, onLog, }) { const page = new Page({ client, target, browser, sourceMapGetter, logLevel, indent, pageIndex, onBrowserLog, onLog, }); await __classPrivateFieldGet(page, _Page_instances, "m", _Page_initialize).call(page); await page.setViewport(defaultViewport); return page; } constructor({ client, target, browser, sourceMapGetter, logLevel, indent, pageIndex, onBrowserLog, onLog, }) { super(); _Page_instances.add(this); this.closed = false; _Page_client.set(this, void 0); _Page_target.set(this, void 0); _Page_timeoutSettings.set(this, new TimeoutSettings_1.TimeoutSettings()); _Page_frameManager.set(this, void 0); _Page_pageBindings.set(this, new Map()); _Page_onConsole.set(this, (log) => { var _a, _b, _c; const stackTrace = log.stackTrace(); const { url, columnNumber, lineNumber } = (_a = stackTrace[0]) !== null && _a !== void 0 ? _a : {}; const logLevel = this.logLevel; const indent = this.indent; if (shouldHideWarning(log)) { return; } (_b = this.onBrowserLog) === null || _b === void 0 ? void 0 : _b.call(this, { stackTrace, text: log.text, type: log.type, }); if ((url === null || url === void 0 ? void 0 : url.endsWith(no_react_1.NoReactInternals.bundleName)) && lineNumber && this.sourceMapGetter()) { const origPosition = (_c = this.sourceMapGetter()) === null || _c === void 0 ? void 0 : _c.originalPositionFor({ column: columnNumber !== null && columnNumber !== void 0 ? columnNumber : 0, line: lineNumber, }); const file = [ origPosition === null || origPosition === void 0 ? void 0 : origPosition.source, origPosition === null || origPosition === void 0 ? void 0 : origPosition.line, origPosition === null || origPosition === void 0 ? void 0 : origPosition.column, ] .filter(truthy_1.truthy) .join(':'); const isDelayRenderClear = log.previewString.includes(no_react_1.NoReactInternals.DELAY_RENDER_CLEAR_TOKEN); const tabInfo = `Tab ${this.pageIndex}`; const tagInfo = [origPosition === null || origPosition === void 0 ? void 0 : origPosition.name, isDelayRenderClear ? null : file] .filter(truthy_1.truthy) .join('@'); const tag = [tabInfo, log.tag, log.tag ? null : tagInfo] .filter(truthy_1.truthy) .join(', '); this.onLog({ logLevel: log.logLevel, tag, previewString: log.previewString, }); } else if (log.type === 'error') { if (log.text.includes('Failed to load resource:')) { logger_1.Log.error({ logLevel, tag: url, indent }, // Sometimes the log is like this: // Failed to load resource: the server responded with a status of 404 () // We remove the empty parentheses. log.text.replace(/\(\)$/, '')); } else { logger_1.Log.error({ logLevel, tag: `console.${log.type}`, indent }, log.text); } } else { logger_1.Log.verbose({ logLevel, tag: `console.${log.type}`, indent }, log.text); } }); __classPrivateFieldSet(this, _Page_client, client, "f"); __classPrivateFieldSet(this, _Page_target, target, "f"); __classPrivateFieldSet(this, _Page_frameManager, new FrameManager_1.FrameManager(client, this, indent, logLevel), "f"); this.screenshotTaskQueue = new TaskQueue_1.TaskQueue(); this.browser = browser; this.id = String(Math.random()); this.sourceMapGetter = sourceMapGetter; this.logLevel = logLevel; this.indent = indent; this.pageIndex = pageIndex; this.onBrowserLog = onBrowserLog; this.onLog = onLog; client.on('Target.attachedToTarget', (event) => { switch (event.targetInfo.type) { case 'iframe': break; case 'worker': break; default: // If we don't detach from service workers, they will never die. // We still want to attach to workers for emitting events. // We still want to attach to iframes so sessions may interact with them. // We detach from all other types out of an abundance of caution. // See https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/devtools_agent_host_impl.cc?ss=chromium&q=f:devtools%20-f:out%20%22::kTypePage%5B%5D%22 // for the complete list of available types. client .send('Target.detachFromTarget', { sessionId: event.sessionId, }) .catch((err) => logger_1.Log.error({ indent, logLevel }, err)); } }); client.on('Runtime.consoleAPICalled', (event) => { return __classPrivateFieldGet(this, _Page_instances, "m", _Page_onConsoleAPI).call(this, event); }); client.on('Runtime.bindingCalled', (event) => { return __classPrivateFieldGet(this, _Page_instances, "m", _Page_onBindingCalled).call(this, event); }); client.on('Inspector.targetCrashed', () => { return __classPrivateFieldGet(this, _Page_instances, "m", _Page_onTargetCrashed).call(this); }); client.on('Log.entryAdded', (event) => { return __classPrivateFieldGet(this, _Page_instances, "m", _Page_onLogEntryAdded).call(this, event); }); } /** * Listen to page events. */ // Note: this method exists to define event typings and handle // proper wireup of cooperative request interception. Actual event listening and // dispatching is delegated to EventEmitter. on(eventName, handler) { return super.on(eventName, handler); } once(eventName, handler) { // Note: this method only exists to define the types; we delegate the impl // to EventEmitter. return super.once(eventName, handler); } off(eventName, handler) { return super.off(eventName, handler); } /** * @returns A target this page was created from. */ target() { return __classPrivateFieldGet(this, _Page_target, "f"); } _client() { return __classPrivateFieldGet(this, _Page_client, "f"); } /** * @returns The page's main frame. * @remarks * Page is guaranteed to have a main frame which persists during navigations. */ mainFrame() { return __classPrivateFieldGet(this, _Page_frameManager, "f").mainFrame(); } async setViewport(viewport) { const fromSurface = !process.env.DISABLE_FROM_SURFACE; const request = fromSurface ? { mobile: false, width: viewport.width, height: viewport.height, deviceScaleFactor: viewport.deviceScaleFactor, screenOrientation: { angle: 0, type: 'portraitPrimary', }, } : { mobile: false, width: viewport.width, height: viewport.height, deviceScaleFactor: 1, screenHeight: viewport.height, screenWidth: viewport.width, scale: viewport.deviceScaleFactor, viewport: { height: viewport.height * viewport.deviceScaleFactor, width: viewport.width * viewport.deviceScaleFactor, scale: 1, x: 0, y: 0, }, }; const { value } = await __classPrivateFieldGet(this, _Page_client, "f").send('Emulation.setDeviceMetricsOverride', request); return value; } setDefaultNavigationTimeout(timeout) { __classPrivateFieldGet(this, _Page_timeoutSettings, "f").setDefaultNavigationTimeout(timeout); } setDefaultTimeout(timeout) { __classPrivateFieldGet(this, _Page_timeoutSettings, "f").setDefaultTimeout(timeout); } async evaluateHandle(pageFunction, ...args) { const context = await this.mainFrame().executionContext(); return context.evaluateHandle(pageFunction, ...args); } url() { return this.mainFrame().url(); } goto({ url, timeout, options = {}, }) { return __classPrivateFieldGet(this, _Page_frameManager, "f").mainFrame().goto(url, timeout, options); } async bringToFront() { await __classPrivateFieldGet(this, _Page_client, "f").send('Page.bringToFront'); } async setAutoDarkModeOverride() { const result = await __classPrivateFieldGet(this, _Page_client, "f").send('Emulation.setEmulatedMedia', { media: 'screen', features: [ { name: 'prefers-color-scheme', value: 'dark', }, ], }); console.log(result); } evaluate(pageFunction, ...args) { return __classPrivateFieldGet(this, _Page_frameManager, "f").mainFrame().evaluate(pageFunction, ...args); } async evaluateOnNewDocument(pageFunction, ...args) { const source = (0, util_1.evaluationString)(pageFunction, ...args); await __classPrivateFieldGet(this, _Page_client, "f").send('Page.addScriptToEvaluateOnNewDocument', { source, }); } async close(options = { runBeforeUnload: undefined }) { const connection = __classPrivateFieldGet(this, _Page_client, "f").connection(); if (!connection) { return; } const runBeforeUnload = Boolean(options.runBeforeUnload); if (runBeforeUnload) { await __classPrivateFieldGet(this, _Page_client, "f").send('Page.close'); } else { await connection.send('Target.closeTarget', { targetId: __classPrivateFieldGet(this, _Page_target, "f")._targetId, }); await __classPrivateFieldGet(this, _Page_target, "f")._isClosedPromise; } } setBrowserSourceMapGetter(context) { this.sourceMapGetter = context; } } exports.Page = Page; _Page_client = new WeakMap(), _Page_target = new WeakMap(), _Page_timeoutSettings = new WeakMap(), _Page_frameManager = new WeakMap(), _Page_pageBindings = new WeakMap(), _Page_onConsole = new WeakMap(), _Page_instances = new WeakSet(), _Page_initialize = async function _Page_initialize() { await Promise.all([ __classPrivateFieldGet(this, _Page_frameManager, "f").initialize(), __classPrivateFieldGet(this, _Page_client, "f").send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: false, flatten: true, }), __classPrivateFieldGet(this, _Page_client, "f").send('Performance.enable'), __classPrivateFieldGet(this, _Page_client, "f").send('Log.enable'), ]); }, _Page_onTargetCrashed = function _Page_onTargetCrashed() { // This error message is being checked against in is-flaky-error.ts this.emit('error', new Error('Page crashed!')); }, _Page_onLogEntryAdded = function _Page_onLogEntryAdded(event) { var _a; const { level, text, args, source, url, lineNumber } = event.entry; if (args) { args.map((arg) => { return (0, util_1.releaseObject)(__classPrivateFieldGet(this, _Page_client, "f"), arg); }); } const { previewString, logLevelFromRemotionLog, logLevelFromEvent, tag } = format(level, args !== null && args !== void 0 ? args : []); if (source !== 'worker') { const message = new ConsoleMessage_1.ConsoleMessage({ type: level, text, args: [], stackTraceLocations: [{ url, lineNumber }], previewString, logLevel: logLevelFromRemotionLog !== null && logLevelFromRemotionLog !== void 0 ? logLevelFromRemotionLog : logLevelFromEvent, tag, }); (_a = this.onBrowserLog) === null || _a === void 0 ? void 0 : _a.call(this, { stackTrace: message.stackTrace(), text: message.text, type: message.type, }); __classPrivateFieldGet(this, _Page_onConsole, "f").call(this, message); } }, _Page_onConsoleAPI = function _Page_onConsoleAPI(event) { if (event.executionContextId === 0) { return; } const context = __classPrivateFieldGet(this, _Page_frameManager, "f").executionContextById(event.executionContextId, __classPrivateFieldGet(this, _Page_client, "f")); const values = event.args.map((arg) => { return (0, JSHandle_1._createJSHandle)(context, arg); }); __classPrivateFieldGet(this, _Page_instances, "m", _Page_addConsoleMessage).call(this, event.type, values, event.stackTrace); }, _Page_onBindingCalled = async function _Page_onBindingCalled(event) { let payload; try { payload = JSON.parse(event.payload); } catch (_a) { // The binding was either called by something in the page or it was // called before our wrapper was initialized. return; } const { type, name, seq, args } = payload; if (type !== 'exposedFun' || !__classPrivateFieldGet(this, _Page_pageBindings, "f").has(name)) { return; } let expression = null; try { const pageBinding = __classPrivateFieldGet(this, _Page_pageBindings, "f").get(name); (0, assert_1.assert)(pageBinding); const result = await pageBinding(...args); expression = (0, util_1.pageBindingDeliverResultString)(name, seq, result); } catch (_error) { if ((0, util_1.isErrorLike)(_error)) { expression = (0, util_1.pageBindingDeliverErrorString)(name, seq, _error.message, _error.stack); } else { expression = (0, util_1.pageBindingDeliverErrorValueString)(name, seq, _error); } } await __classPrivateFieldGet(this, _Page_client, "f").send('Runtime.evaluate', { expression, contextId: event.executionContextId, }); }, _Page_addConsoleMessage = function _Page_addConsoleMessage(eventType, args, stackTrace) { var _a, _b; const textTokens = []; for (const arg of args) { const remoteObject = arg._remoteObject; if (remoteObject.objectId) { textTokens.push(arg.toString()); } else { textTokens.push((0, util_1.valueFromRemoteObject)(remoteObject)); } } const stackTraceLocations = []; if (stackTrace) { for (const callFrame of stackTrace.callFrames) { stackTraceLocations.push({ url: callFrame.url, lineNumber: callFrame.lineNumber, columnNumber: callFrame.columnNumber, }); } } const { previewString, logLevelFromRemotionLog, logLevelFromEvent, tag } = format(eventType, (_a = args.map((a) => a._remoteObject)) !== null && _a !== void 0 ? _a : []); const logLevel = (_b = logLevelFromRemotionLog) !== null && _b !== void 0 ? _b : logLevelFromEvent; const message = new ConsoleMessage_1.ConsoleMessage({ type: eventType, text: textTokens.join(' '), args, stackTraceLocations, previewString, logLevel, tag, }); __classPrivateFieldGet(this, _Page_onConsole, "f").call(this, message); };