@datadog/mobile-react-native-webview 2.13.2 → 2.14.1
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/android/build.gradle +8 -1
- package/android/src/newarch/com/datadog/reactnative/webview/DdSdkReactNativeWebViewManager.kt +125 -0
- package/android/src/newarch/com/datadog/reactnative/webview/DdSdkReactNativeWebViewPackage.kt +4 -4
- package/android/src/oldarch/com/datadog/reactnative/webview/DdSdkReactNativeWebViewManager.kt +5 -19
- package/android/src/test/kotlin/{com → main/com}/datadog/reactnative/tools/unit/GenericAssert.kt +1 -1
- package/android/src/test/{kotlin/com/datadog/reactnative/webview → webview}/DatadogWebViewTest.kt +2 -7
- package/android/src/testNewArch/kotlin/com/datadog/reactnative/webview/DatadogWebViewTest.kt +122 -0
- package/lib/commonjs/index.js +8 -10
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/NativeDdWebView.js +1 -2
- package/lib/commonjs/specs/NativeDdWebView.js.map +1 -1
- package/lib/commonjs/utils/webview-js-utils.js +37 -53
- package/lib/commonjs/utils/webview-js-utils.js.map +1 -1
- package/lib/module/index.js +10 -12
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/NativeDdWebView.js +1 -2
- package/lib/module/specs/NativeDdWebView.js.map +1 -1
- package/lib/module/utils/webview-js-utils.js +34 -50
- package/lib/module/utils/webview-js-utils.js.map +1 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/specs/NativeDdWebView.d.ts +1 -1
- package/lib/typescript/specs/NativeDdWebView.d.ts.map +1 -1
- package/lib/typescript/utils/webview-js-utils.d.ts +4 -9
- package/lib/typescript/utils/webview-js-utils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/WebviewDatadogInjectedJS.test.tsx +27 -61
- package/src/__tests__/webview-js-utils.test.ts +151 -6
- package/src/index.tsx +17 -20
- package/src/specs/NativeDdWebView.ts +3 -5
- package/src/utils/webview-js-utils.ts +49 -57
- package/lib/commonjs/utils/env-utils.js +0 -17
- package/lib/commonjs/utils/env-utils.js.map +0 -1
- package/lib/module/utils/env-utils.js +0 -10
- package/lib/module/utils/env-utils.js.map +0 -1
- package/lib/typescript/utils/env-utils.d.ts +0 -2
- package/lib/typescript/utils/env-utils.d.ts.map +0 -1
- package/src/utils/env-utils.ts +0 -9
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["WebView","RNWebView","React","forwardRef","useCallback","NativeDdLogs","NativeDdSdk","NativeDdWebView","
|
|
1
|
+
{"version":3,"names":["WebView","RNWebView","React","forwardRef","useCallback","useMemo","NativeDdLogs","NativeDdSdk","NativeDdWebView","wrapJsCodeInTryAndCatch","wrapJsCodeWithAllowedHosts","jsx","_jsx","WebViewComponent","props","ref","userDefinedOnMessage","onMessage","event","handleDatadogMessage","ddMessage","type","message","logUserCodeErrors","error","consumeWebviewEvent","nativeEvent","data","jsonMsg","JSON","parse","source","err","injectedJavascript","injectedJavaScript","injectedJavascriptBeforeContentLoaded","injectedJavaScriptBeforeContentLoaded","allowedHosts","nativeConfig","component"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"AAAA;AACA;AACA;AACA;AACA;;AAEA,SAASA,OAAO,IAAIC,SAAS,QAAQ,sBAAsB;AAC3D,OAAOC,KAAK,IAAIC,UAAU,EAAEC,WAAW,EAAEC,OAAO,QAAQ,OAAO;AAE/D,OAAOC,YAAY,MAAM,0BAA0B;AACnD,SAASC,WAAW,QAAQ,yBAAyB;AACrD,SAASC,eAAe,QAAQ,yBAAyB;AACzD,SACIC,uBAAuB,EACvBC,0BAA0B,QACvB,0BAA0B;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAkBlC,MAAMC,gBAAgB,GAAGA,CAACC,KAAY,EAAEC,GAAgC,KAAK;EACzE,MAAMC,oBAAoB,GAAGF,KAAK,CAACG,SAAS;EAE5C,MAAMA,SAAS,GAAGb,WAAW,CACxBc,KAA0B,IAAK;IAC5B,MAAMC,oBAAoB,GAAIC,SAA+B,IAAK;MAC9D,IACIA,SAAS,CAACC,IAAI,KAAK,OAAO,IAC1BD,SAAS,CAACE,OAAO,IAAI,IAAI,KACxBR,KAAK,CAACS,iBAAiB,IAAI,KAAK,CAAC,EACpC;QACEjB,YAAY,EAAEkB,KAAK,CAACJ,SAAS,CAACE,OAAO,EAAE,CAAC,CAAC,CAAC;MAC9C,CAAC,MAAM,IACHF,SAAS,CAACC,IAAI,KAAK,cAAc,IACjCD,SAAS,CAACE,OAAO,IAAI,IAAI,EAC3B;QACEf,WAAW,EAAEkB,mBAAmB,CAACL,SAAS,CAACE,OAAO,CAAC;MACvD;IACJ,CAAC;IAED,MAAMA,OAAO,GAAGJ,KAAK,CAACQ,WAAW,CAACC,IAAI;IACtC,IAAIL,OAAO,IAAI,IAAI,EAAE;MACjB;IACJ;IAEA,IAAI;MACA,MAAMM,OAAO,GAAGC,IAAI,CAACC,KAAK,CAACR,OAAO,CAAC;MACnC,IAAIM,OAAO,IAAIA,OAAO,CAACG,MAAM,KAAK,SAAS,EAAE;QACzCZ,oBAAoB,CAACS,OAAO,CAAC;MACjC,CAAC,MAAM;QACHZ,oBAAoB,GAAGE,KAAK,CAAC;MACjC;IACJ,CAAC,CAAC,OAAOc,GAAG,EAAE;MACVhB,oBAAoB,GAAGE,KAAK,CAAC;IACjC;EACJ,CAAC,EACD,CAACF,oBAAoB,EAAEF,KAAK,CAACS,iBAAiB,CAClD,CAAC;EAED,MAAMU,kBAAkB,GAAG5B,OAAO,CAAC,MAAM;IACrC,OAAOI,uBAAuB,CAACK,KAAK,CAACoB,kBAAkB,CAAC;EAC5D,CAAC,EAAE,CAACpB,KAAK,CAACoB,kBAAkB,CAAC,CAAC;EAE9B,MAAMC,qCAAqC,GAAG9B,OAAO,CAAC,MAAM;IACxD,OAAOK,0BAA0B,CAC7BI,KAAK,CAACsB,qCAAqC,EAC3CtB,KAAK,CAACuB,YACV,CAAC;EACL,CAAC,EAAE,CAACvB,KAAK,CAACsB,qCAAqC,EAAEtB,KAAK,CAACuB,YAAY,CAAC,CAAC;EAErE,oBACIzB,IAAA,CAACX,SAAS;IAAA,GACFa,KAAK;IACTG,SAAS,EAAEA,SAAU;IACrBqB,YAAY,EAAE;MACVC,SAAS,EAAE/B,eAAe;MAC1BM,KAAK,EAAE;QACHuB,YAAY,EAAEvB,KAAK,CAACuB;MACxB;IACJ,CAAE;IACFH,kBAAkB,EAAED,kBAAmB;IACvCG,qCAAqC,EACjCD,qCACH;IACDpB,GAAG,EAAEA;EAAI,CACZ,CAAC;AAEV,CAAC;AAED,OAAO,MAAMf,OAAO,gBAAGG,UAAU,CAACU,gBAAgB,CAAC;;AAEnD;AACA,eAAeb,OAAO","ignoreList":[]}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { requireNativeComponent } from 'react-native';
|
|
8
|
-
|
|
9
|
-
const NativeDdWebView = !isNewArchitecture() ? requireNativeComponent('DdReactNativeWebView') : undefined;
|
|
8
|
+
const NativeDdWebView = requireNativeComponent('DdReactNativeWebView');
|
|
10
9
|
export { NativeDdWebView };
|
|
11
10
|
//# sourceMappingURL=NativeDdWebView.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["requireNativeComponent","
|
|
1
|
+
{"version":3,"names":["requireNativeComponent","NativeDdWebView"],"sourceRoot":"../../../src","sources":["specs/NativeDdWebView.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;;AAGA,SAASA,sBAAsB,QAAQ,cAAc;AAErD,MAAMC,eAAe,GAAGD,sBAAsB,CAC1C,sBACJ,CAAC;AAED,SAASC,eAAe","ignoreList":[]}
|
|
@@ -15,65 +15,49 @@ export const DATADOG_MESSAGE_PREFIX = '[DATADOG]';
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Wraps the given JS Code in a try and catch block
|
|
18
|
+
* Wraps the given JS Code in a try and catch block, including a
|
|
19
|
+
* comment with the given allowedHosts in JSON format
|
|
19
20
|
* @param javascriptCode The JS Code to wrap in a try and catch block.
|
|
20
21
|
* @returns the wrapped JS code.
|
|
21
22
|
*/
|
|
22
|
-
export
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
send(msg) {
|
|
45
|
-
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
46
|
-
source: 'DATADOG',
|
|
47
|
-
type: 'NATIVE_EVENT',
|
|
48
|
-
message: msg
|
|
49
|
-
}));
|
|
50
|
-
true;
|
|
51
|
-
},
|
|
52
|
-
getAllowedWebViewHosts() {
|
|
53
|
-
return ${formatAllowedHosts(allowedHosts)}
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
try{
|
|
57
|
-
${customJavaScriptCode}
|
|
58
|
-
}
|
|
59
|
-
catch (error) {
|
|
60
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
61
|
-
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
62
|
-
source: 'DATADOG',
|
|
63
|
-
type: 'ERROR',
|
|
64
|
-
message: errorMsg
|
|
65
|
-
}));
|
|
66
|
-
true;
|
|
67
|
-
}
|
|
68
|
-
`;
|
|
23
|
+
export function wrapJsCodeWithAllowedHosts(javascriptCode, allowedHosts) {
|
|
24
|
+
let jsCode = '';
|
|
25
|
+
const hosts = formatAllowedHosts(allowedHosts);
|
|
26
|
+
if (hosts) {
|
|
27
|
+
jsCode = `// #allowedHosts=${JSON.stringify(allowedHosts)}\n`;
|
|
28
|
+
}
|
|
29
|
+
return javascriptCode ? `${jsCode}\n${wrapJsCodeInTryAndCatch(javascriptCode)}` : jsCode.trim().length > 0 ? jsCode : undefined;
|
|
30
|
+
}
|
|
31
|
+
export function wrapJsCodeInTryAndCatch(javascriptCode) {
|
|
32
|
+
return javascriptCode ? `try{
|
|
33
|
+
${javascriptCode}
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
37
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
38
|
+
source: 'DATADOG',
|
|
39
|
+
type: 'ERROR',
|
|
40
|
+
message: errorMsg
|
|
41
|
+
}));
|
|
42
|
+
true;
|
|
43
|
+
}` : undefined;
|
|
44
|
+
}
|
|
69
45
|
function formatAllowedHosts(allowedHosts) {
|
|
70
46
|
try {
|
|
71
|
-
|
|
47
|
+
if (!allowedHosts) {
|
|
48
|
+
throw new Error('allowedHosts is undefined');
|
|
49
|
+
}
|
|
50
|
+
const jsonHosts = JSON.stringify(allowedHosts);
|
|
51
|
+
if (!jsonHosts) {
|
|
52
|
+
throw new Error("JSON.stringify returned 'undefined' for the given hosts");
|
|
53
|
+
}
|
|
54
|
+
return jsonHosts;
|
|
72
55
|
} catch (e) {
|
|
73
56
|
if (NativeDdSdk) {
|
|
74
57
|
NativeDdSdk.telemetryError(getErrorMessage(e), getErrorStackTrace(e), 'AllowedHostsError');
|
|
75
58
|
}
|
|
76
|
-
|
|
59
|
+
console.warn(`[@datadog/mobile-react-native-webview] Invalid 'allowedHosts' format: ${e}`);
|
|
60
|
+
return undefined;
|
|
77
61
|
}
|
|
78
62
|
}
|
|
79
63
|
const getErrorMessage = error => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeDdSdk","DATADOG_MESSAGE_PREFIX","
|
|
1
|
+
{"version":3,"names":["NativeDdSdk","DATADOG_MESSAGE_PREFIX","wrapJsCodeWithAllowedHosts","javascriptCode","allowedHosts","jsCode","hosts","formatAllowedHosts","JSON","stringify","wrapJsCodeInTryAndCatch","trim","length","undefined","Error","jsonHosts","e","telemetryError","getErrorMessage","getErrorStackTrace","console","warn","error","EMPTY_MESSAGE","message","String","EMPTY_STACK_TRACE","stack","stacktrace","componentStack","sourceURL","line","column"],"sourceRoot":"../../../src","sources":["utils/webview-js-utils.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAuB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAuB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAA2C,MAAM,OAAO,CAAC;AAWhE,KAAK,KAAK,GAAG,YAAY,GAAG;IACxB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;OAEG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;OAEG;IACH,qCAAqC,CAAC,EAAE,MAAM,CAAC;CAClD,CAAC;AAuEF,eAAO,MAAM,OAAO;IAnFhB;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;0CAyE4C,CAAC;AAGpD,eAAe,OAAO,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { CommonNativeWebViewProps } from 'react-native-webview/lib/WebViewTypes';
|
|
2
|
-
declare const NativeDdWebView: import("react-native").HostComponent<CommonNativeWebViewProps
|
|
2
|
+
declare const NativeDdWebView: import("react-native").HostComponent<CommonNativeWebViewProps>;
|
|
3
3
|
export { NativeDdWebView };
|
|
4
4
|
//# sourceMappingURL=NativeDdWebView.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeDdWebView.d.ts","sourceRoot":"","sources":["../../../src/specs/NativeDdWebView.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"NativeDdWebView.d.ts","sourceRoot":"","sources":["../../../src/specs/NativeDdWebView.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAGtF,QAAA,MAAM,eAAe,gEAEpB,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -19,16 +19,11 @@ export type DatadogMessageFormat = {
|
|
|
19
19
|
message: string;
|
|
20
20
|
};
|
|
21
21
|
/**
|
|
22
|
-
* Wraps the given JS Code in a try and catch block
|
|
22
|
+
* Wraps the given JS Code in a try and catch block, including a
|
|
23
|
+
* comment with the given allowedHosts in JSON format
|
|
23
24
|
* @param javascriptCode The JS Code to wrap in a try and catch block.
|
|
24
25
|
* @returns the wrapped JS code.
|
|
25
26
|
*/
|
|
26
|
-
export declare
|
|
27
|
-
|
|
28
|
-
* Legacy JS code for bridging the WebView events to DataDog native SDKs for consumption.
|
|
29
|
-
* @param allowedHosts The list of allowed hosts.
|
|
30
|
-
* @param customJavaScriptCode Custom user JS code to inject along with the Datadog bridging logic.
|
|
31
|
-
* @returns The JS code block as a string.
|
|
32
|
-
*/
|
|
33
|
-
export declare const getWebViewEventBridgingJS: (allowedHosts?: string[], customJavaScriptCode?: string) => string;
|
|
27
|
+
export declare function wrapJsCodeWithAllowedHosts(javascriptCode?: string, allowedHosts?: string[]): string | undefined;
|
|
28
|
+
export declare function wrapJsCodeInTryAndCatch(javascriptCode: string | undefined): string | undefined;
|
|
34
29
|
//# sourceMappingURL=webview-js-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webview-js-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/webview-js-utils.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAElD;;GAEG;AACH,MAAM,MAAM,kBAAkB;AAC1B;;GAEG;AACD,OAAO;AACT;;GAEG;GACD,cAAc,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IAC/B,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"webview-js-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/webview-js-utils.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAElD;;GAEG;AACH,MAAM,MAAM,kBAAkB;AAC1B;;GAEG;AACD,OAAO;AACT;;GAEG;GACD,cAAc,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IAC/B,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACtC,cAAc,CAAC,EAAE,MAAM,EACvB,YAAY,CAAC,EAAE,MAAM,EAAE,GACxB,MAAM,GAAG,SAAS,CAYpB;AAED,wBAAgB,uBAAuB,CACnC,cAAc,EAAE,MAAM,GAAG,SAAS,GACnC,MAAM,GAAG,SAAS,CAepB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datadog/mobile-react-native-webview",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.14.1",
|
|
4
4
|
"description": "A client-side React Native module to interact with react-native-webview and Datadog",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"datadog",
|
|
@@ -94,5 +94,5 @@
|
|
|
94
94
|
"javaPackageName": "com.datadog.reactnative.webview"
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
|
-
"gitHead": "
|
|
97
|
+
"gitHead": "ceddd4c317a90a7b19409146690022cd6889cb26"
|
|
98
98
|
}
|
|
@@ -3,13 +3,11 @@
|
|
|
3
3
|
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
4
4
|
* Copyright 2016-Present Datadog, Inc.
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
6
|
import { render } from '@testing-library/react-native';
|
|
8
7
|
import { WebView as RNWebView } from 'react-native-webview';
|
|
9
8
|
import React from 'react';
|
|
10
9
|
|
|
11
10
|
import { WebView } from '../index';
|
|
12
|
-
import { isNewArchitecture } from '../utils/env-utils';
|
|
13
11
|
|
|
14
12
|
import { dedent } from './__utils__/string-utils';
|
|
15
13
|
|
|
@@ -28,7 +26,7 @@ jest.mock('react-native-webview', () => {
|
|
|
28
26
|
const callfunction = jest.fn();
|
|
29
27
|
const postMessageMock = jest.fn();
|
|
30
28
|
|
|
31
|
-
window['ReactNativeWebView'] = {
|
|
29
|
+
(window as any)['ReactNativeWebView'] = {
|
|
32
30
|
postMessage: postMessageMock
|
|
33
31
|
};
|
|
34
32
|
|
|
@@ -129,19 +127,18 @@ describe('Webview', () => {
|
|
|
129
127
|
const realInjectedJs = dedent(
|
|
130
128
|
mockedWebView.mock.calls[0][0].injectedJavaScript ?? ''
|
|
131
129
|
);
|
|
132
|
-
const expected = dedent(`
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}`);
|
|
130
|
+
const expected = dedent(`try{
|
|
131
|
+
testInjectedJavaScript()
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
135
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
136
|
+
source: 'DATADOG',
|
|
137
|
+
type: 'ERROR',
|
|
138
|
+
message: errorMsg
|
|
139
|
+
}));
|
|
140
|
+
true;
|
|
141
|
+
}`);
|
|
145
142
|
|
|
146
143
|
expect(realInjectedJs).toBe(expected);
|
|
147
144
|
});
|
|
@@ -167,51 +164,20 @@ describe('Webview', () => {
|
|
|
167
164
|
mockedWebView.mock.calls[0][0]
|
|
168
165
|
.injectedJavaScriptBeforeContentLoaded ?? ''
|
|
169
166
|
);
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return '["localhost","example.com"]'
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
try{
|
|
188
|
-
testInjectedJavaScript()
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
192
|
-
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
193
|
-
source: 'DATADOG',
|
|
194
|
-
type: 'ERROR',
|
|
195
|
-
message: errorMsg
|
|
196
|
-
}));
|
|
197
|
-
true;
|
|
198
|
-
}
|
|
199
|
-
`);
|
|
200
|
-
} else {
|
|
201
|
-
expected = dedent(`
|
|
202
|
-
try{
|
|
203
|
-
testInjectedJavaScript()
|
|
204
|
-
}
|
|
205
|
-
catch (error) {
|
|
206
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
207
|
-
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
208
|
-
source: 'DATADOG',
|
|
209
|
-
type: 'ERROR',
|
|
210
|
-
message: errorMsg
|
|
211
|
-
}));
|
|
212
|
-
true;
|
|
213
|
-
}`);
|
|
214
|
-
}
|
|
167
|
+
const expected = dedent(`// #allowedHosts=["localhost","example.com"]
|
|
168
|
+
|
|
169
|
+
try{
|
|
170
|
+
testInjectedJavaScript()
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
174
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
175
|
+
source: 'DATADOG',
|
|
176
|
+
type: 'ERROR',
|
|
177
|
+
message: errorMsg
|
|
178
|
+
}));
|
|
179
|
+
true;
|
|
180
|
+
}`);
|
|
215
181
|
|
|
216
182
|
expect(realInjectedJs).toBe(expected);
|
|
217
183
|
});
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
* Copyright 2016-Present Datadog, Inc.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
wrapJsCodeInTryAndCatch,
|
|
9
|
+
wrapJsCodeWithAllowedHosts
|
|
10
|
+
} from '../utils/webview-js-utils';
|
|
8
11
|
|
|
9
12
|
import { dedent } from './__utils__/string-utils';
|
|
10
13
|
|
|
@@ -13,13 +16,73 @@ describe('WebView JS Utils', () => {
|
|
|
13
16
|
jest.clearAllMocks();
|
|
14
17
|
});
|
|
15
18
|
|
|
16
|
-
describe('M
|
|
17
|
-
it('M returns the JS
|
|
19
|
+
describe('M wrapJsCodeWithAllowedHosts wraps JS code in try & catch with DD messaging W jsCode is not null', () => {
|
|
20
|
+
it('M returns the allowedHosts JS comment W { jsCode = undefined & valid allowedHosts }', () => {
|
|
18
21
|
// Given
|
|
22
|
+
const warnSpy = jest
|
|
23
|
+
.spyOn(console, 'warn')
|
|
24
|
+
.mockImplementation(() => {});
|
|
25
|
+
const jsCode = undefined;
|
|
26
|
+
|
|
27
|
+
// When
|
|
28
|
+
const wrappedCode = wrapJsCodeWithAllowedHosts(jsCode, [
|
|
29
|
+
'example.com',
|
|
30
|
+
'test.com'
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
// Then
|
|
34
|
+
const expected = '// #allowedHosts=["example.com","test.com"]\n';
|
|
35
|
+
expect(wrappedCode).toBeDefined();
|
|
36
|
+
expect(dedent(wrappedCode as string)).toBe(expected);
|
|
37
|
+
expect(warnSpy).not.toHaveBeenCalled();
|
|
38
|
+
|
|
39
|
+
warnSpy.mockRestore();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('M returns the JS code wrapped in try and catch with allowedHosts comment W { custom JS code & valid allowedHosts }', () => {
|
|
43
|
+
// Given
|
|
44
|
+
const warnSpy = jest
|
|
45
|
+
.spyOn(console, 'warn')
|
|
46
|
+
.mockImplementation(() => {});
|
|
19
47
|
const jsCode = "console.log('test')";
|
|
20
48
|
|
|
21
49
|
// When
|
|
22
|
-
const wrappedCode =
|
|
50
|
+
const wrappedCode = wrapJsCodeWithAllowedHosts(jsCode, [
|
|
51
|
+
'example.com',
|
|
52
|
+
'test.com'
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
// Then
|
|
56
|
+
const expected = dedent(`// #allowedHosts=["example.com","test.com"]
|
|
57
|
+
|
|
58
|
+
try{
|
|
59
|
+
console.log('test')
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
63
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
64
|
+
source: 'DATADOG',
|
|
65
|
+
type: 'ERROR',
|
|
66
|
+
message: errorMsg
|
|
67
|
+
}));
|
|
68
|
+
true;
|
|
69
|
+
}`);
|
|
70
|
+
expect(wrappedCode).toBeDefined();
|
|
71
|
+
expect(dedent(wrappedCode as string)).toBe(expected);
|
|
72
|
+
expect(warnSpy).not.toHaveBeenCalled();
|
|
73
|
+
|
|
74
|
+
warnSpy.mockRestore();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('M returns the JS code wrapped in try and catch W { custom JS code & allowedHosts = undefined }', () => {
|
|
78
|
+
// Given
|
|
79
|
+
const warnSpy = jest
|
|
80
|
+
.spyOn(console, 'warn')
|
|
81
|
+
.mockImplementation(() => {});
|
|
82
|
+
const jsCode = "console.log('test')";
|
|
83
|
+
|
|
84
|
+
// When
|
|
85
|
+
const wrappedCode = wrapJsCodeWithAllowedHosts(jsCode, undefined);
|
|
23
86
|
|
|
24
87
|
// Then
|
|
25
88
|
const expected = dedent(`
|
|
@@ -37,15 +100,97 @@ describe('WebView JS Utils', () => {
|
|
|
37
100
|
}`);
|
|
38
101
|
expect(wrappedCode).toBeDefined();
|
|
39
102
|
expect(dedent(wrappedCode as string)).toBe(expected);
|
|
103
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
104
|
+
"[@datadog/mobile-react-native-webview] Invalid 'allowedHosts' format: Error: allowedHosts is undefined"
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
warnSpy.mockRestore();
|
|
40
108
|
});
|
|
41
109
|
|
|
42
|
-
it('M returns
|
|
110
|
+
it('M returns the JS code wrapped in try and catch W { custom JS code & invalid JSON allowedHosts }', () => {
|
|
111
|
+
// Given
|
|
112
|
+
const warnSpy = jest
|
|
113
|
+
.spyOn(console, 'warn')
|
|
114
|
+
.mockImplementation(() => {});
|
|
115
|
+
const jsCode = "console.log('test')";
|
|
116
|
+
|
|
117
|
+
// When
|
|
118
|
+
const wrappedCode = wrapJsCodeWithAllowedHosts(
|
|
119
|
+
jsCode,
|
|
120
|
+
(() => 'incompatible') as any
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// Then
|
|
124
|
+
const expected = dedent(`
|
|
125
|
+
try{
|
|
126
|
+
console.log('test')
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
130
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
131
|
+
source: 'DATADOG',
|
|
132
|
+
type: 'ERROR',
|
|
133
|
+
message: errorMsg
|
|
134
|
+
}));
|
|
135
|
+
true;
|
|
136
|
+
}`);
|
|
137
|
+
expect(wrappedCode).toBeDefined();
|
|
138
|
+
expect(dedent(wrappedCode as string)).toBe(expected);
|
|
139
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
140
|
+
"[@datadog/mobile-react-native-webview] Invalid 'allowedHosts' format: Error: JSON.stringify returned 'undefined' for the given hosts"
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
warnSpy.mockRestore();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('M returns undefined W { jsCode = undefined & allowedHosts = undefined }', () => {
|
|
43
147
|
// Given
|
|
44
148
|
const jsCode = undefined;
|
|
149
|
+
const allowedHosts = undefined;
|
|
45
150
|
// When
|
|
46
|
-
const wrappedCode =
|
|
151
|
+
const wrappedCode = wrapJsCodeWithAllowedHosts(
|
|
152
|
+
jsCode,
|
|
153
|
+
allowedHosts
|
|
154
|
+
);
|
|
47
155
|
// Then
|
|
48
156
|
expect(wrappedCode).toBe(undefined);
|
|
49
157
|
});
|
|
50
158
|
});
|
|
159
|
+
|
|
160
|
+
describe('M wrapJsCodeInTryAndCatch wraps the given JS code in a try & catch block with DD messaging', () => {
|
|
161
|
+
it('M returns the JS code wrapped in try and catch W { custom JS code is defined }', () => {
|
|
162
|
+
// Given
|
|
163
|
+
const jsCode = "console.log('test')";
|
|
164
|
+
|
|
165
|
+
// When
|
|
166
|
+
const wrappedCode = wrapJsCodeInTryAndCatch(jsCode);
|
|
167
|
+
|
|
168
|
+
// Then
|
|
169
|
+
const expected = dedent(`try{
|
|
170
|
+
console.log('test')
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
174
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
175
|
+
source: 'DATADOG',
|
|
176
|
+
type: 'ERROR',
|
|
177
|
+
message: errorMsg
|
|
178
|
+
}));
|
|
179
|
+
true;
|
|
180
|
+
}`);
|
|
181
|
+
expect(wrappedCode).toBeDefined();
|
|
182
|
+
expect(dedent(wrappedCode as string)).toBe(expected);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('M returns undefined W { custom JS code is undefined }', () => {
|
|
186
|
+
// Given
|
|
187
|
+
const jsCode = undefined;
|
|
188
|
+
|
|
189
|
+
// When
|
|
190
|
+
const wrappedCode = wrapJsCodeInTryAndCatch(jsCode);
|
|
191
|
+
|
|
192
|
+
// Then
|
|
193
|
+
expect(wrappedCode).toBeUndefined();
|
|
194
|
+
});
|
|
195
|
+
});
|
|
51
196
|
});
|
package/src/index.tsx
CHANGED
|
@@ -5,15 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { WebViewMessageEvent, WebViewProps } from 'react-native-webview';
|
|
7
7
|
import { WebView as RNWebView } from 'react-native-webview';
|
|
8
|
-
import React, { forwardRef, useCallback } from 'react';
|
|
8
|
+
import React, { forwardRef, useCallback, useMemo } from 'react';
|
|
9
9
|
|
|
10
10
|
import NativeDdLogs from './ext-specs/NativeDdLogs';
|
|
11
11
|
import { NativeDdSdk } from './ext-specs/NativeDdSdk';
|
|
12
12
|
import { NativeDdWebView } from './specs/NativeDdWebView';
|
|
13
|
-
import { isNewArchitecture } from './utils/env-utils';
|
|
14
13
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
wrapJsCodeInTryAndCatch,
|
|
15
|
+
wrapJsCodeWithAllowedHosts
|
|
17
16
|
} from './utils/webview-js-utils';
|
|
18
17
|
import type { DatadogMessageFormat } from './utils/webview-js-utils';
|
|
19
18
|
|
|
@@ -71,18 +70,16 @@ const WebViewComponent = (props: Props, ref: React.Ref<RNWebView<Props>>) => {
|
|
|
71
70
|
[userDefinedOnMessage, props.logUserCodeErrors]
|
|
72
71
|
);
|
|
73
72
|
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
};
|
|
73
|
+
const injectedJavascript = useMemo(() => {
|
|
74
|
+
return wrapJsCodeInTryAndCatch(props.injectedJavaScript);
|
|
75
|
+
}, [props.injectedJavaScript]);
|
|
76
|
+
|
|
77
|
+
const injectedJavascriptBeforeContentLoaded = useMemo(() => {
|
|
78
|
+
return wrapJsCodeWithAllowedHosts(
|
|
79
|
+
props.injectedJavaScriptBeforeContentLoaded,
|
|
80
|
+
props.allowedHosts
|
|
81
|
+
);
|
|
82
|
+
}, [props.injectedJavaScriptBeforeContentLoaded, props.allowedHosts]);
|
|
86
83
|
|
|
87
84
|
return (
|
|
88
85
|
<RNWebView
|
|
@@ -94,10 +91,10 @@ const WebViewComponent = (props: Props, ref: React.Ref<RNWebView<Props>>) => {
|
|
|
94
91
|
allowedHosts: props.allowedHosts
|
|
95
92
|
}
|
|
96
93
|
}}
|
|
97
|
-
injectedJavaScript={
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
94
|
+
injectedJavaScript={injectedJavascript}
|
|
95
|
+
injectedJavaScriptBeforeContentLoaded={
|
|
96
|
+
injectedJavascriptBeforeContentLoaded
|
|
97
|
+
}
|
|
101
98
|
ref={ref}
|
|
102
99
|
/>
|
|
103
100
|
);
|
|
@@ -7,10 +7,8 @@
|
|
|
7
7
|
import type { CommonNativeWebViewProps } from 'react-native-webview/lib/WebViewTypes';
|
|
8
8
|
import { requireNativeComponent } from 'react-native';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
? requireNativeComponent<CommonNativeWebViewProps>('DdReactNativeWebView')
|
|
14
|
-
: undefined;
|
|
10
|
+
const NativeDdWebView = requireNativeComponent<CommonNativeWebViewProps>(
|
|
11
|
+
'DdReactNativeWebView'
|
|
12
|
+
);
|
|
15
13
|
|
|
16
14
|
export { NativeDdWebView };
|