@sentry/babel-plugin-component-annotate 4.9.1 → 5.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/dist/cjs/index.js +566 -1009
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.mjs +564 -1005
- package/dist/esm/index.mjs.map +1 -1
- package/package.json +6 -10
package/dist/cjs/index.js
CHANGED
|
@@ -1,1071 +1,628 @@
|
|
|
1
|
-
'
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
function _iterableToArrayLimit(arr, i) {
|
|
6
|
-
var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"];
|
|
7
|
-
if (null != _i) {
|
|
8
|
-
var _s,
|
|
9
|
-
_e,
|
|
10
|
-
_x,
|
|
11
|
-
_r,
|
|
12
|
-
_arr = [],
|
|
13
|
-
_n = !0,
|
|
14
|
-
_d = !1;
|
|
15
|
-
try {
|
|
16
|
-
if (_x = (_i = _i.call(arr)).next, 0 === i) {
|
|
17
|
-
if (Object(_i) !== _i) return;
|
|
18
|
-
_n = !1;
|
|
19
|
-
} else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0);
|
|
20
|
-
} catch (err) {
|
|
21
|
-
_d = !0, _e = err;
|
|
22
|
-
} finally {
|
|
23
|
-
try {
|
|
24
|
-
if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return;
|
|
25
|
-
} finally {
|
|
26
|
-
if (_d) throw _e;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return _arr;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
function _typeof(obj) {
|
|
33
|
-
"@babel/helpers - typeof";
|
|
34
|
-
|
|
35
|
-
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
|
|
36
|
-
return typeof obj;
|
|
37
|
-
} : function (obj) {
|
|
38
|
-
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
39
|
-
}, _typeof(obj);
|
|
40
|
-
}
|
|
41
|
-
function _slicedToArray(arr, i) {
|
|
42
|
-
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
|
|
43
|
-
}
|
|
44
|
-
function _arrayWithHoles(arr) {
|
|
45
|
-
if (Array.isArray(arr)) return arr;
|
|
46
|
-
}
|
|
47
|
-
function _unsupportedIterableToArray(o, minLen) {
|
|
48
|
-
if (!o) return;
|
|
49
|
-
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
50
|
-
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
51
|
-
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
52
|
-
if (n === "Map" || n === "Set") return Array.from(o);
|
|
53
|
-
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
54
|
-
}
|
|
55
|
-
function _arrayLikeToArray(arr, len) {
|
|
56
|
-
if (len == null || len > arr.length) len = arr.length;
|
|
57
|
-
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
|
58
|
-
return arr2;
|
|
59
|
-
}
|
|
60
|
-
function _nonIterableRest() {
|
|
61
|
-
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
62
|
-
}
|
|
63
|
-
function _createForOfIteratorHelper(o, allowArrayLike) {
|
|
64
|
-
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
|
|
65
|
-
if (!it) {
|
|
66
|
-
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
|
|
67
|
-
if (it) o = it;
|
|
68
|
-
var i = 0;
|
|
69
|
-
var F = function () {};
|
|
70
|
-
return {
|
|
71
|
-
s: F,
|
|
72
|
-
n: function () {
|
|
73
|
-
if (i >= o.length) return {
|
|
74
|
-
done: true
|
|
75
|
-
};
|
|
76
|
-
return {
|
|
77
|
-
done: false,
|
|
78
|
-
value: o[i++]
|
|
79
|
-
};
|
|
80
|
-
},
|
|
81
|
-
e: function (e) {
|
|
82
|
-
throw e;
|
|
83
|
-
},
|
|
84
|
-
f: F
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
88
|
-
}
|
|
89
|
-
var normalCompletion = true,
|
|
90
|
-
didErr = false,
|
|
91
|
-
err;
|
|
92
|
-
return {
|
|
93
|
-
s: function () {
|
|
94
|
-
it = it.call(o);
|
|
95
|
-
},
|
|
96
|
-
n: function () {
|
|
97
|
-
var step = it.next();
|
|
98
|
-
normalCompletion = step.done;
|
|
99
|
-
return step;
|
|
100
|
-
},
|
|
101
|
-
e: function (e) {
|
|
102
|
-
didErr = true;
|
|
103
|
-
err = e;
|
|
104
|
-
},
|
|
105
|
-
f: function () {
|
|
106
|
-
try {
|
|
107
|
-
if (!normalCompletion && it.return != null) it.return();
|
|
108
|
-
} finally {
|
|
109
|
-
if (didErr) throw err;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* MIT License
|
|
117
|
-
*
|
|
118
|
-
* Copyright (c) 2020 Engineering at FullStory
|
|
119
|
-
*
|
|
120
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
121
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
122
|
-
* in the Software without restriction, including without limitation the rights
|
|
123
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
124
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
125
|
-
* furnished to do so, subject to the following conditions:
|
|
126
|
-
*
|
|
127
|
-
* The above copyright notice and this permission notice shall be included in all
|
|
128
|
-
* copies or substantial portions of the Software.
|
|
129
|
-
*
|
|
130
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
131
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
132
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
133
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
134
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
135
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
136
|
-
* SOFTWARE.
|
|
137
|
-
*
|
|
138
|
-
*/
|
|
139
|
-
|
|
140
|
-
var KNOWN_INCOMPATIBLE_PLUGINS = [
|
|
141
|
-
// This module might be causing an issue preventing clicks. For safety, we won't run on this module.
|
|
142
|
-
"react-native-testfairy",
|
|
143
|
-
// This module checks for unexpected property keys and throws an exception.
|
|
144
|
-
"@react-navigation"];
|
|
145
|
-
var DEFAULT_IGNORED_ELEMENTS = ["a", "abbr", "address", "area", "article", "aside", "audio", "b", "base", "bdi", "bdo", "blockquote", "body", "br", "button", "canvas", "caption", "cite", "code", "col", "colgroup", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "div", "dl", "dt", "em", "embed", "fieldset", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "iframe", "img", "input", "ins", "kbd", "keygen", "label", "legend", "li", "link", "main", "map", "mark", "menu", "menuitem", "meter", "nav", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param", "pre", "progress", "q", "rb", "rp", "rt", "rtc", "ruby", "s", "samp", "script", "section", "select", "small", "source", "span", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "u", "ul", "var", "video", "wbr"];
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* MIT License
|
|
149
|
-
*
|
|
150
|
-
* Copyright (c) 2020 Engineering at FullStory
|
|
151
|
-
*
|
|
152
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
153
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
154
|
-
* in the Software without restriction, including without limitation the rights
|
|
155
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
156
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
157
|
-
* furnished to do so, subject to the following conditions:
|
|
158
|
-
*
|
|
159
|
-
* The above copyright notice and this permission notice shall be included in all
|
|
160
|
-
* copies or substantial portions of the Software.
|
|
161
|
-
*
|
|
162
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
163
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
164
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
165
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
166
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
167
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
168
|
-
* SOFTWARE.
|
|
169
|
-
*
|
|
170
|
-
*/
|
|
1
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
|
|
171
2
|
|
|
3
|
+
//#region src/constants.ts
|
|
172
4
|
/**
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
5
|
+
* MIT License
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2020 Engineering at FullStory
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
* in the Software without restriction, including without limitation the rights
|
|
12
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
* furnished to do so, subject to the following conditions:
|
|
15
|
+
*
|
|
16
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
* copies or substantial portions of the Software.
|
|
18
|
+
*
|
|
19
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
* SOFTWARE.
|
|
26
|
+
*
|
|
27
|
+
*/
|
|
28
|
+
const KNOWN_INCOMPATIBLE_PLUGINS = ["react-native-testfairy", "@react-navigation"];
|
|
29
|
+
const DEFAULT_IGNORED_ELEMENTS = [
|
|
30
|
+
"a",
|
|
31
|
+
"abbr",
|
|
32
|
+
"address",
|
|
33
|
+
"area",
|
|
34
|
+
"article",
|
|
35
|
+
"aside",
|
|
36
|
+
"audio",
|
|
37
|
+
"b",
|
|
38
|
+
"base",
|
|
39
|
+
"bdi",
|
|
40
|
+
"bdo",
|
|
41
|
+
"blockquote",
|
|
42
|
+
"body",
|
|
43
|
+
"br",
|
|
44
|
+
"button",
|
|
45
|
+
"canvas",
|
|
46
|
+
"caption",
|
|
47
|
+
"cite",
|
|
48
|
+
"code",
|
|
49
|
+
"col",
|
|
50
|
+
"colgroup",
|
|
51
|
+
"data",
|
|
52
|
+
"datalist",
|
|
53
|
+
"dd",
|
|
54
|
+
"del",
|
|
55
|
+
"details",
|
|
56
|
+
"dfn",
|
|
57
|
+
"dialog",
|
|
58
|
+
"div",
|
|
59
|
+
"dl",
|
|
60
|
+
"dt",
|
|
61
|
+
"em",
|
|
62
|
+
"embed",
|
|
63
|
+
"fieldset",
|
|
64
|
+
"figure",
|
|
65
|
+
"footer",
|
|
66
|
+
"form",
|
|
67
|
+
"h1",
|
|
68
|
+
"h2",
|
|
69
|
+
"h3",
|
|
70
|
+
"h4",
|
|
71
|
+
"h5",
|
|
72
|
+
"h6",
|
|
73
|
+
"head",
|
|
74
|
+
"header",
|
|
75
|
+
"hgroup",
|
|
76
|
+
"hr",
|
|
77
|
+
"html",
|
|
78
|
+
"i",
|
|
79
|
+
"iframe",
|
|
80
|
+
"img",
|
|
81
|
+
"input",
|
|
82
|
+
"ins",
|
|
83
|
+
"kbd",
|
|
84
|
+
"keygen",
|
|
85
|
+
"label",
|
|
86
|
+
"legend",
|
|
87
|
+
"li",
|
|
88
|
+
"link",
|
|
89
|
+
"main",
|
|
90
|
+
"map",
|
|
91
|
+
"mark",
|
|
92
|
+
"menu",
|
|
93
|
+
"menuitem",
|
|
94
|
+
"meter",
|
|
95
|
+
"nav",
|
|
96
|
+
"noscript",
|
|
97
|
+
"object",
|
|
98
|
+
"ol",
|
|
99
|
+
"optgroup",
|
|
100
|
+
"option",
|
|
101
|
+
"output",
|
|
102
|
+
"p",
|
|
103
|
+
"param",
|
|
104
|
+
"pre",
|
|
105
|
+
"progress",
|
|
106
|
+
"q",
|
|
107
|
+
"rb",
|
|
108
|
+
"rp",
|
|
109
|
+
"rt",
|
|
110
|
+
"rtc",
|
|
111
|
+
"ruby",
|
|
112
|
+
"s",
|
|
113
|
+
"samp",
|
|
114
|
+
"script",
|
|
115
|
+
"section",
|
|
116
|
+
"select",
|
|
117
|
+
"small",
|
|
118
|
+
"source",
|
|
119
|
+
"span",
|
|
120
|
+
"strong",
|
|
121
|
+
"style",
|
|
122
|
+
"sub",
|
|
123
|
+
"summary",
|
|
124
|
+
"sup",
|
|
125
|
+
"table",
|
|
126
|
+
"tbody",
|
|
127
|
+
"td",
|
|
128
|
+
"template",
|
|
129
|
+
"textarea",
|
|
130
|
+
"tfoot",
|
|
131
|
+
"th",
|
|
132
|
+
"thead",
|
|
133
|
+
"time",
|
|
134
|
+
"title",
|
|
135
|
+
"tr",
|
|
136
|
+
"track",
|
|
137
|
+
"u",
|
|
138
|
+
"ul",
|
|
139
|
+
"var",
|
|
140
|
+
"video",
|
|
141
|
+
"wbr"
|
|
142
|
+
];
|
|
143
|
+
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/experimental.ts
|
|
146
|
+
const REACT_NATIVE_ELEMENTS = [
|
|
147
|
+
"Image",
|
|
148
|
+
"Text",
|
|
149
|
+
"View",
|
|
150
|
+
"ScrollView",
|
|
151
|
+
"TextInput",
|
|
152
|
+
"TouchableOpacity",
|
|
153
|
+
"TouchableHighlight",
|
|
154
|
+
"TouchableWithoutFeedback",
|
|
155
|
+
"FlatList",
|
|
156
|
+
"SectionList",
|
|
157
|
+
"ActivityIndicator",
|
|
158
|
+
"Button",
|
|
159
|
+
"Switch",
|
|
160
|
+
"Modal",
|
|
161
|
+
"SafeAreaView",
|
|
162
|
+
"StatusBar",
|
|
163
|
+
"KeyboardAvoidingView",
|
|
164
|
+
"RefreshControl",
|
|
165
|
+
"Picker",
|
|
166
|
+
"Slider"
|
|
167
|
+
];
|
|
168
|
+
function experimentalComponentNameAnnotatePlugin({ types: t }) {
|
|
169
|
+
return { visitor: {
|
|
170
|
+
Program: { enter(path, state) {
|
|
171
|
+
state.sentryFragmentContext = collectFragmentContext$1(path);
|
|
172
|
+
} },
|
|
173
|
+
FunctionDeclaration(path, state) {
|
|
174
|
+
if (!path.node.id || !path.node.id.name) return;
|
|
175
|
+
functionBodyPushAttributes$1(createJSXProcessingContext$1(state, t, path.node.id.name), path);
|
|
176
|
+
},
|
|
177
|
+
ArrowFunctionExpression(path, state) {
|
|
178
|
+
const parent = path.parent;
|
|
179
|
+
if (!parent || !("id" in parent) || !parent.id || !("name" in parent.id) || !parent.id.name) return;
|
|
180
|
+
functionBodyPushAttributes$1(createJSXProcessingContext$1(state, t, parent.id.name), path);
|
|
181
|
+
},
|
|
182
|
+
ClassDeclaration(path, state) {
|
|
183
|
+
const name = path.get("id");
|
|
184
|
+
const render = path.get("body").get("body").find((prop) => {
|
|
185
|
+
return prop.isClassMethod() && prop.get("key").isIdentifier({ name: "render" });
|
|
186
|
+
});
|
|
187
|
+
if (!render || !render.traverse) return;
|
|
188
|
+
const context = createJSXProcessingContext$1(state, t, name.node?.name || "");
|
|
189
|
+
render.traverse({ ReturnStatement(returnStatement) {
|
|
190
|
+
const arg = returnStatement.get("argument");
|
|
191
|
+
if (!arg.isJSXElement() && !arg.isJSXFragment()) return;
|
|
192
|
+
processJSX$1(context, arg);
|
|
193
|
+
} });
|
|
194
|
+
}
|
|
195
|
+
} };
|
|
238
196
|
}
|
|
239
|
-
|
|
240
197
|
/**
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
198
|
+
* Checks if an element name represents an HTML element (as opposed to a React component).
|
|
199
|
+
* HTML elements include standard lowercase HTML tags and React Native elements.
|
|
200
|
+
*/
|
|
244
201
|
function isHtmlElement(elementName) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
// Check for lowercase first letter (standard HTML elements)
|
|
251
|
-
if (elementName.length > 0 && elementName.charAt(0) === elementName.charAt(0).toLowerCase()) {
|
|
252
|
-
return true;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// React Native elements typically start with uppercase but are still "native" elements
|
|
256
|
-
// We consider them HTML-like elements for annotation purposes
|
|
257
|
-
if (REACT_NATIVE_ELEMENTS.includes(elementName)) {
|
|
258
|
-
return true;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Otherwise, assume it's a React component (PascalCase)
|
|
262
|
-
return false;
|
|
202
|
+
if (elementName === UNKNOWN_ELEMENT_NAME$1) return false;
|
|
203
|
+
if (elementName.length > 0 && elementName.charAt(0) === elementName.charAt(0).toLowerCase()) return true;
|
|
204
|
+
if (REACT_NATIVE_ELEMENTS.includes(elementName)) return true;
|
|
205
|
+
return false;
|
|
263
206
|
}
|
|
264
|
-
|
|
265
207
|
/**
|
|
266
|
-
|
|
267
|
-
|
|
208
|
+
* Creates a JSX processing context from the plugin state
|
|
209
|
+
*/
|
|
268
210
|
function createJSXProcessingContext$1(state, t, componentName) {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
};
|
|
211
|
+
return {
|
|
212
|
+
t,
|
|
213
|
+
componentName,
|
|
214
|
+
attributeName: attributeNamesFromState$1(state),
|
|
215
|
+
ignoredComponents: state.opts.ignoredComponents ?? [],
|
|
216
|
+
fragmentContext: state.sentryFragmentContext
|
|
217
|
+
};
|
|
277
218
|
}
|
|
278
|
-
|
|
279
219
|
/**
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
220
|
+
* Processes the body of a function to add Sentry tracking attributes to JSX elements.
|
|
221
|
+
* Handles various function body structures including direct JSX returns, conditional expressions,
|
|
222
|
+
* and nested JSX elements.
|
|
223
|
+
*/
|
|
284
224
|
function functionBodyPushAttributes$1(context, path) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
var consequent = arg.get("consequent");
|
|
314
|
-
if (consequent.isJSXFragment() || consequent.isJSXElement()) {
|
|
315
|
-
processJSX$1(context, consequent);
|
|
316
|
-
}
|
|
317
|
-
var alternate = arg.get("alternate");
|
|
318
|
-
if (alternate.isJSXFragment() || alternate.isJSXElement()) {
|
|
319
|
-
processJSX$1(context, alternate);
|
|
320
|
-
}
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
if (!arg.isJSXFragment() && !arg.isJSXElement()) {
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
jsxNode = arg;
|
|
327
|
-
}
|
|
328
|
-
if (!jsxNode) {
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
processJSX$1(context, jsxNode);
|
|
225
|
+
let jsxNode;
|
|
226
|
+
const functionBody = path.get("body").get("body");
|
|
227
|
+
if (!("length" in functionBody) && functionBody.parent && (functionBody.parent.type === "JSXElement" || functionBody.parent.type === "JSXFragment")) {
|
|
228
|
+
const maybeJsxNode = functionBody.find((c) => {
|
|
229
|
+
return c.type === "JSXElement" || c.type === "JSXFragment";
|
|
230
|
+
});
|
|
231
|
+
if (!maybeJsxNode) return;
|
|
232
|
+
jsxNode = maybeJsxNode;
|
|
233
|
+
} else {
|
|
234
|
+
const returnStatement = functionBody.find((c) => {
|
|
235
|
+
return c.type === "ReturnStatement";
|
|
236
|
+
});
|
|
237
|
+
if (!returnStatement) return;
|
|
238
|
+
const arg = returnStatement.get("argument");
|
|
239
|
+
if (!arg) return;
|
|
240
|
+
if (Array.isArray(arg)) return;
|
|
241
|
+
if (arg.isConditionalExpression()) {
|
|
242
|
+
const consequent = arg.get("consequent");
|
|
243
|
+
if (consequent.isJSXFragment() || consequent.isJSXElement()) processJSX$1(context, consequent);
|
|
244
|
+
const alternate = arg.get("alternate");
|
|
245
|
+
if (alternate.isJSXFragment() || alternate.isJSXElement()) processJSX$1(context, alternate);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (!arg.isJSXFragment() && !arg.isJSXElement()) return;
|
|
249
|
+
jsxNode = arg;
|
|
250
|
+
}
|
|
251
|
+
if (!jsxNode) return;
|
|
252
|
+
processJSX$1(context, jsxNode);
|
|
332
253
|
}
|
|
333
|
-
|
|
334
254
|
/**
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
255
|
+
* Recursively processes JSX elements to add Sentry tracking attributes.
|
|
256
|
+
* Handles both JSX elements and fragments, applying appropriate attributes
|
|
257
|
+
* based on configuration and component context.
|
|
258
|
+
*/
|
|
339
259
|
function processJSX$1(context, jsxNode) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
if (hasInjectedAttributes) {
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
var children = jsxNode.get("children");
|
|
355
|
-
// TODO: See why `Array.isArray` doesn't have correct behaviour here
|
|
356
|
-
if (children && !("length" in children)) {
|
|
357
|
-
// A single child was found, maybe a bit of static text
|
|
358
|
-
children = [children];
|
|
359
|
-
}
|
|
360
|
-
children.forEach(function (child) {
|
|
361
|
-
// Happens for some node types like plain text
|
|
362
|
-
if (!child.node) {
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// If the current element is a fragment, children are still considered at root level
|
|
367
|
-
// Otherwise, children are not at root level
|
|
368
|
-
var openingElement = child.get("openingElement");
|
|
369
|
-
// TODO: Improve this. We never expect to have multiple opening elements
|
|
370
|
-
// but if it's possible, this should work
|
|
371
|
-
if (Array.isArray(openingElement)) {
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
processJSX$1(context, child);
|
|
375
|
-
});
|
|
260
|
+
if (!jsxNode) return;
|
|
261
|
+
const paths = jsxNode.get("openingElement");
|
|
262
|
+
if ((Array.isArray(paths) ? paths : [paths]).reduce((prev, openingElement) => prev || applyAttributes$1(context, openingElement, context.componentName), false)) return;
|
|
263
|
+
let children = jsxNode.get("children");
|
|
264
|
+
if (children && !("length" in children)) children = [children];
|
|
265
|
+
children.forEach((child) => {
|
|
266
|
+
if (!child.node) return;
|
|
267
|
+
const openingElement = child.get("openingElement");
|
|
268
|
+
if (Array.isArray(openingElement)) return;
|
|
269
|
+
processJSX$1(context, child);
|
|
270
|
+
});
|
|
376
271
|
}
|
|
377
|
-
|
|
378
272
|
/**
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
273
|
+
* Applies Sentry tracking attributes to a JSX opening element.
|
|
274
|
+
* Adds component name, element name, and source file attributes while
|
|
275
|
+
* respecting ignore lists and fragment detection.
|
|
276
|
+
*/
|
|
383
277
|
function applyAttributes$1(context, openingElement, componentName) {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
// Check if this is a React fragment - if so, skip attribute addition entirely
|
|
395
|
-
var isFragment = isReactFragment$1(t, openingElement, fragmentContext);
|
|
396
|
-
if (isFragment) {
|
|
397
|
-
return false;
|
|
398
|
-
}
|
|
399
|
-
if (!openingElement.node.attributes) {
|
|
400
|
-
openingElement.node.attributes = [];
|
|
401
|
-
}
|
|
402
|
-
var elementName = getPathName$1(t, openingElement);
|
|
403
|
-
if (!isHtmlElement(elementName)) {
|
|
404
|
-
return false;
|
|
405
|
-
}
|
|
406
|
-
var isAnIgnoredComponent = ignoredComponents.some(function (ignoredComponent) {
|
|
407
|
-
return ignoredComponent === componentName || ignoredComponent === elementName;
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
// Add a stable attribute for the component name (only for root elements)
|
|
411
|
-
if (!isAnIgnoredComponent && !hasAttributeWithName$1(openingElement, componentAttributeName)) {
|
|
412
|
-
if (componentAttributeName) {
|
|
413
|
-
openingElement.node.attributes.push(t.jSXAttribute(t.jSXIdentifier(componentAttributeName), t.stringLiteral(componentName)));
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
return true;
|
|
278
|
+
const { t, attributeName: componentAttributeName, ignoredComponents, fragmentContext } = context;
|
|
279
|
+
if (!openingElement.node) return false;
|
|
280
|
+
if (isReactFragment$1(t, openingElement, fragmentContext)) return false;
|
|
281
|
+
if (!openingElement.node.attributes) openingElement.node.attributes = [];
|
|
282
|
+
const elementName = getPathName$1(t, openingElement);
|
|
283
|
+
if (!isHtmlElement(elementName)) return false;
|
|
284
|
+
if (!ignoredComponents.some((ignoredComponent) => ignoredComponent === componentName || ignoredComponent === elementName) && !hasAttributeWithName$1(openingElement, componentAttributeName)) {
|
|
285
|
+
if (componentAttributeName) openingElement.node.attributes.push(t.jSXAttribute(t.jSXIdentifier(componentAttributeName), t.stringLiteral(componentName)));
|
|
286
|
+
}
|
|
287
|
+
return true;
|
|
417
288
|
}
|
|
418
289
|
function attributeNamesFromState$1(state) {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
}
|
|
422
|
-
return "data-sentry-component";
|
|
290
|
+
if (state.opts.native) return "dataSentryComponent";
|
|
291
|
+
return "data-sentry-component";
|
|
423
292
|
}
|
|
424
293
|
function collectFragmentContext$1(programPath) {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
// Handle: const MyFragment = Fragment (only if Fragment is a known alias)
|
|
457
|
-
if (init.type === "Identifier" && fragmentAliases.has(init.name)) {
|
|
458
|
-
fragmentAliases.add(varPath.node.id.name);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
// Handle: const MyFragment = React.Fragment (only for known React namespaces)
|
|
462
|
-
if (init.type === "MemberExpression" && init.object.type === "Identifier" && init.property.type === "Identifier" && init.property.name === "Fragment" && reactNamespaceAliases.has(init.object.name)) {
|
|
463
|
-
fragmentAliases.add(varPath.node.id.name);
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// Handle destructuring assignments: const { Fragment } = React
|
|
468
|
-
if (varPath.node.id.type === "ObjectPattern") {
|
|
469
|
-
if (init.type === "Identifier" && reactNamespaceAliases.has(init.name)) {
|
|
470
|
-
var properties = varPath.node.id.properties;
|
|
471
|
-
var _iterator = _createForOfIteratorHelper(properties),
|
|
472
|
-
_step;
|
|
473
|
-
try {
|
|
474
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
475
|
-
var prop = _step.value;
|
|
476
|
-
if (prop.type === "ObjectProperty" && prop.key && prop.key.type === "Identifier" && prop.value && prop.value.type === "Identifier" && prop.key.name === "Fragment") {
|
|
477
|
-
fragmentAliases.add(prop.value.name);
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
} catch (err) {
|
|
481
|
-
_iterator.e(err);
|
|
482
|
-
} finally {
|
|
483
|
-
_iterator.f();
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
});
|
|
490
|
-
return {
|
|
491
|
-
fragmentAliases: fragmentAliases,
|
|
492
|
-
reactNamespaceAliases: reactNamespaceAliases
|
|
493
|
-
};
|
|
294
|
+
const fragmentAliases = /* @__PURE__ */ new Set();
|
|
295
|
+
const reactNamespaceAliases = new Set(["React"]);
|
|
296
|
+
programPath.traverse({
|
|
297
|
+
ImportDeclaration(importPath) {
|
|
298
|
+
const source = importPath.node.source.value;
|
|
299
|
+
if (source === "react" || source === "React") importPath.node.specifiers.forEach((spec) => {
|
|
300
|
+
if (spec.type === "ImportSpecifier" && spec.imported.type === "Identifier") {
|
|
301
|
+
if (spec.imported.name === "Fragment") fragmentAliases.add(spec.local.name);
|
|
302
|
+
} else if (spec.type === "ImportDefaultSpecifier" || spec.type === "ImportNamespaceSpecifier") reactNamespaceAliases.add(spec.local.name);
|
|
303
|
+
});
|
|
304
|
+
},
|
|
305
|
+
VariableDeclarator(varPath) {
|
|
306
|
+
if (varPath.node.init) {
|
|
307
|
+
const init = varPath.node.init;
|
|
308
|
+
if (varPath.node.id.type === "Identifier") {
|
|
309
|
+
if (init.type === "Identifier" && fragmentAliases.has(init.name)) fragmentAliases.add(varPath.node.id.name);
|
|
310
|
+
if (init.type === "MemberExpression" && init.object.type === "Identifier" && init.property.type === "Identifier" && init.property.name === "Fragment" && reactNamespaceAliases.has(init.object.name)) fragmentAliases.add(varPath.node.id.name);
|
|
311
|
+
}
|
|
312
|
+
if (varPath.node.id.type === "ObjectPattern") {
|
|
313
|
+
if (init.type === "Identifier" && reactNamespaceAliases.has(init.name)) {
|
|
314
|
+
const properties = varPath.node.id.properties;
|
|
315
|
+
for (const prop of properties) if (prop.type === "ObjectProperty" && prop.key && prop.key.type === "Identifier" && prop.value && prop.value.type === "Identifier" && prop.key.name === "Fragment") fragmentAliases.add(prop.value.name);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
return {
|
|
322
|
+
fragmentAliases,
|
|
323
|
+
reactNamespaceAliases
|
|
324
|
+
};
|
|
494
325
|
}
|
|
495
326
|
function isReactFragment$1(t, openingElement, context) {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
return false;
|
|
519
|
-
}
|
|
520
|
-
if ("object" in nodeName && "property" in nodeName) {
|
|
521
|
-
var nodeNameObject = nodeName.object;
|
|
522
|
-
var nodeNameProperty = nodeName.property;
|
|
523
|
-
if (_typeof(nodeNameObject) !== "object" || _typeof(nodeNameProperty) !== "object") {
|
|
524
|
-
return false;
|
|
525
|
-
}
|
|
526
|
-
if (!nodeNameObject || !nodeNameProperty) {
|
|
527
|
-
return false;
|
|
528
|
-
}
|
|
529
|
-
var objectName = "name" in nodeNameObject && nodeNameObject.name;
|
|
530
|
-
var propertyName = "name" in nodeNameProperty && nodeNameProperty.name;
|
|
531
|
-
|
|
532
|
-
// React.Fragment check
|
|
533
|
-
if (objectName === "React" && propertyName === "Fragment") {
|
|
534
|
-
return true;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
// Enhanced checks using context
|
|
538
|
-
if (context) {
|
|
539
|
-
// Check React.Fragment pattern with known React namespaces
|
|
540
|
-
if (context.reactNamespaceAliases.has(objectName) && propertyName === "Fragment") {
|
|
541
|
-
return true;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
// Check MyFragment.Fragment pattern
|
|
545
|
-
if (context.fragmentAliases.has(objectName) && propertyName === "Fragment") {
|
|
546
|
-
return true;
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
return false;
|
|
327
|
+
if (openingElement.isJSXFragment()) return true;
|
|
328
|
+
const elementName = getPathName$1(t, openingElement);
|
|
329
|
+
if (elementName === "Fragment" || elementName === "React.Fragment") return true;
|
|
330
|
+
if (context && elementName && context.fragmentAliases.has(elementName)) return true;
|
|
331
|
+
if (openingElement.node && "name" in openingElement.node && openingElement.node.name && typeof openingElement.node.name === "object" && "type" in openingElement.node.name && openingElement.node.name.type === "JSXMemberExpression") {
|
|
332
|
+
const nodeName = openingElement.node.name;
|
|
333
|
+
if (typeof nodeName !== "object" || !nodeName) return false;
|
|
334
|
+
if ("object" in nodeName && "property" in nodeName) {
|
|
335
|
+
const nodeNameObject = nodeName.object;
|
|
336
|
+
const nodeNameProperty = nodeName.property;
|
|
337
|
+
if (typeof nodeNameObject !== "object" || typeof nodeNameProperty !== "object") return false;
|
|
338
|
+
if (!nodeNameObject || !nodeNameProperty) return false;
|
|
339
|
+
const objectName = "name" in nodeNameObject && nodeNameObject.name;
|
|
340
|
+
const propertyName = "name" in nodeNameProperty && nodeNameProperty.name;
|
|
341
|
+
if (objectName === "React" && propertyName === "Fragment") return true;
|
|
342
|
+
if (context) {
|
|
343
|
+
if (context.reactNamespaceAliases.has(objectName) && propertyName === "Fragment") return true;
|
|
344
|
+
if (context.fragmentAliases.has(objectName) && propertyName === "Fragment") return true;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return false;
|
|
552
349
|
}
|
|
553
350
|
function hasAttributeWithName$1(openingElement, name) {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
return node.name.name === name;
|
|
560
|
-
}
|
|
561
|
-
return false;
|
|
562
|
-
});
|
|
351
|
+
if (!name) return false;
|
|
352
|
+
return openingElement.node.attributes.some((node) => {
|
|
353
|
+
if (node.type === "JSXAttribute") return node.name.name === name;
|
|
354
|
+
return false;
|
|
355
|
+
});
|
|
563
356
|
}
|
|
564
357
|
function getPathName$1(t, path) {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
if (t.isIdentifier(name) || t.isJSXIdentifier(name)) {
|
|
574
|
-
return name.name;
|
|
575
|
-
}
|
|
576
|
-
if (t.isJSXNamespacedName(name)) {
|
|
577
|
-
return name.name.name;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// Handle JSX member expressions like Tab.Group
|
|
581
|
-
if (t.isJSXMemberExpression(name)) {
|
|
582
|
-
var objectName = getJSXMemberExpressionObjectName$1(t, name.object);
|
|
583
|
-
var propertyName = name.property.name;
|
|
584
|
-
return "".concat(objectName, ".").concat(propertyName);
|
|
585
|
-
}
|
|
586
|
-
return UNKNOWN_ELEMENT_NAME$1;
|
|
358
|
+
if (!path.node) return UNKNOWN_ELEMENT_NAME$1;
|
|
359
|
+
if (!("name" in path.node)) return UNKNOWN_ELEMENT_NAME$1;
|
|
360
|
+
const name = path.node.name;
|
|
361
|
+
if (typeof name === "string") return name;
|
|
362
|
+
if (t.isIdentifier(name) || t.isJSXIdentifier(name)) return name.name;
|
|
363
|
+
if (t.isJSXNamespacedName(name)) return name.name.name;
|
|
364
|
+
if (t.isJSXMemberExpression(name)) return `${getJSXMemberExpressionObjectName$1(t, name.object)}.${name.property.name}`;
|
|
365
|
+
return UNKNOWN_ELEMENT_NAME$1;
|
|
587
366
|
}
|
|
588
|
-
|
|
589
|
-
// Recursively handle nested member expressions (e.g. Components.UI.Header)
|
|
590
367
|
function getJSXMemberExpressionObjectName$1(t, object) {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
368
|
+
if (t.isJSXIdentifier(object)) return object.name;
|
|
369
|
+
if (t.isJSXMemberExpression(object)) return `${getJSXMemberExpressionObjectName$1(t, object.object)}.${object.property.name}`;
|
|
370
|
+
return UNKNOWN_ELEMENT_NAME$1;
|
|
371
|
+
}
|
|
372
|
+
const UNKNOWN_ELEMENT_NAME$1 = "unknown";
|
|
373
|
+
|
|
374
|
+
//#endregion
|
|
375
|
+
//#region src/index.ts
|
|
376
|
+
const webComponentName = "data-sentry-component";
|
|
377
|
+
const webElementName = "data-sentry-element";
|
|
378
|
+
const webSourceFileName = "data-sentry-source-file";
|
|
379
|
+
const nativeComponentName = "dataSentryComponent";
|
|
380
|
+
const nativeElementName = "dataSentryElement";
|
|
381
|
+
const nativeSourceFileName = "dataSentrySourceFile";
|
|
382
|
+
function componentNameAnnotatePlugin({ types: t }) {
|
|
383
|
+
return { visitor: {
|
|
384
|
+
Program: { enter(path, state) {
|
|
385
|
+
state.sentryFragmentContext = collectFragmentContext(path);
|
|
386
|
+
} },
|
|
387
|
+
FunctionDeclaration(path, state) {
|
|
388
|
+
if (!path.node.id || !path.node.id.name) return;
|
|
389
|
+
if (isKnownIncompatiblePluginFromState(state)) return;
|
|
390
|
+
functionBodyPushAttributes(createJSXProcessingContext(state, t, path.node.id.name), path);
|
|
391
|
+
},
|
|
392
|
+
ArrowFunctionExpression(path, state) {
|
|
393
|
+
const parent = path.parent;
|
|
394
|
+
if (!parent || !("id" in parent) || !parent.id || !("name" in parent.id) || !parent.id.name) return;
|
|
395
|
+
if (isKnownIncompatiblePluginFromState(state)) return;
|
|
396
|
+
functionBodyPushAttributes(createJSXProcessingContext(state, t, parent.id.name), path);
|
|
397
|
+
},
|
|
398
|
+
ClassDeclaration(path, state) {
|
|
399
|
+
const name = path.get("id");
|
|
400
|
+
const render = path.get("body").get("body").find((prop) => {
|
|
401
|
+
return prop.isClassMethod() && prop.get("key").isIdentifier({ name: "render" });
|
|
402
|
+
});
|
|
403
|
+
if (!render || !render.traverse || isKnownIncompatiblePluginFromState(state)) return;
|
|
404
|
+
const context = createJSXProcessingContext(state, t, name.node?.name || "");
|
|
405
|
+
render.traverse({ ReturnStatement(returnStatement) {
|
|
406
|
+
const arg = returnStatement.get("argument");
|
|
407
|
+
if (!arg.isJSXElement() && !arg.isJSXFragment()) return;
|
|
408
|
+
processJSX(context, arg);
|
|
409
|
+
} });
|
|
410
|
+
}
|
|
411
|
+
} };
|
|
599
412
|
}
|
|
600
|
-
var UNKNOWN_ELEMENT_NAME$1 = "unknown";
|
|
601
|
-
|
|
602
|
-
var webComponentName = "data-sentry-component";
|
|
603
|
-
var webElementName = "data-sentry-element";
|
|
604
|
-
var webSourceFileName = "data-sentry-source-file";
|
|
605
|
-
var nativeComponentName = "dataSentryComponent";
|
|
606
|
-
var nativeElementName = "dataSentryElement";
|
|
607
|
-
var nativeSourceFileName = "dataSentrySourceFile";
|
|
608
|
-
|
|
609
|
-
// We must export the plugin as default, otherwise the Babel loader will not be able to resolve it when configured using its string identifier
|
|
610
|
-
function componentNameAnnotatePlugin(_ref) {
|
|
611
|
-
var t = _ref.types;
|
|
612
|
-
return {
|
|
613
|
-
visitor: {
|
|
614
|
-
Program: {
|
|
615
|
-
enter: function enter(path, state) {
|
|
616
|
-
var fragmentContext = collectFragmentContext(path);
|
|
617
|
-
state.sentryFragmentContext = fragmentContext;
|
|
618
|
-
}
|
|
619
|
-
},
|
|
620
|
-
FunctionDeclaration: function FunctionDeclaration(path, state) {
|
|
621
|
-
if (!path.node.id || !path.node.id.name) {
|
|
622
|
-
return;
|
|
623
|
-
}
|
|
624
|
-
if (isKnownIncompatiblePluginFromState(state)) {
|
|
625
|
-
return;
|
|
626
|
-
}
|
|
627
|
-
var context = createJSXProcessingContext(state, t, path.node.id.name);
|
|
628
|
-
functionBodyPushAttributes(context, path);
|
|
629
|
-
},
|
|
630
|
-
ArrowFunctionExpression: function ArrowFunctionExpression(path, state) {
|
|
631
|
-
// We're expecting a `VariableDeclarator` like `const MyComponent =`
|
|
632
|
-
var parent = path.parent;
|
|
633
|
-
if (!parent || !("id" in parent) || !parent.id || !("name" in parent.id) || !parent.id.name) {
|
|
634
|
-
return;
|
|
635
|
-
}
|
|
636
|
-
if (isKnownIncompatiblePluginFromState(state)) {
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
639
|
-
var context = createJSXProcessingContext(state, t, parent.id.name);
|
|
640
|
-
functionBodyPushAttributes(context, path);
|
|
641
|
-
},
|
|
642
|
-
ClassDeclaration: function ClassDeclaration(path, state) {
|
|
643
|
-
var _name$node;
|
|
644
|
-
var name = path.get("id");
|
|
645
|
-
var properties = path.get("body").get("body");
|
|
646
|
-
var render = properties.find(function (prop) {
|
|
647
|
-
return prop.isClassMethod() && prop.get("key").isIdentifier({
|
|
648
|
-
name: "render"
|
|
649
|
-
});
|
|
650
|
-
});
|
|
651
|
-
if (!render || !render.traverse || isKnownIncompatiblePluginFromState(state)) {
|
|
652
|
-
return;
|
|
653
|
-
}
|
|
654
|
-
var context = createJSXProcessingContext(state, t, ((_name$node = name.node) === null || _name$node === void 0 ? void 0 : _name$node.name) || "");
|
|
655
|
-
render.traverse({
|
|
656
|
-
ReturnStatement: function ReturnStatement(returnStatement) {
|
|
657
|
-
var arg = returnStatement.get("argument");
|
|
658
|
-
if (!arg.isJSXElement() && !arg.isJSXFragment()) {
|
|
659
|
-
return;
|
|
660
|
-
}
|
|
661
|
-
processJSX(context, arg);
|
|
662
|
-
}
|
|
663
|
-
});
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
|
-
|
|
669
413
|
/**
|
|
670
|
-
|
|
671
|
-
|
|
414
|
+
* Creates a JSX processing context from the plugin state
|
|
415
|
+
*/
|
|
672
416
|
function createJSXProcessingContext(state, t, componentName) {
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
};
|
|
417
|
+
return {
|
|
418
|
+
annotateFragments: state.opts["annotate-fragments"] === true,
|
|
419
|
+
t,
|
|
420
|
+
componentName,
|
|
421
|
+
sourceFileName: sourceFileNameFromState(state),
|
|
422
|
+
attributeNames: attributeNamesFromState(state),
|
|
423
|
+
ignoredComponents: state.opts.ignoredComponents ?? [],
|
|
424
|
+
fragmentContext: state.sentryFragmentContext
|
|
425
|
+
};
|
|
683
426
|
}
|
|
684
|
-
|
|
685
427
|
/**
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
428
|
+
* Processes the body of a function to add Sentry tracking attributes to JSX elements.
|
|
429
|
+
* Handles various function body structures including direct JSX returns, conditional expressions,
|
|
430
|
+
* and nested JSX elements.
|
|
431
|
+
*/
|
|
690
432
|
function functionBodyPushAttributes(context, path) {
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
var consequent = arg.get("consequent");
|
|
720
|
-
if (consequent.isJSXFragment() || consequent.isJSXElement()) {
|
|
721
|
-
processJSX(context, consequent);
|
|
722
|
-
}
|
|
723
|
-
var alternate = arg.get("alternate");
|
|
724
|
-
if (alternate.isJSXFragment() || alternate.isJSXElement()) {
|
|
725
|
-
processJSX(context, alternate);
|
|
726
|
-
}
|
|
727
|
-
return;
|
|
728
|
-
}
|
|
729
|
-
if (!arg.isJSXFragment() && !arg.isJSXElement()) {
|
|
730
|
-
return;
|
|
731
|
-
}
|
|
732
|
-
jsxNode = arg;
|
|
733
|
-
}
|
|
734
|
-
if (!jsxNode) {
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
processJSX(context, jsxNode);
|
|
433
|
+
let jsxNode;
|
|
434
|
+
const functionBody = path.get("body").get("body");
|
|
435
|
+
if (!("length" in functionBody) && functionBody.parent && (functionBody.parent.type === "JSXElement" || functionBody.parent.type === "JSXFragment")) {
|
|
436
|
+
const maybeJsxNode = functionBody.find((c) => {
|
|
437
|
+
return c.type === "JSXElement" || c.type === "JSXFragment";
|
|
438
|
+
});
|
|
439
|
+
if (!maybeJsxNode) return;
|
|
440
|
+
jsxNode = maybeJsxNode;
|
|
441
|
+
} else {
|
|
442
|
+
const returnStatement = functionBody.find((c) => {
|
|
443
|
+
return c.type === "ReturnStatement";
|
|
444
|
+
});
|
|
445
|
+
if (!returnStatement) return;
|
|
446
|
+
const arg = returnStatement.get("argument");
|
|
447
|
+
if (!arg) return;
|
|
448
|
+
if (Array.isArray(arg)) return;
|
|
449
|
+
if (arg.isConditionalExpression()) {
|
|
450
|
+
const consequent = arg.get("consequent");
|
|
451
|
+
if (consequent.isJSXFragment() || consequent.isJSXElement()) processJSX(context, consequent);
|
|
452
|
+
const alternate = arg.get("alternate");
|
|
453
|
+
if (alternate.isJSXFragment() || alternate.isJSXElement()) processJSX(context, alternate);
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
if (!arg.isJSXFragment() && !arg.isJSXElement()) return;
|
|
457
|
+
jsxNode = arg;
|
|
458
|
+
}
|
|
459
|
+
if (!jsxNode) return;
|
|
460
|
+
processJSX(context, jsxNode);
|
|
738
461
|
}
|
|
739
|
-
|
|
740
462
|
/**
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
463
|
+
* Recursively processes JSX elements to add Sentry tracking attributes.
|
|
464
|
+
* Handles both JSX elements and fragments, applying appropriate attributes
|
|
465
|
+
* based on configuration and component context.
|
|
466
|
+
*/
|
|
745
467
|
function processJSX(context, jsxNode, componentName) {
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
children = [children];
|
|
765
|
-
}
|
|
766
|
-
var shouldSetComponentName = context.annotateFragments;
|
|
767
|
-
children.forEach(function (child) {
|
|
768
|
-
// Happens for some node types like plain text
|
|
769
|
-
if (!child.node) {
|
|
770
|
-
return;
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
// Children don't receive the data-component attribute so we pass null for componentName unless it's the first child of a Fragment with a node and `annotateFragments` is true
|
|
774
|
-
var openingElement = child.get("openingElement");
|
|
775
|
-
// TODO: Improve this. We never expect to have multiple opening elements
|
|
776
|
-
// but if it's possible, this should work
|
|
777
|
-
if (Array.isArray(openingElement)) {
|
|
778
|
-
return;
|
|
779
|
-
}
|
|
780
|
-
if (shouldSetComponentName && openingElement && openingElement.node) {
|
|
781
|
-
shouldSetComponentName = false;
|
|
782
|
-
processJSX(context, child, currentComponentName);
|
|
783
|
-
} else {
|
|
784
|
-
processJSX(context, child, "");
|
|
785
|
-
}
|
|
786
|
-
});
|
|
468
|
+
if (!jsxNode) return;
|
|
469
|
+
const currentComponentName = componentName ?? context.componentName;
|
|
470
|
+
const paths = jsxNode.get("openingElement");
|
|
471
|
+
(Array.isArray(paths) ? paths : [paths]).forEach((openingElement) => {
|
|
472
|
+
applyAttributes(context, openingElement, currentComponentName);
|
|
473
|
+
});
|
|
474
|
+
let children = jsxNode.get("children");
|
|
475
|
+
if (children && !("length" in children)) children = [children];
|
|
476
|
+
let shouldSetComponentName = context.annotateFragments;
|
|
477
|
+
children.forEach((child) => {
|
|
478
|
+
if (!child.node) return;
|
|
479
|
+
const openingElement = child.get("openingElement");
|
|
480
|
+
if (Array.isArray(openingElement)) return;
|
|
481
|
+
if (shouldSetComponentName && openingElement && openingElement.node) {
|
|
482
|
+
shouldSetComponentName = false;
|
|
483
|
+
processJSX(context, child, currentComponentName);
|
|
484
|
+
} else processJSX(context, child, "");
|
|
485
|
+
});
|
|
787
486
|
}
|
|
788
|
-
|
|
789
487
|
/**
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
488
|
+
* Applies Sentry tracking attributes to a JSX opening element.
|
|
489
|
+
* Adds component name, element name, and source file attributes while
|
|
490
|
+
* respecting ignore lists and fragment detection.
|
|
491
|
+
*/
|
|
794
492
|
function applyAttributes(context, openingElement, componentName) {
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
return;
|
|
814
|
-
}
|
|
815
|
-
if (!openingElement.node.attributes) openingElement.node.attributes = [];
|
|
816
|
-
var elementName = getPathName(t, openingElement);
|
|
817
|
-
var isAnIgnoredComponent = ignoredComponents.some(function (ignoredComponent) {
|
|
818
|
-
return ignoredComponent === componentName || ignoredComponent === elementName;
|
|
819
|
-
});
|
|
820
|
-
|
|
821
|
-
// Add a stable attribute for the element name but only for non-DOM names
|
|
822
|
-
var isAnIgnoredElement = false;
|
|
823
|
-
if (!isAnIgnoredComponent && !hasAttributeWithName(openingElement, elementAttributeName)) {
|
|
824
|
-
if (DEFAULT_IGNORED_ELEMENTS.includes(elementName)) {
|
|
825
|
-
isAnIgnoredElement = true;
|
|
826
|
-
} else {
|
|
827
|
-
// Always add element attribute for non-ignored elements
|
|
828
|
-
if (elementAttributeName) {
|
|
829
|
-
openingElement.node.attributes.push(t.jSXAttribute(t.jSXIdentifier(elementAttributeName), t.stringLiteral(elementName)));
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
// Add a stable attribute for the component name (absent for non-root elements)
|
|
835
|
-
if (componentName && !isAnIgnoredComponent && !hasAttributeWithName(openingElement, componentAttributeName)) {
|
|
836
|
-
if (componentAttributeName) {
|
|
837
|
-
openingElement.node.attributes.push(t.jSXAttribute(t.jSXIdentifier(componentAttributeName), t.stringLiteral(componentName)));
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
// Add a stable attribute for the source file name
|
|
842
|
-
// Updated condition: add source file for elements that have either:
|
|
843
|
-
// 1. A component name (root elements), OR
|
|
844
|
-
// 2. An element name that's not ignored (child elements)
|
|
845
|
-
if (sourceFileName && !isAnIgnoredComponent && (componentName || !isAnIgnoredElement) && !hasAttributeWithName(openingElement, sourceFileAttributeName)) {
|
|
846
|
-
if (sourceFileAttributeName) {
|
|
847
|
-
openingElement.node.attributes.push(t.jSXAttribute(t.jSXIdentifier(sourceFileAttributeName), t.stringLiteral(sourceFileName)));
|
|
848
|
-
}
|
|
849
|
-
}
|
|
493
|
+
const { t, attributeNames, ignoredComponents, fragmentContext, sourceFileName } = context;
|
|
494
|
+
const [componentAttributeName, elementAttributeName, sourceFileAttributeName] = attributeNames;
|
|
495
|
+
if (!openingElement.node) return;
|
|
496
|
+
if (isReactFragment(t, openingElement, fragmentContext)) return;
|
|
497
|
+
if (!openingElement.node.attributes) openingElement.node.attributes = [];
|
|
498
|
+
const elementName = getPathName(t, openingElement);
|
|
499
|
+
const isAnIgnoredComponent = ignoredComponents.some((ignoredComponent) => ignoredComponent === componentName || ignoredComponent === elementName);
|
|
500
|
+
let isAnIgnoredElement = false;
|
|
501
|
+
if (!isAnIgnoredComponent && !hasAttributeWithName(openingElement, elementAttributeName)) {
|
|
502
|
+
if (DEFAULT_IGNORED_ELEMENTS.includes(elementName)) isAnIgnoredElement = true;
|
|
503
|
+
else if (elementAttributeName) openingElement.node.attributes.push(t.jSXAttribute(t.jSXIdentifier(elementAttributeName), t.stringLiteral(elementName)));
|
|
504
|
+
}
|
|
505
|
+
if (componentName && !isAnIgnoredComponent && !hasAttributeWithName(openingElement, componentAttributeName)) {
|
|
506
|
+
if (componentAttributeName) openingElement.node.attributes.push(t.jSXAttribute(t.jSXIdentifier(componentAttributeName), t.stringLiteral(componentName)));
|
|
507
|
+
}
|
|
508
|
+
if (sourceFileName && !isAnIgnoredComponent && (componentName || !isAnIgnoredElement) && !hasAttributeWithName(openingElement, sourceFileAttributeName)) {
|
|
509
|
+
if (sourceFileAttributeName) openingElement.node.attributes.push(t.jSXAttribute(t.jSXIdentifier(sourceFileAttributeName), t.stringLiteral(sourceFileName)));
|
|
510
|
+
}
|
|
850
511
|
}
|
|
851
512
|
function sourceFileNameFromState(state) {
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
return name.split("/").pop();
|
|
858
|
-
} else if (name.indexOf("\\") !== -1) {
|
|
859
|
-
return name.split("\\").pop();
|
|
860
|
-
} else {
|
|
861
|
-
return name;
|
|
862
|
-
}
|
|
513
|
+
const name = fullSourceFileNameFromState(state);
|
|
514
|
+
if (!name) return;
|
|
515
|
+
if (name.indexOf("/") !== -1) return name.split("/").pop();
|
|
516
|
+
else if (name.indexOf("\\") !== -1) return name.split("\\").pop();
|
|
517
|
+
else return name;
|
|
863
518
|
}
|
|
864
519
|
function fullSourceFileNameFromState(state) {
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
if (typeof name === "string") {
|
|
869
|
-
return name;
|
|
870
|
-
}
|
|
871
|
-
return null;
|
|
520
|
+
const name = state.file.opts.parserOpts?.sourceFileName;
|
|
521
|
+
if (typeof name === "string") return name;
|
|
522
|
+
return null;
|
|
872
523
|
}
|
|
873
524
|
function isKnownIncompatiblePluginFromState(state) {
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
return true;
|
|
881
|
-
}
|
|
882
|
-
return false;
|
|
883
|
-
});
|
|
525
|
+
const fullSourceFileName = fullSourceFileNameFromState(state);
|
|
526
|
+
if (!fullSourceFileName) return false;
|
|
527
|
+
return KNOWN_INCOMPATIBLE_PLUGINS.some((pluginName) => {
|
|
528
|
+
if (fullSourceFileName.includes(`/node_modules/${pluginName}/`) || fullSourceFileName.includes(`\\node_modules\\${pluginName}\\`)) return true;
|
|
529
|
+
return false;
|
|
530
|
+
});
|
|
884
531
|
}
|
|
885
532
|
function attributeNamesFromState(state) {
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
533
|
+
if (state.opts.native) return [
|
|
534
|
+
nativeComponentName,
|
|
535
|
+
nativeElementName,
|
|
536
|
+
nativeSourceFileName
|
|
537
|
+
];
|
|
538
|
+
return [
|
|
539
|
+
webComponentName,
|
|
540
|
+
webElementName,
|
|
541
|
+
webSourceFileName
|
|
542
|
+
];
|
|
890
543
|
}
|
|
891
544
|
function collectFragmentContext(programPath) {
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
// Handle: const MyFragment = Fragment (only if Fragment is a known alias)
|
|
924
|
-
if (init.type === "Identifier" && fragmentAliases.has(init.name)) {
|
|
925
|
-
fragmentAliases.add(varPath.node.id.name);
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
// Handle: const MyFragment = React.Fragment (only for known React namespaces)
|
|
929
|
-
if (init.type === "MemberExpression" && init.object.type === "Identifier" && init.property.type === "Identifier" && init.property.name === "Fragment" && reactNamespaceAliases.has(init.object.name)) {
|
|
930
|
-
fragmentAliases.add(varPath.node.id.name);
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
// Handle destructuring assignments: const { Fragment } = React
|
|
935
|
-
if (varPath.node.id.type === "ObjectPattern") {
|
|
936
|
-
if (init.type === "Identifier" && reactNamespaceAliases.has(init.name)) {
|
|
937
|
-
var properties = varPath.node.id.properties;
|
|
938
|
-
var _iterator = _createForOfIteratorHelper(properties),
|
|
939
|
-
_step;
|
|
940
|
-
try {
|
|
941
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
942
|
-
var prop = _step.value;
|
|
943
|
-
if (prop.type === "ObjectProperty" && prop.key && prop.key.type === "Identifier" && prop.value && prop.value.type === "Identifier" && prop.key.name === "Fragment") {
|
|
944
|
-
fragmentAliases.add(prop.value.name);
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
} catch (err) {
|
|
948
|
-
_iterator.e(err);
|
|
949
|
-
} finally {
|
|
950
|
-
_iterator.f();
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
});
|
|
957
|
-
return {
|
|
958
|
-
fragmentAliases: fragmentAliases,
|
|
959
|
-
reactNamespaceAliases: reactNamespaceAliases
|
|
960
|
-
};
|
|
545
|
+
const fragmentAliases = /* @__PURE__ */ new Set();
|
|
546
|
+
const reactNamespaceAliases = new Set(["React"]);
|
|
547
|
+
programPath.traverse({
|
|
548
|
+
ImportDeclaration(importPath) {
|
|
549
|
+
const source = importPath.node.source.value;
|
|
550
|
+
if (source === "react" || source === "React") importPath.node.specifiers.forEach((spec) => {
|
|
551
|
+
if (spec.type === "ImportSpecifier" && spec.imported.type === "Identifier") {
|
|
552
|
+
if (spec.imported.name === "Fragment") fragmentAliases.add(spec.local.name);
|
|
553
|
+
} else if (spec.type === "ImportDefaultSpecifier" || spec.type === "ImportNamespaceSpecifier") reactNamespaceAliases.add(spec.local.name);
|
|
554
|
+
});
|
|
555
|
+
},
|
|
556
|
+
VariableDeclarator(varPath) {
|
|
557
|
+
if (varPath.node.init) {
|
|
558
|
+
const init = varPath.node.init;
|
|
559
|
+
if (varPath.node.id.type === "Identifier") {
|
|
560
|
+
if (init.type === "Identifier" && fragmentAliases.has(init.name)) fragmentAliases.add(varPath.node.id.name);
|
|
561
|
+
if (init.type === "MemberExpression" && init.object.type === "Identifier" && init.property.type === "Identifier" && init.property.name === "Fragment" && reactNamespaceAliases.has(init.object.name)) fragmentAliases.add(varPath.node.id.name);
|
|
562
|
+
}
|
|
563
|
+
if (varPath.node.id.type === "ObjectPattern") {
|
|
564
|
+
if (init.type === "Identifier" && reactNamespaceAliases.has(init.name)) {
|
|
565
|
+
const properties = varPath.node.id.properties;
|
|
566
|
+
for (const prop of properties) if (prop.type === "ObjectProperty" && prop.key && prop.key.type === "Identifier" && prop.value && prop.value.type === "Identifier" && prop.key.name === "Fragment") fragmentAliases.add(prop.value.name);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
return {
|
|
573
|
+
fragmentAliases,
|
|
574
|
+
reactNamespaceAliases
|
|
575
|
+
};
|
|
961
576
|
}
|
|
962
577
|
function isReactFragment(t, openingElement, context) {
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
return false;
|
|
986
|
-
}
|
|
987
|
-
if ("object" in nodeName && "property" in nodeName) {
|
|
988
|
-
var nodeNameObject = nodeName.object;
|
|
989
|
-
var nodeNameProperty = nodeName.property;
|
|
990
|
-
if (_typeof(nodeNameObject) !== "object" || _typeof(nodeNameProperty) !== "object") {
|
|
991
|
-
return false;
|
|
992
|
-
}
|
|
993
|
-
if (!nodeNameObject || !nodeNameProperty) {
|
|
994
|
-
return false;
|
|
995
|
-
}
|
|
996
|
-
var objectName = "name" in nodeNameObject && nodeNameObject.name;
|
|
997
|
-
var propertyName = "name" in nodeNameProperty && nodeNameProperty.name;
|
|
998
|
-
|
|
999
|
-
// React.Fragment check
|
|
1000
|
-
if (objectName === "React" && propertyName === "Fragment") {
|
|
1001
|
-
return true;
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
// Enhanced checks using context
|
|
1005
|
-
if (context) {
|
|
1006
|
-
// Check React.Fragment pattern with known React namespaces
|
|
1007
|
-
if (context.reactNamespaceAliases.has(objectName) && propertyName === "Fragment") {
|
|
1008
|
-
return true;
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
// Check MyFragment.Fragment pattern
|
|
1012
|
-
if (context.fragmentAliases.has(objectName) && propertyName === "Fragment") {
|
|
1013
|
-
return true;
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
return false;
|
|
578
|
+
if (openingElement.isJSXFragment()) return true;
|
|
579
|
+
const elementName = getPathName(t, openingElement);
|
|
580
|
+
if (elementName === "Fragment" || elementName === "React.Fragment") return true;
|
|
581
|
+
if (context && elementName && context.fragmentAliases.has(elementName)) return true;
|
|
582
|
+
if (openingElement.node && "name" in openingElement.node && openingElement.node.name && typeof openingElement.node.name === "object" && "type" in openingElement.node.name && openingElement.node.name.type === "JSXMemberExpression") {
|
|
583
|
+
const nodeName = openingElement.node.name;
|
|
584
|
+
if (typeof nodeName !== "object" || !nodeName) return false;
|
|
585
|
+
if ("object" in nodeName && "property" in nodeName) {
|
|
586
|
+
const nodeNameObject = nodeName.object;
|
|
587
|
+
const nodeNameProperty = nodeName.property;
|
|
588
|
+
if (typeof nodeNameObject !== "object" || typeof nodeNameProperty !== "object") return false;
|
|
589
|
+
if (!nodeNameObject || !nodeNameProperty) return false;
|
|
590
|
+
const objectName = "name" in nodeNameObject && nodeNameObject.name;
|
|
591
|
+
const propertyName = "name" in nodeNameProperty && nodeNameProperty.name;
|
|
592
|
+
if (objectName === "React" && propertyName === "Fragment") return true;
|
|
593
|
+
if (context) {
|
|
594
|
+
if (context.reactNamespaceAliases.has(objectName) && propertyName === "Fragment") return true;
|
|
595
|
+
if (context.fragmentAliases.has(objectName) && propertyName === "Fragment") return true;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
return false;
|
|
1019
600
|
}
|
|
1020
601
|
function hasAttributeWithName(openingElement, name) {
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
return node.name.name === name;
|
|
1027
|
-
}
|
|
1028
|
-
return false;
|
|
1029
|
-
});
|
|
602
|
+
if (!name) return false;
|
|
603
|
+
return openingElement.node.attributes.some((node) => {
|
|
604
|
+
if (node.type === "JSXAttribute") return node.name.name === name;
|
|
605
|
+
return false;
|
|
606
|
+
});
|
|
1030
607
|
}
|
|
1031
608
|
function getPathName(t, path) {
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
if (t.isIdentifier(name) || t.isJSXIdentifier(name)) {
|
|
1041
|
-
return name.name;
|
|
1042
|
-
}
|
|
1043
|
-
if (t.isJSXNamespacedName(name)) {
|
|
1044
|
-
return name.name.name;
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
// Handle JSX member expressions like Tab.Group
|
|
1048
|
-
if (t.isJSXMemberExpression(name)) {
|
|
1049
|
-
var objectName = getJSXMemberExpressionObjectName(t, name.object);
|
|
1050
|
-
var propertyName = name.property.name;
|
|
1051
|
-
return "".concat(objectName, ".").concat(propertyName);
|
|
1052
|
-
}
|
|
1053
|
-
return UNKNOWN_ELEMENT_NAME;
|
|
609
|
+
if (!path.node) return UNKNOWN_ELEMENT_NAME;
|
|
610
|
+
if (!("name" in path.node)) return UNKNOWN_ELEMENT_NAME;
|
|
611
|
+
const name = path.node.name;
|
|
612
|
+
if (typeof name === "string") return name;
|
|
613
|
+
if (t.isIdentifier(name) || t.isJSXIdentifier(name)) return name.name;
|
|
614
|
+
if (t.isJSXNamespacedName(name)) return name.name.name;
|
|
615
|
+
if (t.isJSXMemberExpression(name)) return `${getJSXMemberExpressionObjectName(t, name.object)}.${name.property.name}`;
|
|
616
|
+
return UNKNOWN_ELEMENT_NAME;
|
|
1054
617
|
}
|
|
1055
|
-
|
|
1056
|
-
// Recursively handle nested member expressions (e.g. Components.UI.Header)
|
|
1057
618
|
function getJSXMemberExpressionObjectName(t, object) {
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
if (t.isJSXMemberExpression(object)) {
|
|
1062
|
-
var objectName = getJSXMemberExpressionObjectName(t, object.object);
|
|
1063
|
-
return "".concat(objectName, ".").concat(object.property.name);
|
|
1064
|
-
}
|
|
1065
|
-
return UNKNOWN_ELEMENT_NAME;
|
|
619
|
+
if (t.isJSXIdentifier(object)) return object.name;
|
|
620
|
+
if (t.isJSXMemberExpression(object)) return `${getJSXMemberExpressionObjectName(t, object.object)}.${object.property.name}`;
|
|
621
|
+
return UNKNOWN_ELEMENT_NAME;
|
|
1066
622
|
}
|
|
1067
|
-
|
|
623
|
+
const UNKNOWN_ELEMENT_NAME = "unknown";
|
|
1068
624
|
|
|
1069
|
-
|
|
625
|
+
//#endregion
|
|
626
|
+
exports.default = componentNameAnnotatePlugin;
|
|
1070
627
|
exports.experimentalComponentNameAnnotatePlugin = experimentalComponentNameAnnotatePlugin;
|
|
1071
|
-
//# sourceMappingURL=index.js.map
|
|
628
|
+
//# sourceMappingURL=index.js.map
|