@kubesense/kubesense-browser-rum 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +34 -0
- package/bundle/chunks/profiler-b64730a2109c3ddbc539-kubesense-rum.js +1 -0
- package/bundle/chunks/recorder-9ae532a18bac5f4280da-kubesense-rum.js +1 -0
- package/bundle/kubesense-rum.js +1 -0
- package/cjs/boot/isBrowserSupported.d.ts +4 -0
- package/cjs/boot/isBrowserSupported.js +17 -0
- package/cjs/boot/isBrowserSupported.js.map +1 -0
- package/cjs/boot/lazyLoadProfiler.d.ts +4 -0
- package/cjs/boot/lazyLoadProfiler.js +54 -0
- package/cjs/boot/lazyLoadProfiler.js.map +1 -0
- package/cjs/boot/lazyLoadRecorder.d.ts +4 -0
- package/cjs/boot/lazyLoadRecorder.js +54 -0
- package/cjs/boot/lazyLoadRecorder.js.map +1 -0
- package/cjs/boot/postStartStrategy.d.ts +33 -0
- package/cjs/boot/postStartStrategy.js +98 -0
- package/cjs/boot/postStartStrategy.js.map +1 -0
- package/cjs/boot/preStartStrategy.d.ts +6 -0
- package/cjs/boot/preStartStrategy.js +24 -0
- package/cjs/boot/preStartStrategy.js.map +1 -0
- package/cjs/boot/profilerApi.d.ts +2 -0
- package/cjs/boot/profilerApi.js +53 -0
- package/cjs/boot/profilerApi.js.map +1 -0
- package/cjs/boot/recorderApi.d.ts +4 -0
- package/cjs/boot/recorderApi.js +73 -0
- package/cjs/boot/recorderApi.js.map +1 -0
- package/cjs/boot/startRecording.d.ts +6 -0
- package/cjs/boot/startRecording.js +45 -0
- package/cjs/boot/startRecording.js.map +1 -0
- package/cjs/domain/deflate/deflateEncoder.d.ts +3 -0
- package/cjs/domain/deflate/deflateEncoder.js +110 -0
- package/cjs/domain/deflate/deflateEncoder.js.map +1 -0
- package/cjs/domain/deflate/deflateWorker.d.ts +30 -0
- package/cjs/domain/deflate/deflateWorker.js +104 -0
- package/cjs/domain/deflate/deflateWorker.js.map +1 -0
- package/cjs/domain/deflate/index.d.ts +3 -0
- package/cjs/domain/deflate/index.js +10 -0
- package/cjs/domain/deflate/index.js.map +1 -0
- package/cjs/domain/getSessionReplayLink.d.ts +2 -0
- package/cjs/domain/getSessionReplayLink.js +35 -0
- package/cjs/domain/getSessionReplayLink.js.map +1 -0
- package/cjs/domain/profiling/profiler.d.ts +7 -0
- package/cjs/domain/profiling/profiler.js +244 -0
- package/cjs/domain/profiling/profiler.js.map +1 -0
- package/cjs/domain/profiling/profilingContext.d.ts +6 -0
- package/cjs/domain/profiling/profilingContext.js +28 -0
- package/cjs/domain/profiling/profilingContext.js.map +1 -0
- package/cjs/domain/profiling/profilingSupported.d.ts +1 -0
- package/cjs/domain/profiling/profilingSupported.js +11 -0
- package/cjs/domain/profiling/profilingSupported.js.map +1 -0
- package/cjs/domain/profiling/test-utils/mockedTrace.d.ts +3 -0
- package/cjs/domain/profiling/test-utils/mockedTrace.js +57 -0
- package/cjs/domain/profiling/test-utils/mockedTrace.js.map +1 -0
- package/cjs/domain/profiling/transport/assembly.d.ts +21 -0
- package/cjs/domain/profiling/transport/assembly.js +45 -0
- package/cjs/domain/profiling/transport/assembly.js.map +1 -0
- package/cjs/domain/profiling/transport/buildProfileEventAttributes.d.ts +25 -0
- package/cjs/domain/profiling/transport/buildProfileEventAttributes.js +50 -0
- package/cjs/domain/profiling/transport/buildProfileEventAttributes.js.map +1 -0
- package/cjs/domain/profiling/types/index.d.ts +2 -0
- package/cjs/domain/profiling/types/index.js +3 -0
- package/cjs/domain/profiling/types/index.js.map +1 -0
- package/cjs/domain/profiling/types/profilerApi.types.d.ts +58 -0
- package/cjs/domain/profiling/types/profilerApi.types.js +5 -0
- package/cjs/domain/profiling/types/profilerApi.types.js.map +1 -0
- package/cjs/domain/profiling/types/rumProfiler.types.d.ts +72 -0
- package/cjs/domain/profiling/types/rumProfiler.types.js +3 -0
- package/cjs/domain/profiling/types/rumProfiler.types.js.map +1 -0
- package/cjs/domain/profiling/utils/getCustomOrDefaultViewName.d.ts +1 -0
- package/cjs/domain/profiling/utils/getCustomOrDefaultViewName.js +7 -0
- package/cjs/domain/profiling/utils/getCustomOrDefaultViewName.js.map +1 -0
- package/cjs/domain/profiling/utils/getDefaultViewName.d.ts +1 -0
- package/cjs/domain/profiling/utils/getDefaultViewName.js +14 -0
- package/cjs/domain/profiling/utils/getDefaultViewName.js.map +1 -0
- package/cjs/domain/profiling/utils/getNumberOfSamples.d.ts +7 -0
- package/cjs/domain/profiling/utils/getNumberOfSamples.js +18 -0
- package/cjs/domain/profiling/utils/getNumberOfSamples.js.map +1 -0
- package/cjs/domain/record/assembly.d.ts +2 -0
- package/cjs/domain/record/assembly.js +16 -0
- package/cjs/domain/record/assembly.js.map +1 -0
- package/cjs/domain/record/elementsScrollPositions.d.ts +10 -0
- package/cjs/domain/record/elementsScrollPositions.js +23 -0
- package/cjs/domain/record/elementsScrollPositions.js.map +1 -0
- package/cjs/domain/record/eventIds.d.ts +4 -0
- package/cjs/domain/record/eventIds.js +16 -0
- package/cjs/domain/record/eventIds.js.map +1 -0
- package/cjs/domain/record/eventsUtils.d.ts +2 -0
- package/cjs/domain/record/eventsUtils.js +15 -0
- package/cjs/domain/record/eventsUtils.js.map +1 -0
- package/cjs/domain/record/index.d.ts +7 -0
- package/cjs/domain/record/index.js +17 -0
- package/cjs/domain/record/index.js.map +1 -0
- package/cjs/domain/record/internalApi.d.ts +22 -0
- package/cjs/domain/record/internalApi.js +57 -0
- package/cjs/domain/record/internalApi.js.map +1 -0
- package/cjs/domain/record/mutationBatch.d.ts +12 -0
- package/cjs/domain/record/mutationBatch.js +44 -0
- package/cjs/domain/record/mutationBatch.js.map +1 -0
- package/cjs/domain/record/nodeIds.d.ts +15 -0
- package/cjs/domain/record/nodeIds.js +32 -0
- package/cjs/domain/record/nodeIds.js.map +1 -0
- package/cjs/domain/record/record.d.ts +16 -0
- package/cjs/domain/record/record.js +90 -0
- package/cjs/domain/record/record.js.map +1 -0
- package/cjs/domain/record/record.types.d.ts +4 -0
- package/cjs/domain/record/record.types.js +3 -0
- package/cjs/domain/record/record.types.js.map +1 -0
- package/cjs/domain/record/recordingScope.d.ts +19 -0
- package/cjs/domain/record/recordingScope.js +13 -0
- package/cjs/domain/record/recordingScope.js.map +1 -0
- package/cjs/domain/record/serialization/index.d.ts +8 -0
- package/cjs/domain/record/serialization/index.js +18 -0
- package/cjs/domain/record/serialization/index.js.map +1 -0
- package/cjs/domain/record/serialization/serialization.types.d.ts +28 -0
- package/cjs/domain/record/serialization/serialization.types.js +3 -0
- package/cjs/domain/record/serialization/serialization.types.js.map +1 -0
- package/cjs/domain/record/serialization/serializationStats.d.ts +12 -0
- package/cjs/domain/record/serialization/serializationStats.js +32 -0
- package/cjs/domain/record/serialization/serializationStats.js.map +1 -0
- package/cjs/domain/record/serialization/serializationTransaction.d.ts +45 -0
- package/cjs/domain/record/serialization/serializationTransaction.js +38 -0
- package/cjs/domain/record/serialization/serializationTransaction.js.map +1 -0
- package/cjs/domain/record/serialization/serializationUtils.d.ts +18 -0
- package/cjs/domain/record/serialization/serializationUtils.js +88 -0
- package/cjs/domain/record/serialization/serializationUtils.js.map +1 -0
- package/cjs/domain/record/serialization/serializeAttribute.d.ts +4 -0
- package/cjs/domain/record/serialization/serializeAttribute.js +42 -0
- package/cjs/domain/record/serialization/serializeAttribute.js.map +1 -0
- package/cjs/domain/record/serialization/serializeAttributes.d.ts +7 -0
- package/cjs/domain/record/serialization/serializeAttributes.js +167 -0
- package/cjs/domain/record/serialization/serializeAttributes.js.map +1 -0
- package/cjs/domain/record/serialization/serializeDocument.d.ts +3 -0
- package/cjs/domain/record/serialization/serializeDocument.js +11 -0
- package/cjs/domain/record/serialization/serializeDocument.js.map +1 -0
- package/cjs/domain/record/serialization/serializeNode.d.ts +7 -0
- package/cjs/domain/record/serialization/serializeNode.js +154 -0
- package/cjs/domain/record/serialization/serializeNode.js.map +1 -0
- package/cjs/domain/record/serialization/serializeStyleSheets.d.ts +2 -0
- package/cjs/domain/record/serialization/serializeStyleSheets.js +19 -0
- package/cjs/domain/record/serialization/serializeStyleSheets.js.map +1 -0
- package/cjs/domain/record/shadowRootsController.d.ts +11 -0
- package/cjs/domain/record/shadowRootsController.js +45 -0
- package/cjs/domain/record/shadowRootsController.js.map +1 -0
- package/cjs/domain/record/startFullSnapshots.d.ts +9 -0
- package/cjs/domain/record/startFullSnapshots.js +59 -0
- package/cjs/domain/record/startFullSnapshots.js.map +1 -0
- package/cjs/domain/record/trackers/index.d.ts +12 -0
- package/cjs/domain/record/trackers/index.js +27 -0
- package/cjs/domain/record/trackers/index.js.map +1 -0
- package/cjs/domain/record/trackers/trackFocus.d.ts +5 -0
- package/cjs/domain/record/trackers/trackFocus.js +15 -0
- package/cjs/domain/record/trackers/trackFocus.js.map +1 -0
- package/cjs/domain/record/trackers/trackFrustration.d.ts +7 -0
- package/cjs/domain/record/trackers/trackFrustration.js +31 -0
- package/cjs/domain/record/trackers/trackFrustration.js.map +1 -0
- package/cjs/domain/record/trackers/trackInput.d.ts +4 -0
- package/cjs/domain/record/trackers/trackInput.js +104 -0
- package/cjs/domain/record/trackers/trackInput.js.map +1 -0
- package/cjs/domain/record/trackers/trackMediaInteraction.d.ts +5 -0
- package/cjs/domain/record/trackers/trackMediaInteraction.js +29 -0
- package/cjs/domain/record/trackers/trackMediaInteraction.js.map +1 -0
- package/cjs/domain/record/trackers/trackMouseInteraction.d.ts +5 -0
- package/cjs/domain/record/trackers/trackMouseInteraction.js +59 -0
- package/cjs/domain/record/trackers/trackMouseInteraction.js.map +1 -0
- package/cjs/domain/record/trackers/trackMove.d.ts +9 -0
- package/cjs/domain/record/trackers/trackMove.js +55 -0
- package/cjs/domain/record/trackers/trackMove.js.map +1 -0
- package/cjs/domain/record/trackers/trackMutation.d.ts +11 -0
- package/cjs/domain/record/trackers/trackMutation.js +270 -0
- package/cjs/domain/record/trackers/trackMutation.js.map +1 -0
- package/cjs/domain/record/trackers/trackScroll.d.ts +5 -0
- package/cjs/domain/record/trackers/trackScroll.js +48 -0
- package/cjs/domain/record/trackers/trackScroll.js.map +1 -0
- package/cjs/domain/record/trackers/trackStyleSheet.d.ts +6 -0
- package/cjs/domain/record/trackers/trackStyleSheet.js +89 -0
- package/cjs/domain/record/trackers/trackStyleSheet.js.map +1 -0
- package/cjs/domain/record/trackers/trackViewEnd.d.ts +5 -0
- package/cjs/domain/record/trackers/trackViewEnd.js +20 -0
- package/cjs/domain/record/trackers/trackViewEnd.js.map +1 -0
- package/cjs/domain/record/trackers/trackViewportResize.d.ts +6 -0
- package/cjs/domain/record/trackers/trackViewportResize.js +46 -0
- package/cjs/domain/record/trackers/trackViewportResize.js.map +1 -0
- package/cjs/domain/record/trackers/tracker.types.d.ts +3 -0
- package/cjs/domain/record/trackers/tracker.types.js +3 -0
- package/cjs/domain/record/trackers/tracker.types.js.map +1 -0
- package/cjs/domain/record/viewports.d.ts +20 -0
- package/cjs/domain/record/viewports.js +60 -0
- package/cjs/domain/record/viewports.js.map +1 -0
- package/cjs/domain/replayStats.d.ts +8 -0
- package/cjs/domain/replayStats.js +60 -0
- package/cjs/domain/replayStats.js.map +1 -0
- package/cjs/domain/scriptLoadingError.d.ts +6 -0
- package/cjs/domain/scriptLoadingError.js +26 -0
- package/cjs/domain/scriptLoadingError.js.map +1 -0
- package/cjs/domain/segmentCollection/buildReplayPayload.d.ts +15 -0
- package/cjs/domain/segmentCollection/buildReplayPayload.js +26 -0
- package/cjs/domain/segmentCollection/buildReplayPayload.js.map +1 -0
- package/cjs/domain/segmentCollection/index.d.ts +4 -0
- package/cjs/domain/segmentCollection/index.js +11 -0
- package/cjs/domain/segmentCollection/index.js.map +1 -0
- package/cjs/domain/segmentCollection/segment.d.ts +16 -0
- package/cjs/domain/segmentCollection/segment.js +82 -0
- package/cjs/domain/segmentCollection/segment.js.map +1 -0
- package/cjs/domain/segmentCollection/segmentCollection.d.ts +31 -0
- package/cjs/domain/segmentCollection/segmentCollection.js +113 -0
- package/cjs/domain/segmentCollection/segmentCollection.js.map +1 -0
- package/cjs/domain/segmentCollection/startSegmentTelemetry.d.ts +6 -0
- package/cjs/domain/segmentCollection/startSegmentTelemetry.js +47 -0
- package/cjs/domain/segmentCollection/startSegmentTelemetry.js.map +1 -0
- package/cjs/domain/startRecordBridge.d.ts +5 -0
- package/cjs/domain/startRecordBridge.js +17 -0
- package/cjs/domain/startRecordBridge.js.map +1 -0
- package/cjs/domain/startRecorderInitTelemetry.d.ts +15 -0
- package/cjs/domain/startRecorderInitTelemetry.js +55 -0
- package/cjs/domain/startRecorderInitTelemetry.js.map +1 -0
- package/cjs/entries/internal.d.ts +11 -0
- package/cjs/entries/internal.js +28 -0
- package/cjs/entries/internal.js.map +1 -0
- package/cjs/entries/internalSynthetics.d.ts +2 -0
- package/cjs/entries/internalSynthetics.js +27 -0
- package/cjs/entries/internalSynthetics.js.map +1 -0
- package/cjs/entries/main.d.ts +23 -0
- package/cjs/entries/main.js +35 -0
- package/cjs/entries/main.js.map +1 -0
- package/cjs/types/index.d.ts +2 -0
- package/cjs/types/index.js +18 -0
- package/cjs/types/index.js.map +1 -0
- package/cjs/types/sessionReplay.d.ts +703 -0
- package/cjs/types/sessionReplay.js +7 -0
- package/cjs/types/sessionReplay.js.map +1 -0
- package/cjs/types/sessionReplayConstants.d.ts +49 -0
- package/cjs/types/sessionReplayConstants.js +49 -0
- package/cjs/types/sessionReplayConstants.js.map +1 -0
- package/esm/boot/isBrowserSupported.d.ts +4 -0
- package/esm/boot/isBrowserSupported.js +14 -0
- package/esm/boot/isBrowserSupported.js.map +1 -0
- package/esm/boot/lazyLoadProfiler.d.ts +4 -0
- package/esm/boot/lazyLoadProfiler.js +18 -0
- package/esm/boot/lazyLoadProfiler.js.map +1 -0
- package/esm/boot/lazyLoadRecorder.d.ts +4 -0
- package/esm/boot/lazyLoadRecorder.js +18 -0
- package/esm/boot/lazyLoadRecorder.js.map +1 -0
- package/esm/boot/postStartStrategy.d.ts +33 -0
- package/esm/boot/postStartStrategy.js +95 -0
- package/esm/boot/postStartStrategy.js.map +1 -0
- package/esm/boot/preStartStrategy.d.ts +6 -0
- package/esm/boot/preStartStrategy.js +21 -0
- package/esm/boot/preStartStrategy.js.map +1 -0
- package/esm/boot/profilerApi.d.ts +2 -0
- package/esm/boot/profilerApi.js +50 -0
- package/esm/boot/profilerApi.js.map +1 -0
- package/esm/boot/recorderApi.d.ts +4 -0
- package/esm/boot/recorderApi.js +70 -0
- package/esm/boot/recorderApi.js.map +1 -0
- package/esm/boot/startRecording.d.ts +6 -0
- package/esm/boot/startRecording.js +42 -0
- package/esm/boot/startRecording.js.map +1 -0
- package/esm/domain/deflate/deflateEncoder.d.ts +3 -0
- package/esm/domain/deflate/deflateEncoder.js +107 -0
- package/esm/domain/deflate/deflateEncoder.js.map +1 -0
- package/esm/domain/deflate/deflateWorker.d.ts +30 -0
- package/esm/domain/deflate/deflateWorker.js +97 -0
- package/esm/domain/deflate/deflateWorker.js.map +1 -0
- package/esm/domain/deflate/index.d.ts +3 -0
- package/esm/domain/deflate/index.js +3 -0
- package/esm/domain/deflate/index.js.map +1 -0
- package/esm/domain/getSessionReplayLink.d.ts +2 -0
- package/esm/domain/getSessionReplayLink.js +32 -0
- package/esm/domain/getSessionReplayLink.js.map +1 -0
- package/esm/domain/profiling/profiler.d.ts +7 -0
- package/esm/domain/profiling/profiler.js +240 -0
- package/esm/domain/profiling/profiler.js.map +1 -0
- package/esm/domain/profiling/profilingContext.d.ts +6 -0
- package/esm/domain/profiling/profilingContext.js +25 -0
- package/esm/domain/profiling/profilingContext.js.map +1 -0
- package/esm/domain/profiling/profilingSupported.d.ts +1 -0
- package/esm/domain/profiling/profilingSupported.js +8 -0
- package/esm/domain/profiling/profilingSupported.js.map +1 -0
- package/esm/domain/profiling/test-utils/mockedTrace.d.ts +3 -0
- package/esm/domain/profiling/test-utils/mockedTrace.js +54 -0
- package/esm/domain/profiling/test-utils/mockedTrace.js.map +1 -0
- package/esm/domain/profiling/transport/assembly.d.ts +21 -0
- package/esm/domain/profiling/transport/assembly.js +42 -0
- package/esm/domain/profiling/transport/assembly.js.map +1 -0
- package/esm/domain/profiling/transport/buildProfileEventAttributes.d.ts +25 -0
- package/esm/domain/profiling/transport/buildProfileEventAttributes.js +47 -0
- package/esm/domain/profiling/transport/buildProfileEventAttributes.js.map +1 -0
- package/esm/domain/profiling/types/index.d.ts +2 -0
- package/esm/domain/profiling/types/index.js +2 -0
- package/esm/domain/profiling/types/index.js.map +1 -0
- package/esm/domain/profiling/types/profilerApi.types.d.ts +58 -0
- package/esm/domain/profiling/types/profilerApi.types.js +4 -0
- package/esm/domain/profiling/types/profilerApi.types.js.map +1 -0
- package/esm/domain/profiling/types/rumProfiler.types.d.ts +72 -0
- package/esm/domain/profiling/types/rumProfiler.types.js +2 -0
- package/esm/domain/profiling/types/rumProfiler.types.js.map +1 -0
- package/esm/domain/profiling/utils/getCustomOrDefaultViewName.d.ts +1 -0
- package/esm/domain/profiling/utils/getCustomOrDefaultViewName.js +3 -0
- package/esm/domain/profiling/utils/getCustomOrDefaultViewName.js.map +1 -0
- package/esm/domain/profiling/utils/getDefaultViewName.d.ts +1 -0
- package/esm/domain/profiling/utils/getDefaultViewName.js +11 -0
- package/esm/domain/profiling/utils/getDefaultViewName.js.map +1 -0
- package/esm/domain/profiling/utils/getNumberOfSamples.d.ts +7 -0
- package/esm/domain/profiling/utils/getNumberOfSamples.js +15 -0
- package/esm/domain/profiling/utils/getNumberOfSamples.js.map +1 -0
- package/esm/domain/record/assembly.d.ts +2 -0
- package/esm/domain/record/assembly.js +13 -0
- package/esm/domain/record/assembly.js.map +1 -0
- package/esm/domain/record/elementsScrollPositions.d.ts +10 -0
- package/esm/domain/record/elementsScrollPositions.js +20 -0
- package/esm/domain/record/elementsScrollPositions.js.map +1 -0
- package/esm/domain/record/eventIds.d.ts +4 -0
- package/esm/domain/record/eventIds.js +13 -0
- package/esm/domain/record/eventIds.js.map +1 -0
- package/esm/domain/record/eventsUtils.d.ts +2 -0
- package/esm/domain/record/eventsUtils.js +11 -0
- package/esm/domain/record/eventsUtils.js.map +1 -0
- package/esm/domain/record/index.d.ts +7 -0
- package/esm/domain/record/index.js +6 -0
- package/esm/domain/record/index.js.map +1 -0
- package/esm/domain/record/internalApi.d.ts +22 -0
- package/esm/domain/record/internalApi.js +53 -0
- package/esm/domain/record/internalApi.js.map +1 -0
- package/esm/domain/record/mutationBatch.d.ts +12 -0
- package/esm/domain/record/mutationBatch.js +40 -0
- package/esm/domain/record/mutationBatch.js.map +1 -0
- package/esm/domain/record/nodeIds.d.ts +15 -0
- package/esm/domain/record/nodeIds.js +29 -0
- package/esm/domain/record/nodeIds.js.map +1 -0
- package/esm/domain/record/record.d.ts +16 -0
- package/esm/domain/record/record.js +54 -0
- package/esm/domain/record/record.js.map +1 -0
- package/esm/domain/record/record.types.d.ts +4 -0
- package/esm/domain/record/record.types.js +2 -0
- package/esm/domain/record/record.types.js.map +1 -0
- package/esm/domain/record/recordingScope.d.ts +19 -0
- package/esm/domain/record/recordingScope.js +10 -0
- package/esm/domain/record/recordingScope.js.map +1 -0
- package/esm/domain/record/serialization/index.d.ts +8 -0
- package/esm/domain/record/serialization/index.js +7 -0
- package/esm/domain/record/serialization/index.js.map +1 -0
- package/esm/domain/record/serialization/serialization.types.d.ts +28 -0
- package/esm/domain/record/serialization/serialization.types.js +2 -0
- package/esm/domain/record/serialization/serialization.types.js.map +1 -0
- package/esm/domain/record/serialization/serializationStats.d.ts +12 -0
- package/esm/domain/record/serialization/serializationStats.js +27 -0
- package/esm/domain/record/serialization/serializationStats.js.map +1 -0
- package/esm/domain/record/serialization/serializationTransaction.d.ts +45 -0
- package/esm/domain/record/serialization/serializationTransaction.js +35 -0
- package/esm/domain/record/serialization/serializationTransaction.js.map +1 -0
- package/esm/domain/record/serialization/serializationUtils.d.ts +18 -0
- package/esm/domain/record/serialization/serializationUtils.js +80 -0
- package/esm/domain/record/serialization/serializationUtils.js.map +1 -0
- package/esm/domain/record/serialization/serializeAttribute.d.ts +4 -0
- package/esm/domain/record/serialization/serializeAttribute.js +38 -0
- package/esm/domain/record/serialization/serializeAttribute.js.map +1 -0
- package/esm/domain/record/serialization/serializeAttributes.d.ts +7 -0
- package/esm/domain/record/serialization/serializeAttributes.js +161 -0
- package/esm/domain/record/serialization/serializeAttributes.js.map +1 -0
- package/esm/domain/record/serialization/serializeDocument.d.ts +3 -0
- package/esm/domain/record/serialization/serializeDocument.js +8 -0
- package/esm/domain/record/serialization/serializeDocument.js.map +1 -0
- package/esm/domain/record/serialization/serializeNode.d.ts +7 -0
- package/esm/domain/record/serialization/serializeNode.js +149 -0
- package/esm/domain/record/serialization/serializeNode.js.map +1 -0
- package/esm/domain/record/serialization/serializeStyleSheets.d.ts +2 -0
- package/esm/domain/record/serialization/serializeStyleSheets.js +16 -0
- package/esm/domain/record/serialization/serializeStyleSheets.js.map +1 -0
- package/esm/domain/record/shadowRootsController.d.ts +11 -0
- package/esm/domain/record/shadowRootsController.js +41 -0
- package/esm/domain/record/shadowRootsController.js.map +1 -0
- package/esm/domain/record/startFullSnapshots.d.ts +9 -0
- package/esm/domain/record/startFullSnapshots.js +55 -0
- package/esm/domain/record/startFullSnapshots.js.map +1 -0
- package/esm/domain/record/trackers/index.d.ts +12 -0
- package/esm/domain/record/trackers/index.js +12 -0
- package/esm/domain/record/trackers/index.js.map +1 -0
- package/esm/domain/record/trackers/trackFocus.d.ts +5 -0
- package/esm/domain/record/trackers/trackFocus.js +12 -0
- package/esm/domain/record/trackers/trackFocus.js.map +1 -0
- package/esm/domain/record/trackers/trackFrustration.d.ts +7 -0
- package/esm/domain/record/trackers/trackFrustration.js +28 -0
- package/esm/domain/record/trackers/trackFrustration.js.map +1 -0
- package/esm/domain/record/trackers/trackInput.d.ts +4 -0
- package/esm/domain/record/trackers/trackInput.js +101 -0
- package/esm/domain/record/trackers/trackInput.js.map +1 -0
- package/esm/domain/record/trackers/trackMediaInteraction.d.ts +5 -0
- package/esm/domain/record/trackers/trackMediaInteraction.js +26 -0
- package/esm/domain/record/trackers/trackMediaInteraction.js.map +1 -0
- package/esm/domain/record/trackers/trackMouseInteraction.d.ts +5 -0
- package/esm/domain/record/trackers/trackMouseInteraction.js +56 -0
- package/esm/domain/record/trackers/trackMouseInteraction.js.map +1 -0
- package/esm/domain/record/trackers/trackMove.d.ts +9 -0
- package/esm/domain/record/trackers/trackMove.js +51 -0
- package/esm/domain/record/trackers/trackMove.js.map +1 -0
- package/esm/domain/record/trackers/trackMutation.d.ts +11 -0
- package/esm/domain/record/trackers/trackMutation.js +266 -0
- package/esm/domain/record/trackers/trackMutation.js.map +1 -0
- package/esm/domain/record/trackers/trackScroll.d.ts +5 -0
- package/esm/domain/record/trackers/trackScroll.js +45 -0
- package/esm/domain/record/trackers/trackScroll.js.map +1 -0
- package/esm/domain/record/trackers/trackStyleSheet.d.ts +6 -0
- package/esm/domain/record/trackers/trackStyleSheet.js +85 -0
- package/esm/domain/record/trackers/trackStyleSheet.js.map +1 -0
- package/esm/domain/record/trackers/trackViewEnd.d.ts +5 -0
- package/esm/domain/record/trackers/trackViewEnd.js +17 -0
- package/esm/domain/record/trackers/trackViewEnd.js.map +1 -0
- package/esm/domain/record/trackers/trackViewportResize.d.ts +6 -0
- package/esm/domain/record/trackers/trackViewportResize.js +42 -0
- package/esm/domain/record/trackers/trackViewportResize.js.map +1 -0
- package/esm/domain/record/trackers/tracker.types.d.ts +3 -0
- package/esm/domain/record/trackers/tracker.types.js +2 -0
- package/esm/domain/record/trackers/tracker.types.js.map +1 -0
- package/esm/domain/record/viewports.d.ts +20 -0
- package/esm/domain/record/viewports.js +55 -0
- package/esm/domain/record/viewports.js.map +1 -0
- package/esm/domain/replayStats.d.ts +8 -0
- package/esm/domain/replayStats.js +51 -0
- package/esm/domain/replayStats.js.map +1 -0
- package/esm/domain/scriptLoadingError.d.ts +6 -0
- package/esm/domain/scriptLoadingError.js +23 -0
- package/esm/domain/scriptLoadingError.js.map +1 -0
- package/esm/domain/segmentCollection/buildReplayPayload.d.ts +15 -0
- package/esm/domain/segmentCollection/buildReplayPayload.js +23 -0
- package/esm/domain/segmentCollection/buildReplayPayload.js.map +1 -0
- package/esm/domain/segmentCollection/index.d.ts +4 -0
- package/esm/domain/segmentCollection/index.js +4 -0
- package/esm/domain/segmentCollection/index.js.map +1 -0
- package/esm/domain/segmentCollection/segment.d.ts +16 -0
- package/esm/domain/segmentCollection/segment.js +46 -0
- package/esm/domain/segmentCollection/segment.js.map +1 -0
- package/esm/domain/segmentCollection/segmentCollection.d.ts +31 -0
- package/esm/domain/segmentCollection/segmentCollection.js +106 -0
- package/esm/domain/segmentCollection/segmentCollection.js.map +1 -0
- package/esm/domain/segmentCollection/startSegmentTelemetry.d.ts +6 -0
- package/esm/domain/segmentCollection/startSegmentTelemetry.js +44 -0
- package/esm/domain/segmentCollection/startSegmentTelemetry.js.map +1 -0
- package/esm/domain/startRecordBridge.d.ts +5 -0
- package/esm/domain/startRecordBridge.js +14 -0
- package/esm/domain/startRecordBridge.js.map +1 -0
- package/esm/domain/startRecorderInitTelemetry.d.ts +15 -0
- package/esm/domain/startRecorderInitTelemetry.js +52 -0
- package/esm/domain/startRecorderInitTelemetry.js.map +1 -0
- package/esm/entries/internal.d.ts +11 -0
- package/esm/entries/internal.js +4 -0
- package/esm/entries/internal.js.map +1 -0
- package/esm/entries/internalSynthetics.d.ts +2 -0
- package/esm/entries/internalSynthetics.js +23 -0
- package/esm/entries/internalSynthetics.js.map +1 -0
- package/esm/entries/main.d.ts +23 -0
- package/esm/entries/main.js +31 -0
- package/esm/entries/main.js.map +1 -0
- package/esm/types/index.d.ts +2 -0
- package/esm/types/index.js +2 -0
- package/esm/types/index.js.map +1 -0
- package/esm/types/sessionReplay.d.ts +703 -0
- package/esm/types/sessionReplay.js +6 -0
- package/esm/types/sessionReplay.js.map +1 -0
- package/esm/types/sessionReplayConstants.d.ts +49 -0
- package/esm/types/sessionReplayConstants.js +46 -0
- package/esm/types/sessionReplayConstants.js.map +1 -0
- package/internal/package.json +6 -0
- package/internal-synthetics/package.json +6 -0
- package/package.json +40 -0
- package/src/boot/isBrowserSupported.ts +14 -0
- package/src/boot/lazyLoadProfiler.ts +21 -0
- package/src/boot/lazyLoadRecorder.ts +21 -0
- package/src/boot/postStartStrategy.ts +176 -0
- package/src/boot/preStartStrategy.ts +34 -0
- package/src/boot/profilerApi.ts +86 -0
- package/src/boot/recorderApi.ts +124 -0
- package/src/boot/startRecording.ts +70 -0
- package/src/domain/deflate/deflateEncoder.ts +144 -0
- package/src/domain/deflate/deflateWorker.ts +157 -0
- package/src/domain/deflate/index.ts +8 -0
- package/src/domain/getSessionReplayLink.ts +40 -0
- package/src/domain/profiling/profiler.ts +338 -0
- package/src/domain/profiling/profilingContext.ts +34 -0
- package/src/domain/profiling/profilingSupported.ts +10 -0
- package/src/domain/profiling/test-utils/mockedTrace.ts +58 -0
- package/src/domain/profiling/transport/assembly.ts +78 -0
- package/src/domain/profiling/transport/buildProfileEventAttributes.ts +66 -0
- package/src/domain/profiling/types/index.ts +2 -0
- package/src/domain/profiling/types/profilerApi.types.ts +87 -0
- package/src/domain/profiling/types/rumProfiler.types.ts +81 -0
- package/src/domain/profiling/utils/getCustomOrDefaultViewName.ts +4 -0
- package/src/domain/profiling/utils/getDefaultViewName.ts +12 -0
- package/src/domain/profiling/utils/getNumberOfSamples.ts +16 -0
- package/src/domain/record/assembly.ts +17 -0
- package/src/domain/record/elementsScrollPositions.ts +28 -0
- package/src/domain/record/eventIds.ts +17 -0
- package/src/domain/record/eventsUtils.ts +12 -0
- package/src/domain/record/index.ts +7 -0
- package/src/domain/record/internalApi.ts +88 -0
- package/src/domain/record/mutationBatch.ts +47 -0
- package/src/domain/record/nodeIds.ts +46 -0
- package/src/domain/record/record.ts +98 -0
- package/src/domain/record/record.types.ts +5 -0
- package/src/domain/record/recordingScope.ts +36 -0
- package/src/domain/record/serialization/index.ts +8 -0
- package/src/domain/record/serialization/serialization.types.ts +43 -0
- package/src/domain/record/serialization/serializationStats.ts +43 -0
- package/src/domain/record/serialization/serializationTransaction.ts +94 -0
- package/src/domain/record/serialization/serializationUtils.ts +103 -0
- package/src/domain/record/serialization/serializeAttribute.ts +55 -0
- package/src/domain/record/serialization/serializeAttributes.ts +194 -0
- package/src/domain/record/serialization/serializeDocument.ts +13 -0
- package/src/domain/record/serialization/serializeNode.ts +229 -0
- package/src/domain/record/serialization/serializeStyleSheets.ts +18 -0
- package/src/domain/record/shadowRootsController.ts +62 -0
- package/src/domain/record/startFullSnapshots.ts +84 -0
- package/src/domain/record/trackers/index.ts +12 -0
- package/src/domain/record/trackers/trackFocus.ts +16 -0
- package/src/domain/record/trackers/trackFrustration.ts +41 -0
- package/src/domain/record/trackers/trackInput.ts +128 -0
- package/src/domain/record/trackers/trackMediaInteraction.ts +43 -0
- package/src/domain/record/trackers/trackMouseInteraction.ts +74 -0
- package/src/domain/record/trackers/trackMove.ts +78 -0
- package/src/domain/record/trackers/trackMutation.ts +399 -0
- package/src/domain/record/trackers/trackScroll.ts +61 -0
- package/src/domain/record/trackers/trackStyleSheet.ts +117 -0
- package/src/domain/record/trackers/trackViewEnd.ts +27 -0
- package/src/domain/record/trackers/trackViewportResize.ts +69 -0
- package/src/domain/record/trackers/tracker.types.ts +3 -0
- package/src/domain/record/viewports.ts +68 -0
- package/src/domain/replayStats.ts +61 -0
- package/src/domain/scriptLoadingError.ts +36 -0
- package/src/domain/segmentCollection/buildReplayPayload.ts +52 -0
- package/src/domain/segmentCollection/index.ts +4 -0
- package/src/domain/segmentCollection/segment.ts +78 -0
- package/src/domain/segmentCollection/segmentCollection.ts +200 -0
- package/src/domain/segmentCollection/startSegmentTelemetry.ts +82 -0
- package/src/domain/startRecordBridge.ts +17 -0
- package/src/domain/startRecorderInitTelemetry.ts +90 -0
- package/src/entries/internal.ts +18 -0
- package/src/entries/internalSynthetics.ts +24 -0
- package/src/entries/main.ts +95 -0
- package/src/types/index.ts +2 -0
- package/src/types/sessionReplay.ts +734 -0
- package/src/types/sessionReplayConstants.ts +86 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { elapsed, timeStampNow } from '@kubesense/kubesense-browser-core'
|
|
2
|
+
|
|
3
|
+
import type { BrowserRecord } from '../../../types'
|
|
4
|
+
import type { NodeId } from '../nodeIds'
|
|
5
|
+
import type { EmitRecordCallback, EmitStatsCallback } from '../record.types'
|
|
6
|
+
import type { RecordingScope } from '../recordingScope'
|
|
7
|
+
import type { SerializationStats } from './serializationStats'
|
|
8
|
+
import { createSerializationStats, updateSerializationStats } from './serializationStats'
|
|
9
|
+
|
|
10
|
+
export type SerializationTransactionCallback = (transaction: SerializationTransaction) => void
|
|
11
|
+
|
|
12
|
+
export const enum SerializationKind {
|
|
13
|
+
INITIAL_FULL_SNAPSHOT,
|
|
14
|
+
SUBSEQUENT_FULL_SNAPSHOT,
|
|
15
|
+
INCREMENTAL_SNAPSHOT,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A serialization transaction is used to build and emit a sequence of session replay
|
|
20
|
+
* records containing a serialized snapshot of the DOM.
|
|
21
|
+
*/
|
|
22
|
+
export interface SerializationTransaction {
|
|
23
|
+
/** Add a record to the transaction. It will be emitted when the transaction ends. */
|
|
24
|
+
add(record: BrowserRecord): void
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Add a metric to the transaction's statistics. The aggregated statistics will be
|
|
28
|
+
* emitted when the transaction ends.
|
|
29
|
+
*/
|
|
30
|
+
addMetric(metric: keyof SerializationStats, value: number): void
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Assign and return an id to the given node. If the node has previously been assigned
|
|
34
|
+
* an id, the existing id will be reused.
|
|
35
|
+
*/
|
|
36
|
+
assignId(node: Node): NodeId
|
|
37
|
+
|
|
38
|
+
/** The kind of serialization being performed in this transaction. */
|
|
39
|
+
kind: SerializationKind
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A set used to track nodes which have been serialized in the current transaction. If
|
|
43
|
+
* undefined, this feature is disabled; this is the default state in new transactions
|
|
44
|
+
* for performance reasons. Set the property to a non-undefined value if you need this
|
|
45
|
+
* capability.
|
|
46
|
+
*/
|
|
47
|
+
serializedNodeIds?: Set<NodeId>
|
|
48
|
+
|
|
49
|
+
/** The recording scope in which this transaction is occurring. */
|
|
50
|
+
scope: RecordingScope
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Perform serialization within a transaction. At the end of the transaction, the
|
|
55
|
+
* generated records and statistics will be emitted.
|
|
56
|
+
*/
|
|
57
|
+
export function serializeInTransaction(
|
|
58
|
+
kind: SerializationKind,
|
|
59
|
+
emitRecord: EmitRecordCallback,
|
|
60
|
+
emitStats: EmitStatsCallback,
|
|
61
|
+
scope: RecordingScope,
|
|
62
|
+
serialize: SerializationTransactionCallback
|
|
63
|
+
): void {
|
|
64
|
+
const records: BrowserRecord[] = []
|
|
65
|
+
const stats = createSerializationStats()
|
|
66
|
+
|
|
67
|
+
const transaction: SerializationTransaction = {
|
|
68
|
+
add(record: BrowserRecord): void {
|
|
69
|
+
records.push(record)
|
|
70
|
+
},
|
|
71
|
+
addMetric(metric: keyof SerializationStats, value: number): void {
|
|
72
|
+
updateSerializationStats(stats, metric, value)
|
|
73
|
+
},
|
|
74
|
+
assignId(node: Node): NodeId {
|
|
75
|
+
const id = scope.nodeIds.assign(node)
|
|
76
|
+
if (transaction.serializedNodeIds) {
|
|
77
|
+
transaction.serializedNodeIds.add(id)
|
|
78
|
+
}
|
|
79
|
+
return id
|
|
80
|
+
},
|
|
81
|
+
kind,
|
|
82
|
+
scope,
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const start = timeStampNow()
|
|
86
|
+
serialize(transaction)
|
|
87
|
+
updateSerializationStats(stats, 'serializationDuration', elapsed(start, timeStampNow()))
|
|
88
|
+
|
|
89
|
+
for (const record of records) {
|
|
90
|
+
emitRecord(record)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
emitStats(stats)
|
|
94
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { buildUrl } from '@kubesense/kubesense-browser-core'
|
|
2
|
+
import { CENSORED_STRING_MARK, shouldMaskNode } from '@kubesense/kubesense-browser-rum-core'
|
|
3
|
+
import type { NodePrivacyLevel } from '@kubesense/kubesense-browser-rum-core'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get the element "value" to be serialized as an attribute or an input update record. It respects
|
|
7
|
+
* the input privacy mode of the element.
|
|
8
|
+
* PERFROMANCE OPTIMIZATION: Assumes that privacy level `HIDDEN` is never encountered because of earlier checks.
|
|
9
|
+
*/
|
|
10
|
+
export function getElementInputValue(element: Element, nodePrivacyLevel: NodePrivacyLevel) {
|
|
11
|
+
/*
|
|
12
|
+
BROWSER SPEC NOTE: <input>, <select>
|
|
13
|
+
For some <input> elements, the `value` is an exceptional property/attribute that has the
|
|
14
|
+
value synced between el.value and el.getAttribute()
|
|
15
|
+
input[type=button,checkbox,hidden,image,radio,reset,submit]
|
|
16
|
+
*/
|
|
17
|
+
const tagName = element.tagName
|
|
18
|
+
const value = (element as HTMLInputElement | HTMLTextAreaElement).value
|
|
19
|
+
|
|
20
|
+
if (shouldMaskNode(element, nodePrivacyLevel)) {
|
|
21
|
+
const type = (element as HTMLInputElement | HTMLTextAreaElement).type
|
|
22
|
+
if (tagName === 'INPUT' && (type === 'button' || type === 'submit' || type === 'reset')) {
|
|
23
|
+
// Overrule `MASK` privacy level for button-like element values, as they are used during replay
|
|
24
|
+
// to display their label. They can still be hidden via the "hidden" privacy attribute or class name.
|
|
25
|
+
return value
|
|
26
|
+
} else if (!value || tagName === 'OPTION') {
|
|
27
|
+
// <Option> value provides no benefit
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
return CENSORED_STRING_MARK
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (tagName === 'OPTION' || tagName === 'SELECT') {
|
|
34
|
+
return (element as HTMLOptionElement | HTMLSelectElement).value
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (tagName !== 'INPUT' && tagName !== 'TEXTAREA') {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return value
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const URL_IN_CSS_REF = /url\((?:(')([^']*)'|(")([^"]*)"|([^)]*))\)/gm
|
|
45
|
+
export const ABSOLUTE_URL = /^[A-Za-z]+:|^\/\//
|
|
46
|
+
export const DATA_URI = /^["']?data:.*,/i
|
|
47
|
+
|
|
48
|
+
export function switchToAbsoluteUrl(cssText: string, cssHref: string | null): string {
|
|
49
|
+
return cssText.replace(
|
|
50
|
+
URL_IN_CSS_REF,
|
|
51
|
+
(
|
|
52
|
+
matchingSubstring: string,
|
|
53
|
+
singleQuote: string | undefined,
|
|
54
|
+
urlWrappedInSingleQuotes: string | undefined,
|
|
55
|
+
doubleQuote: string | undefined,
|
|
56
|
+
urlWrappedInDoubleQuotes: string | undefined,
|
|
57
|
+
urlNotWrappedInQuotes: string | undefined
|
|
58
|
+
) => {
|
|
59
|
+
const url = urlWrappedInSingleQuotes || urlWrappedInDoubleQuotes || urlNotWrappedInQuotes
|
|
60
|
+
|
|
61
|
+
if (!cssHref || !url || ABSOLUTE_URL.test(url) || DATA_URI.test(url)) {
|
|
62
|
+
return matchingSubstring
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const quote = singleQuote || doubleQuote || ''
|
|
66
|
+
return `url(${quote}${makeUrlAbsolute(url, cssHref)}${quote})`
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function makeUrlAbsolute(url: string, baseUrl: string): string {
|
|
72
|
+
try {
|
|
73
|
+
return buildUrl(url, baseUrl).href
|
|
74
|
+
} catch {
|
|
75
|
+
return url
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const TAG_NAME_REGEX = /[^a-z1-6-_]/
|
|
80
|
+
export function getValidTagName(tagName: string): string {
|
|
81
|
+
const processedTagName = tagName.toLowerCase().trim()
|
|
82
|
+
|
|
83
|
+
if (TAG_NAME_REGEX.test(processedTagName)) {
|
|
84
|
+
// if the tag name is odd and we cannot extract
|
|
85
|
+
// anything from the string, then we return a
|
|
86
|
+
// generic div
|
|
87
|
+
return 'div'
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return processedTagName
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Returns the tag name of the given element, normalized to ensure a consistent lowercase
|
|
95
|
+
* representation regardless of whether the element is HTML, XHTML, or SVG.
|
|
96
|
+
*/
|
|
97
|
+
export function normalizedTagName(element: Element): string {
|
|
98
|
+
return element.tagName.toLowerCase()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function censoredImageForSize(width: number, height: number) {
|
|
102
|
+
return `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='${width}' height='${height}' style='background-color:silver'%3E%3C/svg%3E`
|
|
103
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NodePrivacyLevel,
|
|
3
|
+
CENSORED_STRING_MARK,
|
|
4
|
+
CENSORED_IMG_MARK,
|
|
5
|
+
sanitizeIfLongDataUrl,
|
|
6
|
+
shouldMaskAttribute,
|
|
7
|
+
} from '@kubesense/kubesense-browser-rum-core'
|
|
8
|
+
import type { RumConfiguration } from '@kubesense/kubesense-browser-rum-core'
|
|
9
|
+
import { censoredImageForSize } from './serializationUtils'
|
|
10
|
+
|
|
11
|
+
// TODO: temporarily bump the Session Replay limit to 1Mb for dataUrls
|
|
12
|
+
// This limit should be removed after [PANA-2843] is implemented
|
|
13
|
+
export const MAX_ATTRIBUTE_VALUE_CHAR_LENGTH = 1_000_000
|
|
14
|
+
|
|
15
|
+
export function serializeAttribute(
|
|
16
|
+
element: Element,
|
|
17
|
+
nodePrivacyLevel: NodePrivacyLevel,
|
|
18
|
+
attributeName: string,
|
|
19
|
+
configuration: RumConfiguration
|
|
20
|
+
): string | null {
|
|
21
|
+
if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {
|
|
22
|
+
// dup condition for direct access case
|
|
23
|
+
return null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const attributeValue = element.getAttribute(attributeName)
|
|
27
|
+
const tagName = element.tagName
|
|
28
|
+
if (shouldMaskAttribute(tagName, attributeName, attributeValue, nodePrivacyLevel, configuration)) {
|
|
29
|
+
// mask image URLs
|
|
30
|
+
if (tagName === 'IMG') {
|
|
31
|
+
// generate image with similar dimension than the original to have the same rendering behaviour
|
|
32
|
+
const image = element as HTMLImageElement
|
|
33
|
+
if (image.naturalWidth > 0) {
|
|
34
|
+
return censoredImageForSize(image.naturalWidth, image.naturalHeight)
|
|
35
|
+
}
|
|
36
|
+
const { width, height } = element.getBoundingClientRect()
|
|
37
|
+
if (width > 0 || height > 0) {
|
|
38
|
+
return censoredImageForSize(width, height)
|
|
39
|
+
}
|
|
40
|
+
// if we can't get the image size, fallback to the censored image
|
|
41
|
+
return CENSORED_IMG_MARK
|
|
42
|
+
}
|
|
43
|
+
if (tagName === 'SOURCE') {
|
|
44
|
+
return CENSORED_IMG_MARK
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return CENSORED_STRING_MARK
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!attributeValue) {
|
|
51
|
+
return attributeValue
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return sanitizeIfLongDataUrl(attributeValue, MAX_ATTRIBUTE_VALUE_CHAR_LENGTH)
|
|
55
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { NodePrivacyLevel, shouldMaskNode } from '@kubesense/kubesense-browser-rum-core'
|
|
2
|
+
import { isSafari } from '@kubesense/kubesense-browser-core'
|
|
3
|
+
import { getElementInputValue, normalizedTagName, switchToAbsoluteUrl } from './serializationUtils'
|
|
4
|
+
import { serializeAttribute } from './serializeAttribute'
|
|
5
|
+
import type { SerializationTransaction } from './serializationTransaction'
|
|
6
|
+
import { SerializationKind } from './serializationTransaction'
|
|
7
|
+
import type { VirtualAttributes } from './serialization.types'
|
|
8
|
+
|
|
9
|
+
export function serializeAttributes(
|
|
10
|
+
element: Element,
|
|
11
|
+
nodePrivacyLevel: NodePrivacyLevel,
|
|
12
|
+
transaction: SerializationTransaction
|
|
13
|
+
): Record<string, number | string> {
|
|
14
|
+
return {
|
|
15
|
+
...serializeDOMAttributes(element, nodePrivacyLevel, transaction),
|
|
16
|
+
...serializeVirtualAttributes(element, nodePrivacyLevel, transaction),
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function serializeDOMAttributes(
|
|
21
|
+
element: Element,
|
|
22
|
+
nodePrivacyLevel: NodePrivacyLevel,
|
|
23
|
+
transaction: SerializationTransaction
|
|
24
|
+
): Record<string, string> {
|
|
25
|
+
if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {
|
|
26
|
+
return {}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const attrs: Record<string, string> = {}
|
|
30
|
+
const tagName = normalizedTagName(element)
|
|
31
|
+
|
|
32
|
+
for (let i = 0; i < element.attributes.length; i += 1) {
|
|
33
|
+
const attribute = element.attributes.item(i)!
|
|
34
|
+
const attributeName = attribute.name
|
|
35
|
+
const attributeValue = serializeAttribute(element, nodePrivacyLevel, attributeName, transaction.scope.configuration)
|
|
36
|
+
if (attributeValue !== null) {
|
|
37
|
+
attrs[attributeName] = attributeValue
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (
|
|
42
|
+
(element as HTMLInputElement).value &&
|
|
43
|
+
(tagName === 'textarea' || tagName === 'select' || tagName === 'option' || tagName === 'input')
|
|
44
|
+
) {
|
|
45
|
+
const formValue = getElementInputValue(element, nodePrivacyLevel)
|
|
46
|
+
if (formValue !== undefined) {
|
|
47
|
+
attrs.value = formValue
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* <Option> can be selected, which occurs if its `value` matches ancestor `<Select>.value`
|
|
53
|
+
*/
|
|
54
|
+
if (tagName === 'option') {
|
|
55
|
+
const optionElement = element as HTMLOptionElement
|
|
56
|
+
if (optionElement.selected && !shouldMaskNode(optionElement, nodePrivacyLevel)) {
|
|
57
|
+
attrs.selected = ''
|
|
58
|
+
} else {
|
|
59
|
+
delete attrs.selected
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Forms: input[type=checkbox,radio]
|
|
65
|
+
* The `checked` property for <input> is a little bit special:
|
|
66
|
+
* 1. el.checked is a setter that returns if truthy.
|
|
67
|
+
* 2. getAttribute returns the string value
|
|
68
|
+
* getAttribute('checked') does not sync with `Element.checked`, so use JS property
|
|
69
|
+
* NOTE: `checked` property exists on `HTMLInputElement`. For serializer assumptions, we check for type=radio|check.
|
|
70
|
+
*/
|
|
71
|
+
const inputElement = element as HTMLInputElement
|
|
72
|
+
if (tagName === 'input' && (inputElement.type === 'radio' || inputElement.type === 'checkbox')) {
|
|
73
|
+
if (inputElement.checked && !shouldMaskNode(inputElement, nodePrivacyLevel)) {
|
|
74
|
+
attrs.checked = ''
|
|
75
|
+
} else {
|
|
76
|
+
delete attrs.checked
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return attrs
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function serializeVirtualAttributes(
|
|
84
|
+
element: Element,
|
|
85
|
+
nodePrivacyLevel: NodePrivacyLevel,
|
|
86
|
+
transaction: SerializationTransaction
|
|
87
|
+
): VirtualAttributes {
|
|
88
|
+
if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {
|
|
89
|
+
return {}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const attrs: VirtualAttributes = {}
|
|
93
|
+
const doc = element.ownerDocument
|
|
94
|
+
const tagName = normalizedTagName(element)
|
|
95
|
+
|
|
96
|
+
// remote css
|
|
97
|
+
if (tagName === 'link') {
|
|
98
|
+
const stylesheet = Array.from(doc.styleSheets).find((s) => s.href === (element as HTMLLinkElement).href)
|
|
99
|
+
const cssText = getCssRulesString(stylesheet)
|
|
100
|
+
if (cssText && stylesheet) {
|
|
101
|
+
transaction.addMetric('cssText', cssText.length)
|
|
102
|
+
attrs._cssText = cssText
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// dynamic stylesheet
|
|
107
|
+
if (tagName === 'style' && (element as HTMLStyleElement).sheet) {
|
|
108
|
+
const cssText = getCssRulesString((element as HTMLStyleElement).sheet)
|
|
109
|
+
if (cssText) {
|
|
110
|
+
transaction.addMetric('cssText', cssText.length)
|
|
111
|
+
attrs._cssText = cssText
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Serialize the media playback state
|
|
117
|
+
*/
|
|
118
|
+
if (tagName === 'audio' || tagName === 'video') {
|
|
119
|
+
const mediaElement = element as HTMLMediaElement
|
|
120
|
+
attrs.rr_mediaState = mediaElement.paused ? 'paused' : 'played'
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Serialize the scroll state for each element only for full snapshot
|
|
125
|
+
*/
|
|
126
|
+
let scrollTop: number | undefined
|
|
127
|
+
let scrollLeft: number | undefined
|
|
128
|
+
switch (transaction.kind) {
|
|
129
|
+
case SerializationKind.INITIAL_FULL_SNAPSHOT:
|
|
130
|
+
scrollTop = Math.round(element.scrollTop)
|
|
131
|
+
scrollLeft = Math.round(element.scrollLeft)
|
|
132
|
+
if (scrollTop || scrollLeft) {
|
|
133
|
+
transaction.scope.elementsScrollPositions.set(element, { scrollTop, scrollLeft })
|
|
134
|
+
}
|
|
135
|
+
break
|
|
136
|
+
case SerializationKind.SUBSEQUENT_FULL_SNAPSHOT:
|
|
137
|
+
if (transaction.scope.elementsScrollPositions.has(element)) {
|
|
138
|
+
;({ scrollTop, scrollLeft } = transaction.scope.elementsScrollPositions.get(element)!)
|
|
139
|
+
}
|
|
140
|
+
break
|
|
141
|
+
}
|
|
142
|
+
if (scrollLeft) {
|
|
143
|
+
attrs.rr_scrollLeft = scrollLeft
|
|
144
|
+
}
|
|
145
|
+
if (scrollTop) {
|
|
146
|
+
attrs.rr_scrollTop = scrollTop
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return attrs
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function getCssRulesString(cssStyleSheet: CSSStyleSheet | undefined | null): string | null {
|
|
153
|
+
if (!cssStyleSheet) {
|
|
154
|
+
return null
|
|
155
|
+
}
|
|
156
|
+
let rules: CSSRuleList | undefined
|
|
157
|
+
try {
|
|
158
|
+
rules = cssStyleSheet.rules || cssStyleSheet.cssRules
|
|
159
|
+
} catch {
|
|
160
|
+
// if css is protected by CORS we cannot access cssRules see: https://www.w3.org/TR/cssom-1/#the-cssstylesheet-interface
|
|
161
|
+
}
|
|
162
|
+
if (!rules) {
|
|
163
|
+
return null
|
|
164
|
+
}
|
|
165
|
+
const styleSheetCssText = Array.from(rules, isSafari() ? getCssRuleStringForSafari : getCssRuleString).join('')
|
|
166
|
+
return switchToAbsoluteUrl(styleSheetCssText, cssStyleSheet.href)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function getCssRuleStringForSafari(rule: CSSRule): string {
|
|
170
|
+
// Safari does not escape attribute selectors containing : properly
|
|
171
|
+
// https://bugs.webkit.org/show_bug.cgi?id=184604
|
|
172
|
+
if (isCSSStyleRule(rule) && rule.selectorText.includes(':')) {
|
|
173
|
+
// This regex replaces [foo:bar] by [foo\\:bar]
|
|
174
|
+
const escapeColon = /(\[[\w-]+[^\\])(:[^\]]+\])/g
|
|
175
|
+
return rule.cssText.replace(escapeColon, '$1\\$2')
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return getCssRuleString(rule)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function getCssRuleString(rule: CSSRule): string {
|
|
182
|
+
// If it's an @import rule, try to inline sub-rules recursively with `getCssRulesString`. This
|
|
183
|
+
// operation can fail if the imported stylesheet is protected by CORS, in which case we fallback
|
|
184
|
+
// to the @import rule CSS text.
|
|
185
|
+
return (isCSSImportRule(rule) && getCssRulesString(rule.styleSheet)) || rule.cssText
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function isCSSImportRule(rule: CSSRule): rule is CSSImportRule {
|
|
189
|
+
return 'styleSheet' in rule
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function isCSSStyleRule(rule: CSSRule): rule is CSSStyleRule {
|
|
193
|
+
return 'selectorText' in rule
|
|
194
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DocumentNode, SerializedNodeWithId } from '../../../types'
|
|
2
|
+
import { serializeNode } from './serializeNode'
|
|
3
|
+
import type { SerializationTransaction } from './serializationTransaction'
|
|
4
|
+
|
|
5
|
+
export function serializeDocument(
|
|
6
|
+
document: Document,
|
|
7
|
+
transaction: SerializationTransaction
|
|
8
|
+
): DocumentNode & SerializedNodeWithId {
|
|
9
|
+
const defaultPrivacyLevel = transaction.scope.configuration.defaultPrivacyLevel
|
|
10
|
+
const serializedNode = serializeNode(document, defaultPrivacyLevel, transaction)
|
|
11
|
+
// We are sure that Documents are never ignored, so this function never returns null
|
|
12
|
+
return serializedNode as DocumentNode & SerializedNodeWithId
|
|
13
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import {
|
|
2
|
+
reducePrivacyLevel,
|
|
3
|
+
getNodeSelfPrivacyLevel,
|
|
4
|
+
getTextContent,
|
|
5
|
+
isNodeShadowRoot,
|
|
6
|
+
hasChildNodes,
|
|
7
|
+
forEachChildNodes,
|
|
8
|
+
NodePrivacyLevel,
|
|
9
|
+
PRIVACY_ATTR_NAME,
|
|
10
|
+
PRIVACY_ATTR_VALUE_HIDDEN,
|
|
11
|
+
} from '@kubesense/kubesense-browser-rum-core'
|
|
12
|
+
import type {
|
|
13
|
+
DocumentFragmentNode,
|
|
14
|
+
DocumentNode,
|
|
15
|
+
SerializedNodeWithId,
|
|
16
|
+
CDataNode,
|
|
17
|
+
DocumentTypeNode,
|
|
18
|
+
ElementNode,
|
|
19
|
+
TextNode,
|
|
20
|
+
} from '../../../types'
|
|
21
|
+
import { NodeType } from '../../../types'
|
|
22
|
+
import { getValidTagName } from './serializationUtils'
|
|
23
|
+
import type { ParentNodePrivacyLevel } from './serialization.types'
|
|
24
|
+
import { serializeStyleSheets } from './serializeStyleSheets'
|
|
25
|
+
import { serializeAttributes } from './serializeAttributes'
|
|
26
|
+
import type { SerializationTransaction } from './serializationTransaction'
|
|
27
|
+
|
|
28
|
+
export function serializeNode(
|
|
29
|
+
node: Element,
|
|
30
|
+
parentNodePrivacyLevel: ParentNodePrivacyLevel,
|
|
31
|
+
transaction: SerializationTransaction
|
|
32
|
+
): (SerializedNodeWithId & ElementNode) | null
|
|
33
|
+
export function serializeNode(
|
|
34
|
+
node: Node,
|
|
35
|
+
parentNodePrivacyLevel: ParentNodePrivacyLevel,
|
|
36
|
+
transaction: SerializationTransaction
|
|
37
|
+
): SerializedNodeWithId | null
|
|
38
|
+
export function serializeNode(
|
|
39
|
+
node: Node,
|
|
40
|
+
parentNodePrivacyLevel: ParentNodePrivacyLevel,
|
|
41
|
+
transaction: SerializationTransaction
|
|
42
|
+
): SerializedNodeWithId | null {
|
|
43
|
+
switch (node.nodeType) {
|
|
44
|
+
case node.DOCUMENT_NODE:
|
|
45
|
+
return serializeDocumentNode(node as Document, parentNodePrivacyLevel, transaction)
|
|
46
|
+
case node.DOCUMENT_FRAGMENT_NODE:
|
|
47
|
+
return serializeDocumentFragmentNode(node as DocumentFragment, parentNodePrivacyLevel, transaction)
|
|
48
|
+
case node.DOCUMENT_TYPE_NODE:
|
|
49
|
+
return serializeDocumentTypeNode(node as DocumentType, transaction)
|
|
50
|
+
case node.ELEMENT_NODE:
|
|
51
|
+
return serializeElementNode(node as Element, parentNodePrivacyLevel, transaction)
|
|
52
|
+
case node.TEXT_NODE:
|
|
53
|
+
return serializeTextNode(node as Text, parentNodePrivacyLevel, transaction)
|
|
54
|
+
case node.CDATA_SECTION_NODE:
|
|
55
|
+
return serializeCDataNode(node as CDATASection, transaction)
|
|
56
|
+
default:
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function serializeChildNodes(
|
|
62
|
+
node: Node,
|
|
63
|
+
parentNodePrivacyLevel: ParentNodePrivacyLevel,
|
|
64
|
+
transaction: SerializationTransaction
|
|
65
|
+
): SerializedNodeWithId[] {
|
|
66
|
+
const result: SerializedNodeWithId[] = []
|
|
67
|
+
forEachChildNodes(node, (childNode) => {
|
|
68
|
+
const serializedChildNode = serializeNode(childNode, parentNodePrivacyLevel, transaction)
|
|
69
|
+
if (serializedChildNode) {
|
|
70
|
+
result.push(serializedChildNode)
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
return result
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function serializeDocumentNode(
|
|
77
|
+
document: Document,
|
|
78
|
+
parentNodePrivacyLevel: ParentNodePrivacyLevel,
|
|
79
|
+
transaction: SerializationTransaction
|
|
80
|
+
): DocumentNode & SerializedNodeWithId {
|
|
81
|
+
return {
|
|
82
|
+
type: NodeType.Document,
|
|
83
|
+
id: transaction.assignId(document),
|
|
84
|
+
childNodes: serializeChildNodes(document, parentNodePrivacyLevel, transaction),
|
|
85
|
+
adoptedStyleSheets: serializeStyleSheets(document.adoptedStyleSheets),
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function serializeDocumentFragmentNode(
|
|
90
|
+
element: DocumentFragment,
|
|
91
|
+
parentNodePrivacyLevel: ParentNodePrivacyLevel,
|
|
92
|
+
transaction: SerializationTransaction
|
|
93
|
+
): DocumentFragmentNode & SerializedNodeWithId {
|
|
94
|
+
const isShadowRoot = isNodeShadowRoot(element)
|
|
95
|
+
if (isShadowRoot) {
|
|
96
|
+
transaction.scope.shadowRootsController.addShadowRoot(element, transaction.scope)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
type: NodeType.DocumentFragment,
|
|
101
|
+
id: transaction.assignId(element),
|
|
102
|
+
childNodes: serializeChildNodes(element, parentNodePrivacyLevel, transaction),
|
|
103
|
+
isShadowRoot,
|
|
104
|
+
adoptedStyleSheets: isShadowRoot ? serializeStyleSheets(element.adoptedStyleSheets) : undefined,
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function serializeDocumentTypeNode(
|
|
109
|
+
documentType: DocumentType,
|
|
110
|
+
transaction: SerializationTransaction
|
|
111
|
+
): DocumentTypeNode & SerializedNodeWithId {
|
|
112
|
+
return {
|
|
113
|
+
type: NodeType.DocumentType,
|
|
114
|
+
id: transaction.assignId(documentType),
|
|
115
|
+
name: documentType.name,
|
|
116
|
+
publicId: documentType.publicId,
|
|
117
|
+
systemId: documentType.systemId,
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Serializing Element nodes involves capturing:
|
|
123
|
+
* 1. HTML ATTRIBUTES:
|
|
124
|
+
* 2. JS STATE:
|
|
125
|
+
* - scroll offsets
|
|
126
|
+
* - Form fields (input value, checkbox checked, option selection, range)
|
|
127
|
+
* - Canvas state,
|
|
128
|
+
* - Media (video/audio) play mode + currentTime
|
|
129
|
+
* - iframe contents
|
|
130
|
+
* - webcomponents
|
|
131
|
+
* 3. CUSTOM PROPERTIES:
|
|
132
|
+
* - height+width for when `hidden` to cover the element
|
|
133
|
+
* 4. EXCLUDED INTERACTION STATE:
|
|
134
|
+
* - focus (possible, but not worth perf impact)
|
|
135
|
+
* - hover (tracked only via mouse activity)
|
|
136
|
+
* - fullscreen mode
|
|
137
|
+
*/
|
|
138
|
+
|
|
139
|
+
function serializeElementNode(
|
|
140
|
+
element: Element,
|
|
141
|
+
parentNodePrivacyLevel: ParentNodePrivacyLevel,
|
|
142
|
+
transaction: SerializationTransaction
|
|
143
|
+
): (ElementNode & SerializedNodeWithId) | null {
|
|
144
|
+
const tagName = getValidTagName(element.tagName)
|
|
145
|
+
const isSVG = isSVGElement(element) || undefined
|
|
146
|
+
|
|
147
|
+
// For performance reason, we don't use getNodePrivacyLevel directly: we leverage the
|
|
148
|
+
// parentNodePrivacyLevel option to avoid iterating over all parents
|
|
149
|
+
const nodePrivacyLevel = reducePrivacyLevel(getNodeSelfPrivacyLevel(element), parentNodePrivacyLevel)
|
|
150
|
+
|
|
151
|
+
if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {
|
|
152
|
+
const { width, height } = element.getBoundingClientRect()
|
|
153
|
+
return {
|
|
154
|
+
type: NodeType.Element,
|
|
155
|
+
id: transaction.assignId(element),
|
|
156
|
+
tagName,
|
|
157
|
+
attributes: {
|
|
158
|
+
rr_width: `${width}px`,
|
|
159
|
+
rr_height: `${height}px`,
|
|
160
|
+
[PRIVACY_ATTR_NAME]: PRIVACY_ATTR_VALUE_HIDDEN,
|
|
161
|
+
},
|
|
162
|
+
childNodes: [],
|
|
163
|
+
isSVG,
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Ignore Elements like Script and some Link, Metas
|
|
168
|
+
if (nodePrivacyLevel === NodePrivacyLevel.IGNORE) {
|
|
169
|
+
return null
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const id = transaction.assignId(element)
|
|
173
|
+
const attributes = serializeAttributes(element, nodePrivacyLevel, transaction)
|
|
174
|
+
|
|
175
|
+
let childNodes: SerializedNodeWithId[] = []
|
|
176
|
+
if (
|
|
177
|
+
hasChildNodes(element) &&
|
|
178
|
+
// Do not serialize style children as the css rules are already in the _cssText attribute
|
|
179
|
+
tagName !== 'style'
|
|
180
|
+
) {
|
|
181
|
+
childNodes = serializeChildNodes(element, nodePrivacyLevel, transaction)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
type: NodeType.Element,
|
|
186
|
+
id,
|
|
187
|
+
tagName,
|
|
188
|
+
attributes,
|
|
189
|
+
childNodes,
|
|
190
|
+
isSVG,
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function isSVGElement(el: Element): boolean {
|
|
195
|
+
return el.tagName === 'svg' || el instanceof SVGElement
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Text Nodes are dependant on Element nodes
|
|
200
|
+
* Privacy levels are set on elements so we check the parentElement of a text node
|
|
201
|
+
* for privacy level.
|
|
202
|
+
*/
|
|
203
|
+
|
|
204
|
+
function serializeTextNode(
|
|
205
|
+
textNode: Text,
|
|
206
|
+
parentNodePrivacyLevel: ParentNodePrivacyLevel,
|
|
207
|
+
transaction: SerializationTransaction
|
|
208
|
+
): (TextNode & SerializedNodeWithId) | null {
|
|
209
|
+
const textContent = getTextContent(textNode, parentNodePrivacyLevel)
|
|
210
|
+
if (textContent === undefined) {
|
|
211
|
+
return null
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
type: NodeType.Text,
|
|
215
|
+
id: transaction.assignId(textNode),
|
|
216
|
+
textContent,
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function serializeCDataNode(
|
|
221
|
+
node: CDATASection,
|
|
222
|
+
transaction: SerializationTransaction
|
|
223
|
+
): CDataNode & SerializedNodeWithId {
|
|
224
|
+
return {
|
|
225
|
+
type: NodeType.CDATA,
|
|
226
|
+
id: transaction.assignId(node),
|
|
227
|
+
textContent: '',
|
|
228
|
+
}
|
|
229
|
+
}
|