Dev aleksk (#795)

*feat(tracker;backend;frontend/player): focus in elem
*feat(tracker;frontend/player): FontFace load
This commit is contained in:
Alex K 2022-11-04 11:33:29 +01:00 committed by GitHub
parent d8774122b7
commit 822ca53980
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 3070 additions and 2713 deletions

View file

@ -10,5 +10,5 @@ func IsIOSType(id int) bool {
}
func IsDOMType(id int) bool {
return 0 == id || 4 == id || 5 == id || 6 == id || 7 == id || 8 == id || 9 == id || 10 == id || 11 == id || 12 == id || 13 == id || 14 == id || 15 == id || 16 == id || 18 == id || 19 == id || 20 == id || 37 == id || 38 == id || 49 == id || 54 == id || 55 == id || 59 == id || 60 == id || 61 == id || 67 == id || 69 == id || 70 == id || 71 == id || 72 == id || 73 == id || 74 == id || 75 == id || 76 == id || 77 == id || 90 == id || 93 == id || 96 == id || 100 == id || 102 == id || 103 == id || 105 == id
return 0 == id || 4 == id || 5 == id || 6 == id || 7 == id || 8 == id || 9 == id || 10 == id || 11 == id || 12 == id || 13 == id || 14 == id || 15 == id || 16 == id || 18 == id || 19 == id || 20 == id || 37 == id || 38 == id || 49 == id || 54 == id || 55 == id || 57 == id || 58 == id || 59 == id || 60 == id || 61 == id || 67 == id || 69 == id || 70 == id || 71 == id || 72 == id || 73 == id || 74 == id || 75 == id || 76 == id || 77 == id || 90 == id || 93 == id || 96 == id || 100 == id || 102 == id || 103 == id || 105 == id
}

View file

@ -4,7 +4,6 @@ package messages
import "encoding/binary"
const (
MsgBatchMeta = 80
MsgBatchMetadata = 81
@ -119,6 +118,10 @@ const (
MsgPerformanceTrackAggr = 56
MsgLoadFontFace = 57
MsgSetNodeFocus = 58
MsgLongTask = 59
MsgSetNodeAttributeURLBased = 60
@ -198,10 +201,8 @@ const (
MsgIOSPerformanceAggregated = 110
MsgIOSIssueEvent = 111
)
type BatchMeta struct {
message
PageNo uint64
@ -544,7 +545,6 @@ func (msg *SetViewportScroll) TypeID() int {
type CreateDocument struct {
message
}
func (msg *CreateDocument) Encode() []byte {
@ -2352,6 +2352,76 @@ func (msg *PerformanceTrackAggr) TypeID() int {
return 56
}
type LoadFontFace struct {
message
ParentID uint64
Family string
Source string
Descriptors string
}
func (msg *LoadFontFace) Encode() []byte {
buf := make([]byte, 41+len(msg.Family)+len(msg.Source)+len(msg.Descriptors))
buf[0] = 57
p := 1
p = WriteUint(msg.ParentID, buf, p)
p = WriteString(msg.Family, buf, p)
p = WriteString(msg.Source, buf, p)
p = WriteString(msg.Descriptors, buf, p)
return buf[:p]
}
func (msg *LoadFontFace) EncodeWithIndex() []byte {
encoded := msg.Encode()
if IsIOSType(msg.TypeID()) {
return encoded
}
data := make([]byte, len(encoded)+8)
copy(data[8:], encoded[:])
binary.LittleEndian.PutUint64(data[0:], msg.Meta().Index)
return data
}
func (msg *LoadFontFace) Decode() Message {
return msg
}
func (msg *LoadFontFace) TypeID() int {
return 57
}
type SetNodeFocus struct {
message
ID int64
}
func (msg *SetNodeFocus) Encode() []byte {
buf := make([]byte, 11)
buf[0] = 58
p := 1
p = WriteInt(msg.ID, buf, p)
return buf[:p]
}
func (msg *SetNodeFocus) EncodeWithIndex() []byte {
encoded := msg.Encode()
if IsIOSType(msg.TypeID()) {
return encoded
}
data := make([]byte, len(encoded)+8)
copy(data[8:], encoded[:])
binary.LittleEndian.PutUint64(data[0:], msg.Meta().Index)
return data
}
func (msg *SetNodeFocus) Decode() Message {
return msg
}
func (msg *SetNodeFocus) TypeID() int {
return 58
}
type LongTask struct {
message
Timestamp uint64
@ -3869,4 +3939,3 @@ func (msg *IOSIssueEvent) Decode() Message {
func (msg *IOSIssueEvent) TypeID() int {
return 111
}

View file

@ -6,7 +6,6 @@ import (
"io"
)
func DecodeBatchMeta(reader io.Reader) (Message, error) {
var err error = nil
msg := &BatchMeta{}
@ -22,7 +21,6 @@ func DecodeBatchMeta(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeBatchMetadata(reader io.Reader) (Message, error) {
var err error = nil
msg := &BatchMetadata{}
@ -44,7 +42,6 @@ func DecodeBatchMetadata(reader io.Reader) (Message, error) {
return msg, err
}
func DecodePartitionedMessage(reader io.Reader) (Message, error) {
var err error = nil
msg := &PartitionedMessage{}
@ -57,7 +54,6 @@ func DecodePartitionedMessage(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeTimestamp(reader io.Reader) (Message, error) {
var err error = nil
msg := &Timestamp{}
@ -67,7 +63,6 @@ func DecodeTimestamp(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSessionStart(reader io.Reader) (Message, error) {
var err error = nil
msg := &SessionStart{}
@ -122,7 +117,6 @@ func DecodeSessionStart(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSessionEndDeprecated(reader io.Reader) (Message, error) {
var err error = nil
msg := &SessionEndDeprecated{}
@ -132,7 +126,6 @@ func DecodeSessionEndDeprecated(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetPageLocation(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetPageLocation{}
@ -148,7 +141,6 @@ func DecodeSetPageLocation(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetViewportSize(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetViewportSize{}
@ -161,7 +153,6 @@ func DecodeSetViewportSize(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetViewportScroll(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetViewportScroll{}
@ -174,7 +165,6 @@ func DecodeSetViewportScroll(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeCreateDocument(reader io.Reader) (Message, error) {
var err error = nil
msg := &CreateDocument{}
@ -182,7 +172,6 @@ func DecodeCreateDocument(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeCreateElementNode(reader io.Reader) (Message, error) {
var err error = nil
msg := &CreateElementNode{}
@ -204,7 +193,6 @@ func DecodeCreateElementNode(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeCreateTextNode(reader io.Reader) (Message, error) {
var err error = nil
msg := &CreateTextNode{}
@ -220,7 +208,6 @@ func DecodeCreateTextNode(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeMoveNode(reader io.Reader) (Message, error) {
var err error = nil
msg := &MoveNode{}
@ -236,7 +223,6 @@ func DecodeMoveNode(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeRemoveNode(reader io.Reader) (Message, error) {
var err error = nil
msg := &RemoveNode{}
@ -246,7 +232,6 @@ func DecodeRemoveNode(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetNodeAttribute(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetNodeAttribute{}
@ -262,7 +247,6 @@ func DecodeSetNodeAttribute(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeRemoveNodeAttribute(reader io.Reader) (Message, error) {
var err error = nil
msg := &RemoveNodeAttribute{}
@ -275,7 +259,6 @@ func DecodeRemoveNodeAttribute(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetNodeData(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetNodeData{}
@ -288,7 +271,6 @@ func DecodeSetNodeData(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetCSSData(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetCSSData{}
@ -301,7 +283,6 @@ func DecodeSetCSSData(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetNodeScroll(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetNodeScroll{}
@ -317,7 +298,6 @@ func DecodeSetNodeScroll(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetInputTarget(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetInputTarget{}
@ -330,7 +310,6 @@ func DecodeSetInputTarget(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetInputValue(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetInputValue{}
@ -346,7 +325,6 @@ func DecodeSetInputValue(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetInputChecked(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetInputChecked{}
@ -359,7 +337,6 @@ func DecodeSetInputChecked(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeMouseMove(reader io.Reader) (Message, error) {
var err error = nil
msg := &MouseMove{}
@ -372,7 +349,6 @@ func DecodeMouseMove(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeConsoleLog(reader io.Reader) (Message, error) {
var err error = nil
msg := &ConsoleLog{}
@ -385,7 +361,6 @@ func DecodeConsoleLog(reader io.Reader) (Message, error) {
return msg, err
}
func DecodePageLoadTiming(reader io.Reader) (Message, error) {
var err error = nil
msg := &PageLoadTiming{}
@ -419,7 +394,6 @@ func DecodePageLoadTiming(reader io.Reader) (Message, error) {
return msg, err
}
func DecodePageRenderTiming(reader io.Reader) (Message, error) {
var err error = nil
msg := &PageRenderTiming{}
@ -435,7 +409,6 @@ func DecodePageRenderTiming(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeJSExceptionDeprecated(reader io.Reader) (Message, error) {
var err error = nil
msg := &JSExceptionDeprecated{}
@ -451,7 +424,6 @@ func DecodeJSExceptionDeprecated(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIntegrationEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &IntegrationEvent{}
@ -473,7 +445,6 @@ func DecodeIntegrationEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeRawCustomEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &RawCustomEvent{}
@ -486,7 +457,6 @@ func DecodeRawCustomEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeUserID(reader io.Reader) (Message, error) {
var err error = nil
msg := &UserID{}
@ -496,7 +466,6 @@ func DecodeUserID(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeUserAnonymousID(reader io.Reader) (Message, error) {
var err error = nil
msg := &UserAnonymousID{}
@ -506,7 +475,6 @@ func DecodeUserAnonymousID(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeMetadata(reader io.Reader) (Message, error) {
var err error = nil
msg := &Metadata{}
@ -519,7 +487,6 @@ func DecodeMetadata(reader io.Reader) (Message, error) {
return msg, err
}
func DecodePageEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &PageEvent{}
@ -577,7 +544,6 @@ func DecodePageEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeInputEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &InputEvent{}
@ -599,7 +565,6 @@ func DecodeInputEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeClickEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &ClickEvent{}
@ -621,7 +586,6 @@ func DecodeClickEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeResourceEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &ResourceEvent{}
@ -664,7 +628,6 @@ func DecodeResourceEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeCustomEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &CustomEvent{}
@ -683,7 +646,6 @@ func DecodeCustomEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeCSSInsertRule(reader io.Reader) (Message, error) {
var err error = nil
msg := &CSSInsertRule{}
@ -699,7 +661,6 @@ func DecodeCSSInsertRule(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeCSSDeleteRule(reader io.Reader) (Message, error) {
var err error = nil
msg := &CSSDeleteRule{}
@ -712,7 +673,6 @@ func DecodeCSSDeleteRule(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeFetch(reader io.Reader) (Message, error) {
var err error = nil
msg := &Fetch{}
@ -740,7 +700,6 @@ func DecodeFetch(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeProfiler(reader io.Reader) (Message, error) {
var err error = nil
msg := &Profiler{}
@ -759,7 +718,6 @@ func DecodeProfiler(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeOTable(reader io.Reader) (Message, error) {
var err error = nil
msg := &OTable{}
@ -772,7 +730,6 @@ func DecodeOTable(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeStateAction(reader io.Reader) (Message, error) {
var err error = nil
msg := &StateAction{}
@ -782,7 +739,6 @@ func DecodeStateAction(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeStateActionEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &StateActionEvent{}
@ -798,7 +754,6 @@ func DecodeStateActionEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeRedux(reader io.Reader) (Message, error) {
var err error = nil
msg := &Redux{}
@ -814,7 +769,6 @@ func DecodeRedux(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeVuex(reader io.Reader) (Message, error) {
var err error = nil
msg := &Vuex{}
@ -827,7 +781,6 @@ func DecodeVuex(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeMobX(reader io.Reader) (Message, error) {
var err error = nil
msg := &MobX{}
@ -840,7 +793,6 @@ func DecodeMobX(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeNgRx(reader io.Reader) (Message, error) {
var err error = nil
msg := &NgRx{}
@ -856,7 +808,6 @@ func DecodeNgRx(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeGraphQL(reader io.Reader) (Message, error) {
var err error = nil
msg := &GraphQL{}
@ -875,7 +826,6 @@ func DecodeGraphQL(reader io.Reader) (Message, error) {
return msg, err
}
func DecodePerformanceTrack(reader io.Reader) (Message, error) {
var err error = nil
msg := &PerformanceTrack{}
@ -894,7 +844,6 @@ func DecodePerformanceTrack(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeGraphQLEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &GraphQLEvent{}
@ -919,7 +868,6 @@ func DecodeGraphQLEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeFetchEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &FetchEvent{}
@ -950,7 +898,6 @@ func DecodeFetchEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeDOMDrop(reader io.Reader) (Message, error) {
var err error = nil
msg := &DOMDrop{}
@ -960,7 +907,6 @@ func DecodeDOMDrop(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeResourceTiming(reader io.Reader) (Message, error) {
var err error = nil
msg := &ResourceTiming{}
@ -991,7 +937,6 @@ func DecodeResourceTiming(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeConnectionInformation(reader io.Reader) (Message, error) {
var err error = nil
msg := &ConnectionInformation{}
@ -1004,7 +949,6 @@ func DecodeConnectionInformation(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetPageVisibility(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetPageVisibility{}
@ -1014,7 +958,6 @@ func DecodeSetPageVisibility(reader io.Reader) (Message, error) {
return msg, err
}
func DecodePerformanceTrackAggr(reader io.Reader) (Message, error) {
var err error = nil
msg := &PerformanceTrackAggr{}
@ -1063,6 +1006,32 @@ func DecodePerformanceTrackAggr(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeLoadFontFace(reader io.Reader) (Message, error) {
var err error = nil
msg := &LoadFontFace{}
if msg.ParentID, err = ReadUint(reader); err != nil {
return nil, err
}
if msg.Family, err = ReadString(reader); err != nil {
return nil, err
}
if msg.Source, err = ReadString(reader); err != nil {
return nil, err
}
if msg.Descriptors, err = ReadString(reader); err != nil {
return nil, err
}
return msg, err
}
func DecodeSetNodeFocus(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetNodeFocus{}
if msg.ID, err = ReadInt(reader); err != nil {
return nil, err
}
return msg, err
}
func DecodeLongTask(reader io.Reader) (Message, error) {
var err error = nil
@ -1091,7 +1060,6 @@ func DecodeLongTask(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetNodeAttributeURLBased(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetNodeAttributeURLBased{}
@ -1110,7 +1078,6 @@ func DecodeSetNodeAttributeURLBased(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSetCSSDataURLBased(reader io.Reader) (Message, error) {
var err error = nil
msg := &SetCSSDataURLBased{}
@ -1126,7 +1093,6 @@ func DecodeSetCSSDataURLBased(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIssueEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &IssueEvent{}
@ -1151,7 +1117,6 @@ func DecodeIssueEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeTechnicalInfo(reader io.Reader) (Message, error) {
var err error = nil
msg := &TechnicalInfo{}
@ -1164,7 +1129,6 @@ func DecodeTechnicalInfo(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeCustomIssue(reader io.Reader) (Message, error) {
var err error = nil
msg := &CustomIssue{}
@ -1177,7 +1141,6 @@ func DecodeCustomIssue(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeAssetCache(reader io.Reader) (Message, error) {
var err error = nil
msg := &AssetCache{}
@ -1187,7 +1150,6 @@ func DecodeAssetCache(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeCSSInsertRuleURLBased(reader io.Reader) (Message, error) {
var err error = nil
msg := &CSSInsertRuleURLBased{}
@ -1206,7 +1168,6 @@ func DecodeCSSInsertRuleURLBased(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeMouseClick(reader io.Reader) (Message, error) {
var err error = nil
msg := &MouseClick{}
@ -1225,7 +1186,6 @@ func DecodeMouseClick(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeCreateIFrameDocument(reader io.Reader) (Message, error) {
var err error = nil
msg := &CreateIFrameDocument{}
@ -1238,7 +1198,6 @@ func DecodeCreateIFrameDocument(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeAdoptedSSReplaceURLBased(reader io.Reader) (Message, error) {
var err error = nil
msg := &AdoptedSSReplaceURLBased{}
@ -1254,7 +1213,6 @@ func DecodeAdoptedSSReplaceURLBased(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeAdoptedSSReplace(reader io.Reader) (Message, error) {
var err error = nil
msg := &AdoptedSSReplace{}
@ -1267,7 +1225,6 @@ func DecodeAdoptedSSReplace(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeAdoptedSSInsertRuleURLBased(reader io.Reader) (Message, error) {
var err error = nil
msg := &AdoptedSSInsertRuleURLBased{}
@ -1286,7 +1243,6 @@ func DecodeAdoptedSSInsertRuleURLBased(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeAdoptedSSInsertRule(reader io.Reader) (Message, error) {
var err error = nil
msg := &AdoptedSSInsertRule{}
@ -1302,7 +1258,6 @@ func DecodeAdoptedSSInsertRule(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeAdoptedSSDeleteRule(reader io.Reader) (Message, error) {
var err error = nil
msg := &AdoptedSSDeleteRule{}
@ -1315,7 +1270,6 @@ func DecodeAdoptedSSDeleteRule(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeAdoptedSSAddOwner(reader io.Reader) (Message, error) {
var err error = nil
msg := &AdoptedSSAddOwner{}
@ -1328,7 +1282,6 @@ func DecodeAdoptedSSAddOwner(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeAdoptedSSRemoveOwner(reader io.Reader) (Message, error) {
var err error = nil
msg := &AdoptedSSRemoveOwner{}
@ -1341,7 +1294,6 @@ func DecodeAdoptedSSRemoveOwner(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeZustand(reader io.Reader) (Message, error) {
var err error = nil
msg := &Zustand{}
@ -1354,7 +1306,6 @@ func DecodeZustand(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeJSException(reader io.Reader) (Message, error) {
var err error = nil
msg := &JSException{}
@ -1373,7 +1324,6 @@ func DecodeJSException(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSessionEnd(reader io.Reader) (Message, error) {
var err error = nil
msg := &SessionEnd{}
@ -1386,7 +1336,6 @@ func DecodeSessionEnd(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeSessionSearch(reader io.Reader) (Message, error) {
var err error = nil
msg := &SessionSearch{}
@ -1399,7 +1348,6 @@ func DecodeSessionSearch(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSBatchMeta(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSBatchMeta{}
@ -1415,7 +1363,6 @@ func DecodeIOSBatchMeta(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSSessionStart(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSSessionStart{}
@ -1452,7 +1399,6 @@ func DecodeIOSSessionStart(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSSessionEnd(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSSessionEnd{}
@ -1462,7 +1408,6 @@ func DecodeIOSSessionEnd(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSMetadata(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSMetadata{}
@ -1481,7 +1426,6 @@ func DecodeIOSMetadata(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSCustomEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSCustomEvent{}
@ -1500,7 +1444,6 @@ func DecodeIOSCustomEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSUserID(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSUserID{}
@ -1516,7 +1459,6 @@ func DecodeIOSUserID(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSUserAnonymousID(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSUserAnonymousID{}
@ -1532,7 +1474,6 @@ func DecodeIOSUserAnonymousID(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSScreenChanges(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSScreenChanges{}
@ -1557,7 +1498,6 @@ func DecodeIOSScreenChanges(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSCrash(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSCrash{}
@ -1579,7 +1519,6 @@ func DecodeIOSCrash(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSScreenEnter(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSScreenEnter{}
@ -1598,7 +1537,6 @@ func DecodeIOSScreenEnter(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSScreenLeave(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSScreenLeave{}
@ -1617,7 +1555,6 @@ func DecodeIOSScreenLeave(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSClickEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSClickEvent{}
@ -1639,7 +1576,6 @@ func DecodeIOSClickEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSInputEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSInputEvent{}
@ -1661,7 +1597,6 @@ func DecodeIOSInputEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSPerformanceEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSPerformanceEvent{}
@ -1680,7 +1615,6 @@ func DecodeIOSPerformanceEvent(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSLog(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSLog{}
@ -1699,7 +1633,6 @@ func DecodeIOSLog(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSInternalError(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSInternalError{}
@ -1715,7 +1648,6 @@ func DecodeIOSInternalError(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSNetworkCall(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSNetworkCall{}
@ -1749,7 +1681,6 @@ func DecodeIOSNetworkCall(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSPerformanceAggregated(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSPerformanceAggregated{}
@ -1798,7 +1729,6 @@ func DecodeIOSPerformanceAggregated(reader io.Reader) (Message, error) {
return msg, err
}
func DecodeIOSIssueEvent(reader io.Reader) (Message, error) {
var err error = nil
msg := &IOSIssueEvent{}
@ -1820,8 +1750,6 @@ func DecodeIOSIssueEvent(reader io.Reader) (Message, error) {
return msg, err
}
func ReadMessage(t uint64, reader io.Reader) (Message, error) {
switch t {
@ -1996,6 +1924,12 @@ func ReadMessage(t uint64, reader io.Reader) (Message, error) {
case 56:
return DecodePerformanceTrackAggr(reader)
case 57:
return DecodeLoadFontFace(reader)
case 58:
return DecodeSetNodeFocus(reader)
case 59:
return DecodeLongTask(reader)

View file

@ -66,12 +66,18 @@ func ResolveCSS(baseURL string, css string) string {
css = rewriteLinks(css, func(rawurl string) string {
return ResolveURL(baseURL, rawurl)
})
return strings.Replace(css, ":hover", ".-openreplay-hover", -1)
return rewritePseudoclasses(css)
}
func (r *Rewriter) RewriteCSS(sessionID uint64, baseurl string, css string) string {
css = rewriteLinks(css, func(rawurl string) string {
return r.RewriteURL(sessionID, baseurl, rawurl)
})
return strings.Replace(css, ":hover", ".-openreplay-hover", -1)
return rewritePseudoclasses(css)
}
func rewritePseudoclasses(css string) string {
css = strings.Replace(css, ":hover", ".-openreplay-hover", -1)
css = strings.Replace(css, ":focus", ".-openreplay-focus", -1)
return css
}

View file

@ -568,6 +568,23 @@ class PerformanceTrackAggr(Message):
self.max_used_js_heap_size = max_used_js_heap_size
class LoadFontFace(Message):
__id__ = 57
def __init__(self, parent_id, family, source, descriptors):
self.parent_id = parent_id
self.family = family
self.source = source
self.descriptors = descriptors
class SetNodeFocus(Message):
__id__ = 58
def __init__(self, id):
self.id = id
class LongTask(Message):
__id__ = 59

View file

@ -524,6 +524,19 @@ class MessageCodec(Codec):
max_used_js_heap_size=self.read_uint(reader)
)
if message_id == 57:
return LoadFontFace(
parent_id=self.read_uint(reader),
family=self.read_string(reader),
source=self.read_string(reader),
descriptors=self.read_string(reader)
)
if message_id == 58:
return SetNodeFocus(
id=self.read_int(reader)
)
if message_id == 59:
return LongTask(
timestamp=self.read_uint(reader),

View file

@ -5,6 +5,7 @@ import type { Message, SetNodeScroll, CreateElementNode } from '../../messages';
import ListWalker from '../ListWalker';
import StylesManager, { rewriteNodeStyleSheet } from './StylesManager';
import FocusManager from './FocusManager';
import {
VElement,
VText,
@ -35,9 +36,9 @@ const ATTR_NAME_REGEXP = /([^\t\n\f \/>"'=]+)/; // regexp costs ~
export default class DOMManager extends ListWalker<Message> {
private vTexts: Map<number, VText> = new Map() // map vs object here?
private vElements: Map<number, VElement> = new Map()
private vRoots: Map<number, VShadowRoot | VDocument> = new Map()
private readonly vTexts: Map<number, VText> = new Map() // map vs object here?
private readonly vElements: Map<number, VElement> = new Map()
private readonly 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()
@ -46,6 +47,7 @@ export default class DOMManager extends ListWalker<Message> {
private upperBodyId: number = -1;
private nodeScrollManagers: Map<number, ListWalker<SetNodeScroll>> = new Map()
private stylesManager: StylesManager
private focusManager: FocusManager = new FocusManager(this.vElements)
constructor(
@ -67,6 +69,10 @@ export default class DOMManager extends ListWalker<Message> {
scrollManager.append(m)
return
}
if (m.tp === "set_node_focus") {
this.focusManager.append(m)
return
}
if (m.tp === "create_element_node") {
if(m.tag === "BODY" && this.upperBodyId === -1) {
this.upperBodyId = m.id
@ -126,7 +132,7 @@ export default class DOMManager extends ListWalker<Message> {
parent.insertChildAt(child, index)
}
private applyMessage = (msg: Message): void => {
private applyMessage = (msg: Message): Promise<any> | undefined => {
let node: Node | undefined
let vn: VNode | undefined
let doc: Document | null
@ -145,12 +151,15 @@ export default class DOMManager extends ListWalker<Message> {
fRoot.innerText = '';
vn = new VElement(fRoot)
this.vElements = new Map([[0, vn]])
this.vElements.clear()
this.vElements.set(0, vn)
const vDoc = new VDocument(doc)
vDoc.insertChildAt(vn, 0)
this.vRoots = new Map([[0, vDoc]]) // watchout: id==0 for both Document and documentElement
this.vRoots.clear()
this.vRoots.set(0, vDoc) // watchout: id==0 for both Document and documentElement
// this is done for the AdoptedCSS logic
// todo: start from 0 (sync logic with tracker)
this.vTexts.clear()
this.stylesManager.reset()
this.activeIframeRoots.clear()
return
@ -371,20 +380,37 @@ export default class DOMManager extends ListWalker<Message> {
//@ts-ignore
vn.node.adoptedStyleSheets = [...vn.node.adoptedStyleSheets].filter(s => s !== styleSheet)
return
case "load_font_face":
vn = this.vRoots.get(msg.parentID)
if (!vn) { logger.error("Node not found", msg); return }
if (vn instanceof VShadowRoot) { logger.error(`Node ${vn} expected to be a Document`, msg); return }
let descr: Object
try {
descr = JSON.parse(msg.descriptors)
descr = typeof descr === 'object' ? descr : undefined
} catch {
logger.warn("Can't parse font-face descriptors: ", msg)
}
const ff = new FontFace(msg.family, msg.source, descr)
vn.node.fonts.add(ff)
return ff.load()
}
}
moveReady(t: number): Promise<void> {
async moveReady(t: number): Promise<void> {
// MBTODO (back jump optimisation):
// - store intemediate virtual dom state
// - cancel previous moveReady tasks (is it possible?) if new timestamp is less
this.moveApply(t, this.applyMessage) // This function autoresets pointer if necessary (better name?)
// This function autoresets pointer if necessary (better name?)
await this.moveWait(t, this.applyMessage)
this.vRoots.forEach(rt => rt.applyChanges()) // MBTODO (optimisation): affected set
// Thinkabout (read): css preload
// What if we go back before it is ready? We'll have two handlres?
return this.stylesManager.moveReady(t).then(() => {
// Apply focus
this.focusManager.move(t)
// Apply all scrolls after the styles got applied
this.nodeScrollManagers.forEach(manager => {
const msg = manager.moveGetLast(t)

View file

@ -0,0 +1,26 @@
import logger from 'App/logger';
import type { SetNodeFocus } from '../../messages';
import type { VElement } from './VirtualDOM';
import ListWalker from '../ListWalker';
const FOCUS_CLASS = "-openreplay-focus"
export default class FocusManager extends ListWalker<SetNodeFocus> {
constructor(private readonly vElements: Map<number, VElement>) {super()}
private focused: Element | null = null
move(t: number) {
const msg = this.moveGetLast(t)
if (!msg) {return}
this.focused?.classList.remove(FOCUS_CLASS)
if (msg.id === -1) {
this.focused = null
return
}
const vn = this.vElements.get(msg.id)
if (!vn) { logger.error("Node not found", msg); return }
this.focused = vn.node
this.focused.classList.add(FOCUS_CLASS)
}
}

View file

@ -9,7 +9,7 @@ export default class ListWalker<T extends Timed> {
console.error("Trying to append message with the less time then the list tail: ", m)
return
}
this._list.push(m);
this.list.push(m);
}
reset(): void {
@ -18,53 +18,53 @@ export default class ListWalker<T extends Timed> {
sort(comparator: (a: T, b: T) => number): void {
// @ts-ignore
this._list.sort((m1,m2) => comparator(m1,m2) || (m1._index - m2._index) ); // indexes for sort stability (TODO: fix types???)
this.list.sort((m1,m2) => comparator(m1,m2) || (m1._index - m2._index) ); // indexes for sort stability (TODO: fix types???)
}
forEach(f: (item: T) => void):void {
this._list.forEach(f);
this.list.forEach(f);
}
get last(): T | null {
if (this._list.length === 0) {
if (this.list.length === 0) {
return null;
}
return this._list[ this._list.length - 1 ];
return this.list[ this.list.length - 1 ];
}
get current(): T | null {
if (this.p === 0) {
return null;
}
return this._list[ this.p - 1 ];
return this.list[ this.p - 1 ];
}
get timeNow(): number {
if (this.p === 0) {
return 0;
}
return this._list[ this.p - 1 ].time;
return this.list[ this.p - 1 ].time;
}
get length(): number {
return this._list.length;
return this.list.length;
}
get maxTime(): number {
if (this.length === 0) {
return 0;
}
return this._list[ this.length - 1 ].time;
return this.list[ this.length - 1 ].time;
}
get minTime(): number {
if (this.length === 0) {
return 0;
}
return this._list[ 0 ].time;
return this.list[ 0 ].time;
}
get listNow(): Array<T> {
return this._list.slice(0, this.p);
return this.list.slice(0, this.p);
}
get list(): Array<T> {
@ -93,28 +93,42 @@ export default class ListWalker<T extends Timed> {
}
let changed = false;
while (this.p < this.length && this._list[this.p][key] <= val) {
while (this.p < this.length && this.list[this.p][key] <= val) {
this.p++;
changed = true;
}
while (this.p > 0 && this._list[ this.p - 1 ][key] > val) {
while (this.p > 0 && this.list[ this.p - 1 ][key] > val) {
this.p--;
changed = true;
}
return changed ? this._list[ this.p - 1 ] : null;
return changed ? this.list[ this.p - 1 ] : null;
}
moveApply(t: number, fn: (T) => void, fnBack?: (T) => void): void {
moveApply(t: number, fn: (msg: T) => void, fnBack?: (msg: T) => void): void {
// Applying only in increment order for now
if (t < this.timeNow) {
this.reset();
}
while (!!this._list[this.p] && this._list[this.p].time <= t) {
fn(this._list[ this.p++ ]);
const list = this.list
while (list[this.p] && list[this.p].time <= t) {
fn(list[ this.p++ ]);
}
while (fnBack && this.p > 0 && this._list[ this.p - 1 ].time > t) {
fnBack(this._list[ --this.p ]);
while (fnBack && this.p > 0 && list[ this.p - 1 ].time > t) {
fnBack(list[ --this.p ]);
}
}
async moveWait(t: number, fn: (msg: T) => Promise<any> | undefined): Promise<void> {
// Applying only in increment order for now
if (t < this.timeNow) {
this.reset();
}
const list = this.list
while (list[this.p] && list[this.p].time <= t) {
const ret = fn(this.list[ this.p++ ]);
if (ret) { await ret }
}
}

View file

@ -366,6 +366,28 @@ export default class RawMessageReader extends PrimitiveReader {
};
}
case 57: {
const parentID = this.readUint(); if (parentID === null) { return resetPointer() }
const family = this.readString(); if (family === null) { return resetPointer() }
const source = this.readString(); if (source === null) { return resetPointer() }
const descriptors = this.readString(); if (descriptors === null) { return resetPointer() }
return {
tp: "load_font_face",
parentID,
family,
source,
descriptors,
};
}
case 58: {
const id = this.readInt(); if (id === null) { return resetPointer() }
return {
tp: "set_node_focus",
id,
};
}
case 59: {
const timestamp = this.readUint(); if (timestamp === null) { return resetPointer() }
const duration = this.readUint(); if (duration === null) { return resetPointer() }

View file

@ -35,6 +35,8 @@ import type {
RawPerformanceTrack,
RawConnectionInformation,
RawSetPageVisibility,
RawLoadFontFace,
RawSetNodeFocus,
RawLongTask,
RawSetNodeAttributeURLBased,
RawSetCssDataURLBased,
@ -123,6 +125,10 @@ export type ConnectionInformation = RawConnectionInformation & Timed
export type SetPageVisibility = RawSetPageVisibility & Timed
export type LoadFontFace = RawLoadFontFace & Timed
export type SetNodeFocus = RawSetNodeFocus & Timed
export type LongTask = RawLongTask & Timed
export type SetNodeAttributeURLBased = RawSetNodeAttributeURLBased & Timed

View file

@ -207,6 +207,19 @@ export interface RawSetPageVisibility {
hidden: boolean,
}
export interface RawLoadFontFace {
tp: "load_font_face",
parentID: number,
family: string,
source: string,
descriptors: string,
}
export interface RawSetNodeFocus {
tp: "set_node_focus",
id: number,
}
export interface RawLongTask {
tp: "long_task",
timestamp: number,
@ -378,4 +391,4 @@ export interface RawIosNetworkCall {
}
export type RawMessage = RawTimestamp | RawSetPageLocation | RawSetViewportSize | RawSetViewportScroll | RawCreateDocument | RawCreateElementNode | RawCreateTextNode | RawMoveNode | RawRemoveNode | RawSetNodeAttribute | RawRemoveNodeAttribute | RawSetNodeData | RawSetCssData | RawSetNodeScroll | RawSetInputValue | RawSetInputChecked | RawMouseMove | RawConsoleLog | RawCssInsertRule | RawCssDeleteRule | RawFetch | RawProfiler | RawOTable | RawRedux | RawVuex | RawMobX | RawNgRx | RawGraphQl | RawPerformanceTrack | RawConnectionInformation | RawSetPageVisibility | RawLongTask | RawSetNodeAttributeURLBased | RawSetCssDataURLBased | RawCssInsertRuleURLBased | RawMouseClick | RawCreateIFrameDocument | RawAdoptedSsReplaceURLBased | RawAdoptedSsReplace | RawAdoptedSsInsertRuleURLBased | RawAdoptedSsInsertRule | RawAdoptedSsDeleteRule | RawAdoptedSsAddOwner | RawAdoptedSsRemoveOwner | RawZustand | RawIosSessionStart | RawIosCustomEvent | RawIosScreenChanges | RawIosClickEvent | RawIosPerformanceEvent | RawIosLog | RawIosNetworkCall;
export type RawMessage = RawTimestamp | RawSetPageLocation | RawSetViewportSize | RawSetViewportScroll | RawCreateDocument | RawCreateElementNode | RawCreateTextNode | RawMoveNode | RawRemoveNode | RawSetNodeAttribute | RawRemoveNodeAttribute | RawSetNodeData | RawSetCssData | RawSetNodeScroll | RawSetInputValue | RawSetInputChecked | RawMouseMove | RawConsoleLog | RawCssInsertRule | RawCssDeleteRule | RawFetch | RawProfiler | RawOTable | RawRedux | RawVuex | RawMobX | RawNgRx | RawGraphQl | RawPerformanceTrack | RawConnectionInformation | RawSetPageVisibility | RawLoadFontFace | RawSetNodeFocus | RawLongTask | RawSetNodeAttributeURLBased | RawSetCssDataURLBased | RawCssInsertRuleURLBased | RawMouseClick | RawCreateIFrameDocument | RawAdoptedSsReplaceURLBased | RawAdoptedSsReplace | RawAdoptedSsInsertRuleURLBased | RawAdoptedSsInsertRule | RawAdoptedSsDeleteRule | RawAdoptedSsAddOwner | RawAdoptedSsRemoveOwner | RawZustand | RawIosSessionStart | RawIosCustomEvent | RawIosScreenChanges | RawIosClickEvent | RawIosPerformanceEvent | RawIosLog | RawIosNetworkCall;

View file

@ -46,6 +46,8 @@ export const TP_MAP = {
53: "resource_timing",
54: "connection_information",
55: "set_page_visibility",
57: "load_font_face",
58: "set_node_focus",
59: "long_task",
60: "set_node_attribute_url_based",
61: "set_css_data_url_based",

View file

@ -290,6 +290,19 @@ type TrSetPageVisibility = [
hidden: boolean,
]
type TrLoadFontFace = [
type: 57,
parentID: number,
family: string,
source: string,
descriptors: string,
]
type TrSetNodeFocus = [
type: 58,
id: number,
]
type TrLongTask = [
type: 59,
timestamp: number,
@ -398,7 +411,7 @@ type TrJSException = [
]
export type TrackerMessage = TrBatchMetadata | TrPartitionedMessage | TrTimestamp | TrSetPageLocation | TrSetViewportSize | TrSetViewportScroll | TrCreateDocument | TrCreateElementNode | TrCreateTextNode | TrMoveNode | TrRemoveNode | TrSetNodeAttribute | TrRemoveNodeAttribute | TrSetNodeData | TrSetNodeScroll | TrSetInputTarget | TrSetInputValue | TrSetInputChecked | TrMouseMove | TrConsoleLog | TrPageLoadTiming | TrPageRenderTiming | TrJSExceptionDeprecated | TrRawCustomEvent | TrUserID | TrUserAnonymousID | TrMetadata | TrCSSInsertRule | TrCSSDeleteRule | TrFetch | TrProfiler | TrOTable | TrStateAction | TrRedux | TrVuex | TrMobX | TrNgRx | TrGraphQL | TrPerformanceTrack | TrResourceTiming | TrConnectionInformation | TrSetPageVisibility | TrLongTask | TrSetNodeAttributeURLBased | TrSetCSSDataURLBased | TrTechnicalInfo | TrCustomIssue | TrCSSInsertRuleURLBased | TrMouseClick | TrCreateIFrameDocument | TrAdoptedSSReplaceURLBased | TrAdoptedSSInsertRuleURLBased | TrAdoptedSSDeleteRule | TrAdoptedSSAddOwner | TrAdoptedSSRemoveOwner | TrZustand | TrJSException
export type TrackerMessage = TrBatchMetadata | TrPartitionedMessage | TrTimestamp | TrSetPageLocation | TrSetViewportSize | TrSetViewportScroll | TrCreateDocument | TrCreateElementNode | TrCreateTextNode | TrMoveNode | TrRemoveNode | TrSetNodeAttribute | TrRemoveNodeAttribute | TrSetNodeData | TrSetNodeScroll | TrSetInputTarget | TrSetInputValue | TrSetInputChecked | TrMouseMove | TrConsoleLog | TrPageLoadTiming | TrPageRenderTiming | TrJSExceptionDeprecated | TrRawCustomEvent | TrUserID | TrUserAnonymousID | TrMetadata | TrCSSInsertRule | TrCSSDeleteRule | TrFetch | TrProfiler | TrOTable | TrStateAction | TrRedux | TrVuex | TrMobX | TrNgRx | TrGraphQL | TrPerformanceTrack | TrResourceTiming | TrConnectionInformation | TrSetPageVisibility | TrLoadFontFace | TrSetNodeFocus | TrLongTask | TrSetNodeAttributeURLBased | TrSetCSSDataURLBased | TrTechnicalInfo | TrCustomIssue | TrCSSInsertRuleURLBased | TrMouseClick | TrCreateIFrameDocument | TrAdoptedSSReplaceURLBased | TrAdoptedSSInsertRuleURLBased | TrAdoptedSSDeleteRule | TrAdoptedSSAddOwner | TrAdoptedSSRemoveOwner | TrZustand | TrJSException
export default function translate(tMsg: TrackerMessage): RawMessage | null {
switch(tMsg[0]) {
@ -662,6 +675,23 @@ export default function translate(tMsg: TrackerMessage): RawMessage | null {
}
}
case 57: {
return {
tp: "load_font_face",
parentID: tMsg[1],
family: tMsg[2],
source: tMsg[3],
descriptors: tMsg[4],
}
}
case 58: {
return {
tp: "set_node_focus",
id: tMsg[1],
}
}
case 59: {
return {
tp: "long_task",

View file

@ -50,6 +50,14 @@ function rewriteCSSLinks(css: string, rewriter: (rawurl: string) => string): str
return css
}
export function resolveCSS(baseURL: string, css: string): string {
return rewriteCSSLinks(css, rawurl => resolveURL(baseURL, rawurl));
function rewritePseudoclasses(css: string): string {
return css
.replace(/:hover/g, ".-openreplay-hover")
.replace(/:focus/g, ".-openreplay-focus")
}
export function resolveCSS(baseURL: string, css: string): string {
return rewritePseudoclasses(
rewriteCSSLinks(css, rawurl => resolveURL(baseURL, rawurl))
);
}

View file

@ -4,11 +4,5 @@
To generate all necessary files for the project:
```sh
ruby run.rb
sh generate.sh
```
In order format generated files run:
```sh
sh format.sh
```
(Otherwise there will be changes in stage)

View file

@ -1 +1,2 @@
ruby run.rb
gofmt -w ../backend/pkg/messages

View file

@ -359,7 +359,19 @@ message 56, 'PerformanceTrackAggr', :tracker => false, :replayer => false do
uint 'AvgUsedJSHeapSize'
uint 'MaxUsedJSHeapSize'
end
## 57 58
# Since 4.1.7 / 1.9.0
message 57, 'LoadFontFace' do
uint 'ParentID'
string 'Family'
string 'Source'
string 'Descriptors'
end
# Since 4.1.7 / 1.9.0
message 58, 'SetNodeFocus' do
int 'ID'
end
#Depricated (since 3.0.?)
message 59, 'LongTask' do
uint 'Timestamp'
@ -466,6 +478,8 @@ message 78, 'JSException', :replayer => false do
string 'Payload'
string 'Metadata'
end
message 126, 'SessionEnd', :tracker => false, :replayer => false do
uint 'Timestamp'
string 'EncryptionKey'

View file

@ -44,6 +44,8 @@ export declare const enum Type {
ResourceTiming = 53,
ConnectionInformation = 54,
SetPageVisibility = 55,
LoadFontFace = 57,
SetNodeFocus = 58,
LongTask = 59,
SetNodeAttributeURLBased = 60,
SetCSSDataURLBased = 61,
@ -348,6 +350,19 @@ export type SetPageVisibility = [
/*hidden:*/ boolean,
]
export type LoadFontFace = [
/*type:*/ Type.LoadFontFace,
/*parentID:*/ number,
/*family:*/ string,
/*source:*/ string,
/*descriptors:*/ string,
]
export type SetNodeFocus = [
/*type:*/ Type.SetNodeFocus,
/*id:*/ number,
]
export type LongTask = [
/*type:*/ Type.LongTask,
/*timestamp:*/ number,
@ -456,5 +471,5 @@ export type JSException = [
]
type Message = BatchMetadata | PartitionedMessage | Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | ConsoleLog | PageLoadTiming | PageRenderTiming | JSExceptionDeprecated | RawCustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | Redux | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | ResourceTiming | ConnectionInformation | SetPageVisibility | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | Zustand | JSException
type Message = BatchMetadata | PartitionedMessage | Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | ConsoleLog | PageLoadTiming | PageRenderTiming | JSExceptionDeprecated | RawCustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | Redux | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | ResourceTiming | ConnectionInformation | SetPageVisibility | LoadFontFace | SetNodeFocus | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | Zustand | JSException
export default Message

View file

@ -25,6 +25,7 @@ export function isRootNode(node: Node): node is Document | DocumentFragment {
type TagTypeMap = {
HTML: HTMLHtmlElement
BODY: HTMLBodyElement
IMG: HTMLImageElement
INPUT: HTMLInputElement
TEXTAREA: HTMLTextAreaElement

View file

@ -480,7 +480,8 @@ export default class App {
const onStartInfo = { sessionToken: token, userUUID, sessionID }
this.startCallbacks.forEach((cb) => cb(onStartInfo)) // TODO: start as early as possible (before receiving the token)
// TODO: start as early as possible (before receiving the token)
this.startCallbacks.forEach((cb) => cb(onStartInfo)) // MBTODO: callbacks after DOM "mounted" (observed)
this.observer.observe()
this.ticker.start()
this.activityState = ActivityState.Active

View file

@ -535,6 +535,30 @@ export function SetPageVisibility(
]
}
export function LoadFontFace(
parentID: number,
family: string,
source: string,
descriptors: string,
): Messages.LoadFontFace {
return [
Messages.Type.LoadFontFace,
parentID,
family,
source,
descriptors,
]
}
export function SetNodeFocus(
id: number,
): Messages.SetNodeFocus {
return [
Messages.Type.SetNodeFocus,
id,
]
}
export function LongTask(
timestamp: number,
duration: number,

View file

@ -129,6 +129,8 @@ export default class TopObserver extends Observer {
window.document,
() => {
this.app.send(CreateDocument())
// it has no node_id here
this.app.nodes.callNodeCallbacks(document, true)
},
window.document.documentElement,
)

View file

@ -20,6 +20,8 @@ import Performance from './modules/performance.js'
import Scroll from './modules/scroll.js'
import Viewport from './modules/viewport.js'
import CSSRules from './modules/cssrules.js'
import Focus from './modules/focus.js'
import Fonts from './modules/fonts.js'
import ConstructedStyleSheets from './modules/constructedStyleSheets.js'
import { IN_BROWSER, deprecationWarn, DOCS_HOST } from './utils.js'
@ -123,6 +125,8 @@ export default class API {
Timing(app, options)
Performance(app, options)
Scroll(app)
Focus(app)
Fonts(app)
;(window as any).__OPENREPLAY__ = this
if (options.autoResetOnWindowOpen) {

View file

@ -31,10 +31,6 @@ export default function (app: App | null) {
return
}
if (!hasAdoptedSS(document)) {
app.attachStartCallback(() => {
// MBTODO: pre-start sendQueue app
app.send(TechnicalInfo('no_adopted_stylesheets', ''))
})
return
}

View file

@ -0,0 +1,45 @@
import type App from '../app/index.js'
import { isNode, hasTag } from '../app/guards.js'
import { SetNodeFocus } from '../app/messages.gen.js'
export default function (app: App): void {
function sendSetNodeFocus(n: Node) {
const id = app.nodes.getID(n)
if (id !== undefined) {
app.send(SetNodeFocus(id))
}
}
let blurred = false
app.nodes.attachNodeCallback((node) => {
if (!hasTag(node, 'BODY')) {
return
}
app.nodes.attachNodeListener(node, 'focus', (e: FocusEvent): void => {
if (!isNode(e.target)) {
return
}
sendSetNodeFocus(e.target)
blurred = false
})
app.nodes.attachNodeListener(node, 'blur', (e: FocusEvent): void => {
if (e.relatedTarget === null) {
blurred = true
setTimeout(() => {
if (blurred) {
app.send(SetNodeFocus(-1))
}
}, 0)
}
})
})
app.attachStartCallback(() => {
let elem = document.activeElement
while (elem && hasTag(elem, 'IFRAME') && elem.contentDocument) {
elem = elem.contentDocument.activeElement
}
if (elem && elem !== elem.ownerDocument.body) {
sendSetNodeFocus(elem)
}
}, true)
}

View file

@ -0,0 +1,66 @@
import type App from '../app/index.js'
import { isDocument } from '../app/guards.js'
import { LoadFontFace } from '../app/messages.gen.js'
type FFData = [string, string, string]
export default function (app: App) {
if (!window.FontFace) {
return
}
const docFonts: Map<Document, FFData[]> = new Map()
const patchWindow = (wnd: typeof globalThis) => {
class FontFaceInterceptor extends wnd.FontFace {
constructor(...args: ConstructorParameters<typeof FontFace>) {
//maybe do this on load(). In this case check if the document.fonts.load(...) function calls the font's load()
if (typeof args[1] === 'string') {
let desc = ''
if (args[2]) {
app.safe(() => {
desc = JSON.stringify(args[2])
})
}
const ffData: FFData = [args[0], args[1], desc]
const ffDataArr = docFonts.get(wnd.document) || []
ffDataArr.push(ffData)
docFonts.set(wnd.document, ffDataArr)
const parentID = wnd === window ? 0 : app.nodes.getID(wnd.document)
if (parentID === undefined) {
return
}
if (app.active()) {
app.send(LoadFontFace(parentID, ...ffData))
}
}
super(...args)
}
}
wnd.FontFace = FontFaceInterceptor
}
app.observer.attachContextCallback(patchWindow)
patchWindow(window)
app.nodes.attachNodeCallback((node) => {
if (!isDocument(node)) {
return
}
const ffDataArr = docFonts.get(node)
if (!ffDataArr) {
return
}
const parentID = node.defaultView === window ? 0 : app.nodes.getID(node)
if (parentID === undefined) {
return
}
ffDataArr.forEach((ffData) => {
app.send(LoadFontFace(parentID, ...ffData))
})
})
}

View file

@ -178,6 +178,14 @@ export default class MessageEncoder extends PrimitiveEncoder {
return this.boolean(msg[1])
break
case Messages.Type.LoadFontFace:
return this.uint(msg[1]) && this.string(msg[2]) && this.string(msg[3]) && this.string(msg[4])
break
case Messages.Type.SetNodeFocus:
return this.int(msg[1])
break
case Messages.Type.LongTask:
return this.uint(msg[1]) && this.uint(msg[2]) && this.uint(msg[3]) && this.uint(msg[4]) && this.string(msg[5]) && this.string(msg[6]) && this.string(msg[7])
break