* fix: style not applied to polyfillled shadow dom * test: add integration test for shadydom and @lwc/synthetic-shadow * improve the implementation of function isNativeShadowDom * apply lele0108's review suggestion
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
|||||||
isElement,
|
isElement,
|
||||||
isShadowRoot,
|
isShadowRoot,
|
||||||
maskInputValue,
|
maskInputValue,
|
||||||
|
isNativeShadowDom,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
let _id = 1;
|
let _id = 1;
|
||||||
@@ -248,7 +249,10 @@ export function transformAttribute(
|
|||||||
value: string,
|
value: string,
|
||||||
): string {
|
): string {
|
||||||
// relative path in attribute
|
// relative path in attribute
|
||||||
if (name === 'src' || (name === 'href' && value && !(tagName === 'use' && value[0] === '#'))) {
|
if (
|
||||||
|
name === 'src' ||
|
||||||
|
(name === 'href' && value && !(tagName === 'use' && value[0] === '#'))
|
||||||
|
) {
|
||||||
// href starts with a # is an id pointer for svg
|
// href starts with a # is an id pointer for svg
|
||||||
return absoluteToDoc(doc, value);
|
return absoluteToDoc(doc, value);
|
||||||
} else if (name === 'xlink:href' && value && value[0] !== '#') {
|
} else if (name === 'xlink:href' && value && value[0] !== '#') {
|
||||||
@@ -1025,7 +1029,9 @@ export function serializeNodeWithId(
|
|||||||
recordChild = recordChild && !serializedNode.needBlock;
|
recordChild = recordChild && !serializedNode.needBlock;
|
||||||
// this property was not needed in replay side
|
// this property was not needed in replay side
|
||||||
delete serializedNode.needBlock;
|
delete serializedNode.needBlock;
|
||||||
if ((n as HTMLElement).shadowRoot) serializedNode.isShadowHost = true;
|
const shadowRoot = (n as HTMLElement).shadowRoot;
|
||||||
|
if (shadowRoot && isNativeShadowDom(shadowRoot))
|
||||||
|
serializedNode.isShadowHost = true;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
(serializedNode.type === NodeType.Document ||
|
(serializedNode.type === NodeType.Document ||
|
||||||
@@ -1075,14 +1081,19 @@ export function serializeNodeWithId(
|
|||||||
for (const childN of Array.from(n.shadowRoot.childNodes)) {
|
for (const childN of Array.from(n.shadowRoot.childNodes)) {
|
||||||
const serializedChildNode = serializeNodeWithId(childN, bypassOptions);
|
const serializedChildNode = serializeNodeWithId(childN, bypassOptions);
|
||||||
if (serializedChildNode) {
|
if (serializedChildNode) {
|
||||||
serializedChildNode.isShadow = true;
|
isNativeShadowDom(n.shadowRoot) &&
|
||||||
|
(serializedChildNode.isShadow = true);
|
||||||
serializedNode.childNodes.push(serializedChildNode);
|
serializedNode.childNodes.push(serializedChildNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n.parentNode && isShadowRoot(n.parentNode)) {
|
if (
|
||||||
|
n.parentNode &&
|
||||||
|
isShadowRoot(n.parentNode) &&
|
||||||
|
isNativeShadowDom(n.parentNode)
|
||||||
|
) {
|
||||||
serializedNode.isShadow = true;
|
serializedNode.isShadow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,14 @@ export function isShadowRoot(n: Node): n is ShadowRoot {
|
|||||||
return Boolean(host?.shadowRoot === n);
|
return Boolean(host?.shadowRoot === n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To fix the issue https://github.com/rrweb-io/rrweb/issues/933.
|
||||||
|
* Some websites use polyfilled shadow dom and this function is used to detect this situation.
|
||||||
|
*/
|
||||||
|
export function isNativeShadowDom(shadowRoot: ShadowRoot) {
|
||||||
|
return Object.prototype.toString.call(shadowRoot) === '[object ShadowRoot]';
|
||||||
|
}
|
||||||
|
|
||||||
export class Mirror implements IMirror<Node> {
|
export class Mirror implements IMirror<Node> {
|
||||||
private idNodeMap: idNodeMap = new Map();
|
private idNodeMap: idNodeMap = new Map();
|
||||||
private nodeMetaMap: nodeMetaMap = new WeakMap();
|
private nodeMetaMap: nodeMetaMap = new WeakMap();
|
||||||
|
|||||||
1
packages/rrweb-snapshot/typings/utils.d.ts
vendored
1
packages/rrweb-snapshot/typings/utils.d.ts
vendored
@@ -1,6 +1,7 @@
|
|||||||
import { MaskInputFn, MaskInputOptions, IMirror, serializedNodeWithId } from './types';
|
import { MaskInputFn, MaskInputOptions, IMirror, serializedNodeWithId } from './types';
|
||||||
export declare function isElement(n: Node): n is Element;
|
export declare function isElement(n: Node): n is Element;
|
||||||
export declare function isShadowRoot(n: Node): n is ShadowRoot;
|
export declare function isShadowRoot(n: Node): n is ShadowRoot;
|
||||||
|
export declare function isNativeShadowDom(shadowRoot: ShadowRoot): boolean;
|
||||||
export declare class Mirror implements IMirror<Node> {
|
export declare class Mirror implements IMirror<Node> {
|
||||||
private idNodeMap;
|
private idNodeMap;
|
||||||
private nodeMetaMap;
|
private nodeMetaMap;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
needMaskingText,
|
needMaskingText,
|
||||||
maskInputValue,
|
maskInputValue,
|
||||||
Mirror,
|
Mirror,
|
||||||
|
isNativeShadowDom,
|
||||||
} from 'rrweb-snapshot';
|
} from 'rrweb-snapshot';
|
||||||
import type {
|
import type {
|
||||||
mutationRecord,
|
mutationRecord,
|
||||||
@@ -581,7 +582,10 @@ export default class MutationBuffer {
|
|||||||
this.removes.push({
|
this.removes.push({
|
||||||
parentId,
|
parentId,
|
||||||
id: nodeId,
|
id: nodeId,
|
||||||
isShadow: isShadowRoot(m.target) ? true : undefined,
|
isShadow:
|
||||||
|
isShadowRoot(m.target) && isNativeShadowDom(m.target)
|
||||||
|
? true
|
||||||
|
: undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.mapRemoves.push(n);
|
this.mapRemoves.push(n);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import type {
|
|||||||
import { initMutationObserver, initScrollObserver } from './observer';
|
import { initMutationObserver, initScrollObserver } from './observer';
|
||||||
import { patch } from '../utils';
|
import { patch } from '../utils';
|
||||||
import type { Mirror } from 'rrweb-snapshot';
|
import type { Mirror } from 'rrweb-snapshot';
|
||||||
|
import { isNativeShadowDom } from 'rrweb-snapshot';
|
||||||
|
|
||||||
type BypassOptions = Omit<
|
type BypassOptions = Omit<
|
||||||
MutationBufferParam,
|
MutationBufferParam,
|
||||||
@@ -53,6 +54,7 @@ export class ShadowDomManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public addShadowRoot(shadowRoot: ShadowRoot, doc: Document) {
|
public addShadowRoot(shadowRoot: ShadowRoot, doc: Document) {
|
||||||
|
if (!isNativeShadowDom(shadowRoot)) return;
|
||||||
initMutationObserver(
|
initMutationObserver(
|
||||||
{
|
{
|
||||||
...this.bypassOptions,
|
...this.bypassOptions,
|
||||||
|
|||||||
@@ -10764,6 +10764,537 @@ exports[`record integration tests should record shadow DOM 1`] = `
|
|||||||
]"
|
]"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`record integration tests should record shadow doms polyfilled by shadydom 1`] = `
|
||||||
|
"[
|
||||||
|
{
|
||||||
|
\\"type\\": 0,
|
||||||
|
\\"data\\": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 1,
|
||||||
|
\\"data\\": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 4,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"href\\": \\"about:blank\\",
|
||||||
|
\\"width\\": 1920,
|
||||||
|
\\"height\\": 1080
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"node\\": {
|
||||||
|
\\"type\\": 0,
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 1,
|
||||||
|
\\"name\\": \\"html\\",
|
||||||
|
\\"publicId\\": \\"\\",
|
||||||
|
\\"systemId\\": \\"\\",
|
||||||
|
\\"id\\": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"html\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"lang\\": \\"en\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"head\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"script\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||||
|
\\"id\\": 7
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"script\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"src\\": \\"https://cdn.jsdelivr.net/npm/@webcomponents/shadydom@1.9.0/shadydom.min.js\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\\\n \\",
|
||||||
|
\\"id\\": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"meta\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"charset\\": \\"UTF-8\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 11
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 12
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"body\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"id\\": \\"target1\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 17
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 18
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"id\\": \\"target2\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"p\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 20
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 19
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 21
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"id\\": \\"target3\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 22
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 23
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"script\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||||
|
\\"id\\": 25
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\\\n \\",
|
||||||
|
\\"id\\": 26
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"script\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||||
|
\\"id\\": 28
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 27
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\\\n \\\\n\\\\n\\",
|
||||||
|
\\"id\\": 29
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 14
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 1
|
||||||
|
},
|
||||||
|
\\"initialOffset\\": {
|
||||||
|
\\"left\\": 0,
|
||||||
|
\\"top\\": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"source\\": 0,
|
||||||
|
\\"texts\\": [],
|
||||||
|
\\"attributes\\": [],
|
||||||
|
\\"removes\\": [],
|
||||||
|
\\"adds\\": [
|
||||||
|
{
|
||||||
|
\\"parentId\\": 22,
|
||||||
|
\\"nextId\\": null,
|
||||||
|
\\"node\\": {
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"span\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 30
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`record integration tests should record shadow doms polyfilled by synthetic-shadow 1`] = `
|
||||||
|
"[
|
||||||
|
{
|
||||||
|
\\"type\\": 0,
|
||||||
|
\\"data\\": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 1,
|
||||||
|
\\"data\\": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 4,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"href\\": \\"about:blank\\",
|
||||||
|
\\"width\\": 1920,
|
||||||
|
\\"height\\": 1080
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"node\\": {
|
||||||
|
\\"type\\": 0,
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 1,
|
||||||
|
\\"name\\": \\"html\\",
|
||||||
|
\\"publicId\\": \\"\\",
|
||||||
|
\\"systemId\\": \\"\\",
|
||||||
|
\\"id\\": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"html\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"lang\\": \\"en\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"head\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"script\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||||
|
\\"id\\": 7
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"script\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"src\\": \\"https://cdn.jsdelivr.net/npm/@lwc/synthetic-shadow@2.20.3/dist/synthetic-shadow.js\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\\\n \\",
|
||||||
|
\\"id\\": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"meta\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"charset\\": \\"UTF-8\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 11
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 12
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"body\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"id\\": \\"target1\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 17,
|
||||||
|
\\"isShadow\\": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 16,
|
||||||
|
\\"isShadowHost\\": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 18
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"id\\": \\"target2\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"p\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 20
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 19
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 21
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"id\\": \\"target3\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 22
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 23
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"script\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||||
|
\\"id\\": 25
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\\\n \\",
|
||||||
|
\\"id\\": 26
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"script\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||||
|
\\"id\\": 28
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 27
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\\\n \\\\n\\\\n\\",
|
||||||
|
\\"id\\": 29
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 14
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 1
|
||||||
|
},
|
||||||
|
\\"initialOffset\\": {
|
||||||
|
\\"left\\": 0,
|
||||||
|
\\"top\\": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"source\\": 0,
|
||||||
|
\\"texts\\": [],
|
||||||
|
\\"attributes\\": [],
|
||||||
|
\\"removes\\": [],
|
||||||
|
\\"adds\\": [
|
||||||
|
{
|
||||||
|
\\"parentId\\": 22,
|
||||||
|
\\"nextId\\": null,
|
||||||
|
\\"node\\": {
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"span\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 30
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"parentId\\": 14,
|
||||||
|
\\"nextId\\": null,
|
||||||
|
\\"node\\": {
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"id\\": \\"target4\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 31,
|
||||||
|
\\"isShadowHost\\": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"source\\": 0,
|
||||||
|
\\"texts\\": [],
|
||||||
|
\\"attributes\\": [],
|
||||||
|
\\"removes\\": [],
|
||||||
|
\\"adds\\": [
|
||||||
|
{
|
||||||
|
\\"parentId\\": 31,
|
||||||
|
\\"nextId\\": null,
|
||||||
|
\\"node\\": {
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"ul\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 32,
|
||||||
|
\\"isShadow\\": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`record integration tests should record webgl canvas mutations 1`] = `
|
exports[`record integration tests should record webgl canvas mutations 1`] = `
|
||||||
"[
|
"[
|
||||||
{
|
{
|
||||||
|
|||||||
24
packages/rrweb/test/html/polyfilled-shadowdom-mutation.html
Normal file
24
packages/rrweb/test/html/polyfilled-shadowdom-mutation.html
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="target1"></div>
|
||||||
|
<div id="target2"></div>
|
||||||
|
<div id="target3"></div>
|
||||||
|
<script>
|
||||||
|
const target1 = document.querySelector('#target1');
|
||||||
|
target1.attachShadow({
|
||||||
|
mode: 'open',
|
||||||
|
});
|
||||||
|
target1.shadowRoot.appendChild(document.createElement('div'));
|
||||||
|
const target2 = document.querySelector('#target2');
|
||||||
|
target2.attachShadow({
|
||||||
|
mode: 'open',
|
||||||
|
'$$lwc-synthetic-mode': true,
|
||||||
|
});
|
||||||
|
target2.shadowRoot.appendChild(document.createElement('p'));
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -589,6 +589,78 @@ describe('record integration tests', function (this: ISuite) {
|
|||||||
assertSnapshot(snapshots);
|
assertSnapshot(snapshots);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// https://github.com/webcomponents/polyfills/tree/master/packages/shadydom
|
||||||
|
it('should record shadow doms polyfilled by shadydom', async () => {
|
||||||
|
const page: puppeteer.Page = await browser.newPage();
|
||||||
|
await page.goto('about:blank');
|
||||||
|
await page.setContent(
|
||||||
|
// insert shadydom script
|
||||||
|
replaceLast(
|
||||||
|
getHtml.call(this, 'polyfilled-shadowdom-mutation.html'),
|
||||||
|
'<head>',
|
||||||
|
`
|
||||||
|
<head>
|
||||||
|
<script>
|
||||||
|
// To force ShadyDOM to be used even when native ShadowDOM is available, set the ShadyDOM = {force: true} in a script prior to loading the polyfill.
|
||||||
|
window.ShadyDOM = { force: true };
|
||||||
|
</script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/shadydom@1.9.0/shadydom.min.js"></script>
|
||||||
|
`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await page.evaluate(() => {
|
||||||
|
const target3 = document.querySelector('#target3');
|
||||||
|
target3?.attachShadow({
|
||||||
|
mode: 'open',
|
||||||
|
});
|
||||||
|
target3?.shadowRoot?.appendChild(document.createElement('span'));
|
||||||
|
});
|
||||||
|
await waitForRAF(page); // wait till browser sent snapshots
|
||||||
|
|
||||||
|
const snapshots = await page.evaluate('window.snapshots');
|
||||||
|
assertSnapshot(snapshots);
|
||||||
|
});
|
||||||
|
|
||||||
|
// https://github.com/salesforce/lwc/tree/master/packages/%40lwc/synthetic-shadow
|
||||||
|
it('should record shadow doms polyfilled by synthetic-shadow', async () => {
|
||||||
|
const page: puppeteer.Page = await browser.newPage();
|
||||||
|
await page.goto('about:blank');
|
||||||
|
await page.setContent(
|
||||||
|
// insert lwc's synthetic-shadow script
|
||||||
|
replaceLast(
|
||||||
|
getHtml.call(this, 'polyfilled-shadowdom-mutation.html'),
|
||||||
|
'<head>',
|
||||||
|
`
|
||||||
|
<head>
|
||||||
|
<script>var process = {env: {NODE_ENV: "production"}};</script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/@lwc/synthetic-shadow@2.20.3/dist/synthetic-shadow.js"></script>
|
||||||
|
`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await page.evaluate(() => {
|
||||||
|
const target3 = document.querySelector('#target3');
|
||||||
|
// create a shadow dom with synthetic shadow
|
||||||
|
// https://github.com/salesforce/lwc/blob/v2.20.3/packages/@lwc/synthetic-shadow/src/faux-shadow/element.ts#L81-L87
|
||||||
|
target3?.attachShadow({
|
||||||
|
mode: 'open',
|
||||||
|
'$$lwc-synthetic-mode': true,
|
||||||
|
} as ShadowRootInit);
|
||||||
|
target3?.shadowRoot?.appendChild(document.createElement('span'));
|
||||||
|
const target4 = document.createElement('div');
|
||||||
|
target4.id = 'target4';
|
||||||
|
// create a native shadow dom
|
||||||
|
document.body.appendChild(target4);
|
||||||
|
target4.attachShadow({
|
||||||
|
mode: 'open',
|
||||||
|
});
|
||||||
|
target4.shadowRoot?.appendChild(document.createElement('ul'));
|
||||||
|
});
|
||||||
|
await waitForRAF(page); // wait till browser sent snapshots
|
||||||
|
|
||||||
|
const snapshots = await page.evaluate('window.snapshots');
|
||||||
|
assertSnapshot(snapshots);
|
||||||
|
});
|
||||||
|
|
||||||
it('should mask texts', async () => {
|
it('should mask texts', async () => {
|
||||||
const page: puppeteer.Page = await browser.newPage();
|
const page: puppeteer.Page = await browser.newPage();
|
||||||
await page.goto('about:blank');
|
await page.goto('about:blank');
|
||||||
|
|||||||
Reference in New Issue
Block a user