fix(frontend/player): PostponedStyleSheet callbacks & logs in tracker & accept virtual svg-style in tracker

This commit is contained in:
Alex Kaminskii 2022-09-16 18:33:29 +02:00
parent cc6e0715d8
commit 2a926d038d
3 changed files with 63 additions and 12 deletions

View file

@ -5,7 +5,15 @@ import type { Message, SetNodeScroll, CreateElementNode } from '../../messages';
import ListWalker from '../ListWalker';
import StylesManager, { rewriteNodeStyleSheet } from './StylesManager';
import { VElement, VText, VShadowRoot, VDocument, VNode, VStyleElement } from './VirtualDOM';
import {
VElement,
VText,
VShadowRoot,
VDocument,
VNode,
VStyleElement,
PostponedStyleSheet,
} from './VirtualDOM';
import type { StyleElement } from './VirtualDOM';
@ -24,20 +32,21 @@ const ATTR_NAME_REGEXP = /([^\t\n\f \/>"'=]+)/; // regexp costs ~
// .replace(/\-webkit\-/g, "")
// }
function insertRule(sheet: CSSStyleSheet, msg: { rule: string, index: number }) {
function insertRule(sheet: CSSStyleSheet | PostponedStyleSheet, msg: { rule: string, index: number }) {
try {
sheet.insertRule(msg.rule, msg.index)
} catch (e) {
logger.warn(e, msg)
try {
sheet.insertRule(msg.rule)
sheet.insertRule(msg.rule, 0)
logger.warn("Inserting rule into 0-index", e, msg)
} catch (e) {
logger.warn("Cannot insert rule.", e, msg)
}
}
}
function deleteRule(sheet: CSSStyleSheet, msg: { index: number }) {
function deleteRule(sheet: CSSStyleSheet | PostponedStyleSheet, msg: { index: number }) {
try {
sheet.deleteRule(msg.index)
} catch (e) {
@ -51,6 +60,7 @@ export default class DOMManager extends ListWalker<Message> {
private vRoots: Map<number, VShadowRoot | VDocument> = new Map()
private activeIframeRoots: Map<number, number> = new Map()
private styleSheets: Map<number, CSSStyleSheet> = new Map()
private ppStyleSheets: Map<number, PostponedStyleSheet> = new Map()
private upperBodyId: number = -1;
@ -141,7 +151,7 @@ export default class DOMManager extends ListWalker<Message> {
let node: Node | undefined
let vn: VNode | undefined
let doc: Document | null
let styleSheet: CSSStyleSheet | undefined
let styleSheet: CSSStyleSheet | PostponedStyleSheet | undefined
switch (msg.tp) {
case "create_document":
doc = this.screen.document;
@ -321,7 +331,7 @@ export default class DOMManager extends ListWalker<Message> {
}
return
case "adopted_ss_insert_rule":
styleSheet = this.styleSheets.get(msg.sheetID)
styleSheet = this.styleSheets.get(msg.sheetID) || this.ppStyleSheets.get(msg.sheetID)
if (!styleSheet) {
logger.warn("No stylesheet was created for ", msg)
return
@ -329,7 +339,7 @@ export default class DOMManager extends ListWalker<Message> {
insertRule(styleSheet, msg)
return
case "adopted_ss_delete_rule":
styleSheet = this.styleSheets.get(msg.sheetID)
styleSheet = this.styleSheets.get(msg.sheetID) || this.ppStyleSheets.get(msg.sheetID)
if (!styleSheet) {
logger.warn("No stylesheet was created for ", msg)
return
@ -353,7 +363,7 @@ export default class DOMManager extends ListWalker<Message> {
vn = this.vElements.get(msg.id)
if (!vn) { logger.error("Node not found", msg); return }
if (!(vn instanceof VStyleElement)) { logger.error("Non-style owner", msg); return }
this.styleSheets.set(msg.sheetID, vn.node.sheet)
this.ppStyleSheets.set(msg.sheetID, new PostponedStyleSheet(vn.node))
return
}
styleSheet = this.styleSheets.get(msg.sheetID)

View file

@ -119,6 +119,8 @@ export class VElement extends VParent {
type StyleSheetCallback = (s: CSSStyleSheet) => void
export type StyleElement = HTMLStyleElement | SVGStyleElement
// @Depricated TODO: remove in favor of PostponedStyleSheet
export class VStyleElement extends VElement {
private loaded = false
private stylesheetCallbacks: StyleSheetCallback[] = []
@ -149,6 +151,45 @@ export class VStyleElement extends VElement {
}
}
export class PostponedStyleSheet {
private loaded = false
private stylesheetCallbacks: StyleSheetCallback[] = []
constructor(private readonly node: StyleElement) {
node.onload = () => {
const sheet = node.sheet
if (sheet) {
this.stylesheetCallbacks.forEach(cb => cb(sheet))
this.stylesheetCallbacks = []
} else {
console.warn("Style node onload: sheet is null")
}
this.loaded = true
}
}
private applyCallback(cb: StyleSheetCallback) {
if (this.loaded) {
if (!this.node.sheet) {
console.warn("Style tag is loaded, but sheet is null")
return
}
cb(this.node.sheet)
} else {
this.stylesheetCallbacks.push(cb)
}
}
insertRule(rule: string, index: number) {
this.applyCallback(s => s.insertRule(rule, index))
}
deleteRule(index: number) {
this.applyCallback(s => s.deleteRule(index))
}
}
export class VText {
parentNode: VParent | null = null
constructor(public readonly node: Text = new Text()) {}

View file

@ -20,8 +20,7 @@ export default function (app: App | null) {
const sendInserDeleteRule = app.safe((sheet: CSSStyleSheet, index: number, rule?: string) => {
const sheetID = styleSheetIDMap.get(sheet)
if (!sheetID) {
app.debug.log('StyleSheet not registered ', sheet, sheet.ownerNode)
// Sheet haven't been registered yet. Rules will be sent on registration.
// OK-case. Sheet haven't been registered yet. Rules will be sent on registration.
return
}
if (typeof rule === 'string') {
@ -53,6 +52,8 @@ export default function (app: App | null) {
if (idx >= 0) {
app.send(AdoptedSSInsertRuleURLBased(sheetID, cssText, idx, app.getBaseHref()))
app.send(AdoptedSSDeleteRule(sheetID, idx + 1)) // Remove previous clone
} else {
app.debug.warn('Rule index not found in', sheet, topmostRule)
}
})
@ -86,7 +87,7 @@ export default function (app: App | null) {
app.observer.attachContextCallback(patchContext)
app.nodes.attachNodeCallback((node: Node): void => {
if (!hasTag(node, 'STYLE') || !node.sheet) {
if (!(hasTag(node, 'STYLE') || hasTag(node, 'style')) || !node.sheet) {
return
}
if (node.textContent !== null && node.textContent.trim().length > 0) {
@ -101,7 +102,6 @@ export default function (app: App | null) {
const sheetID = nextID()
styleSheetIDMap.set(sheet, sheetID)
app.send(AdoptedSSAddOwner(sheetID, nodeID))
app.debug.log('StyleSheet registered ', sheet, node)
const rules = sheet.cssRules
for (let i = 0; i < rules.length; i++) {