Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@fullstory/babel-plugin-react-native

Package Overview
Dependencies
Maintainers
2
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fullstory/babel-plugin-react-native - npm Package Compare versions

Comparing version 1.0.3 to 1.1.0

179

lib/index.js

@@ -6,36 +6,13 @@ "use strict";

});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
exports.default = function (_ref) {
var t = _ref.types;
return {
visitor: {
/* Looks like we don't currently need to add this to the interface declaration
InterfaceDeclaration(path, state) {
fixUIManagerJSInterface(path);
}, */
ClassDeclaration: function ClassDeclaration(path, state) {
fixPressability(t, path);
},
VariableDeclaration: function VariableDeclaration(path, state) {
fixReactNativeViewConfig(path);
fixReactNativeViewAttributes(path);
fixTouchableMixin(t, path);
}
}
};
exports.default = _default;
var babylon = _interopRequireWildcard(require("@babel/parser"));
var t = _interopRequireWildcard(require("@babel/types"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
// We only add our ref to all Symbol(react.forward_ref) and Symbol(react.element) types, since they support refs
var _createFabricRefCode = function _createFabricRefCode(refIdentifier, typeIdentifier, propsIdentifier) {
return "\n const SUPPORTED_FS_ATTRIBUTES = [\n 'fsClass',\n 'fsAttribute',\n 'fsTagName',\n 'dataElement',\n 'dataComponent',\n 'dataSourceFile',\n ]; \n if (global.__turboModuleProxy != null && Platform.OS === 'ios') {\n if (".concat(typeIdentifier, ".$$typeof && (").concat(typeIdentifier, ".$$typeof.toString() === 'Symbol(react.forward_ref)' || ").concat(typeIdentifier, ".$$typeof.toString() === 'Symbol(react.element)')) {\n if (").concat(propsIdentifier, ") {\n const propContainsFSAttribute = SUPPORTED_FS_ATTRIBUTES.some(fsAttribute => {\n return typeof ").concat(propsIdentifier, "[fsAttribute] === 'string' && !!").concat(propsIdentifier, "[fsAttribute];\n });\n \n if (propContainsFSAttribute) {\n const fs = require('@fullstory/react-native');\n ").concat(refIdentifier, " = fs.applyFSPropertiesWithRef(").concat(refIdentifier, ");\n }\n }\n }\n }");
};
var _parser = require("@babel/parser");
var babylon = _interopRequireWildcard(_parser);
var _types = require("@babel/types");
var t = _interopRequireWildcard(_types);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
// This is the code that we will generate for Pressability.

@@ -46,3 +23,2 @@ // Note that `typeof UIManager` will cause an exception, so we use a try/catch.

var _onFsPressForwardCallPress_PressabilityCode = "this._onFsPressForward_Pressability(false)";
var _onFsPressForward_PressabilityAst = babylon.parseExpression(_onFsPressForward_PressabilityCode, {});

@@ -57,3 +33,2 @@ var _onFsPressForwardCallLongPress_PressabilityAst = babylon.parseExpression(_onFsPressForwardCallLongPress_PressabilityCode, {});

var _onFsPressForwardCallPressCode = "this._onFsPressForward(false)";
var _onFsPressForwardAst = babylon.parseExpression(_onFsPressForwardCode, {});

@@ -66,6 +41,5 @@ var _onFsPressForwardCallLongPressAst = babylon.parseExpression(_onFsPressForwardCallLongPressCode, {});

var indent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
var cache = [];
var retVal = JSON.stringify(obj, function (key, value) {
return (typeof value === "undefined" ? "undefined" : _typeof(value)) === 'object' && value !== null ? cache.includes(value) ? undefined // Duplicate reference found, discard key
return _typeof(value) === 'object' && value !== null ? cache.includes(value) ? undefined // Duplicate reference found, discard key
: cache.push(value) && value // Store value in our collection

@@ -77,3 +51,2 @@ : value;

}
function addFullStoryPressHandlerDeclaration(props) {

@@ -84,3 +57,2 @@ var prop = {};

prop.value = {};
prop.value.type = 'FunctionTypeAnnotation';

@@ -92,14 +64,10 @@ prop.value.params = [];

prop.value.params.push(t.functionTypeParam(t.identifier('hasLongPressHandler'), t.booleanTypeAnnotation()));
prop.value.rest = null;
prop.value.returnType = t.voidTypeAnnotation();
prop.value.typeParameters = null;
prop.optional = false;
prop.static = false;
prop.variance = null;
props.push(prop);
}
function addFullStoryProperties(properties) {

@@ -124,3 +92,2 @@ // add fsAttribute

}
function fixReactNativeViewConfig(path) {

@@ -131,3 +98,2 @@ // make sure that this path has a node with a declarations array of size 1

}
var declaration = path.node.declarations[0];

@@ -143,3 +109,2 @@ // validate that there is a name node and its value is what we expect

}
var props = declaration.init.properties;

@@ -162,3 +127,2 @@ for (var i = 0; i < props.length; i++) {

}
function fixReactNativeViewAttributes(path) {

@@ -169,3 +133,2 @@ // make sure that this path has a node with a declarations array of size 1

}
var declaration = path.node.declarations[0];

@@ -181,3 +144,2 @@ // validate that there is a name node and its value is what we expect

}
var props = declaration.init.properties;

@@ -195,3 +157,2 @@ for (var i = 0; i < props.length; i++) {

}
function fixUIManagerJSInterface(path) {

@@ -207,3 +168,2 @@ // make sure that this path has a node with an id named what we expect

}
for (var i = 0; i < path.node.body.properties.length; i++) {

@@ -220,3 +180,2 @@ var key = path.node.body.properties[i].key;

}
function fixPressability(t, path) {

@@ -232,3 +191,2 @@ // make sure that this path has a node with an id named what we expect

}
var bodyArray = path.node.body.body;

@@ -258,3 +216,3 @@

// now add the new ClassMethod to the bodyArray
bodyArray.push(t.classMethod("method", t.identifier("_onFsPressForward_Pressability"), _onFsPressForward_PressabilityAst.right.params, _onFsPressForward_PressabilityAst.right.body, false, false));
bodyArray.push(t.classMethod('method', t.identifier('_onFsPressForward_Pressability'), _onFsPressForward_PressabilityAst.right.params, _onFsPressForward_PressabilityAst.right.body, false, false));
} else {

@@ -267,3 +225,2 @@ // skip further processing on this object property

}
function fixTouchableMixin(t, path) {

@@ -274,3 +231,2 @@ // make sure that this path has a node with a declarations array

}
var mixin = null;

@@ -319,3 +275,3 @@ for (var i = 0; i < path.node.declarations.length; i++) {

// now add the new ObjectProperty to the parent path
mixin.init.properties.push(t.objectProperty(t.identifier("_onFsPressForward"), _onFsPressForwardAst.right));
mixin.init.properties.push(t.objectProperty(t.identifier('_onFsPressForward'), _onFsPressForwardAst.right));
} else {

@@ -328,3 +284,112 @@ // skip further processing on this object property

}
function extendReactElementWithRef(path) {
/* We're looking for the bit where react actually creates a ReactElement.
* We identify this by it being an object that has a ref property, and
* then after that, we verify that there is a $$typeof property that is
* the magic ReactElement. i.e., we're looking for a whole object with:
*
* var blah1 = Symbol.for('react.element');
* [...]
* var blah2;
* { $$typeof: blah1, ..., ref: blah2, ... }
*/
/* eslint-disable complexity */
// Are we actually looking at the ref: in there, and does it refer to a single variable?
if (path.node.key.name !== 'ref' || !t.isIdentifier(path.node.value)) {
return;
}
// Make sure that we have the $$typeof as a sibling, and it has a variable
// reference as its contents.
var typeofIdentifierNode = path.parentPath.node.properties.find(function (property) {
return t.isObjectProperty(property) && property.key.name === '$$typeof';
});
if (!typeofIdentifierNode || !t.isIdentifier(typeofIdentifierNode.value)) {
return;
}
// In this case, the typeofDeclPath points to the 'var blah1' declaration
// in the above snippet; make sure it's of the form we expect it to be.
var typeofDeclPath = path.scope.getBinding(typeofIdentifierNode.value.name).path;
if (!t.isVariableDeclarator(typeofDeclPath.node) || !t.isCallExpression(typeofDeclPath.node.init) ||
// we could validate typeofDeclPath.node.init.callee to make sure it is 'Symbol.for', but life is too long
typeofDeclPath.node.init.arguments.length != 1 || !t.isStringLiteral(typeofDeclPath.node.init.arguments[0]) || typeofDeclPath.node.init.arguments[0].value != 'react.element') {
return;
}
// Need to dynamically grab variable names for variables since minified
// code will change variable names; this is the lookup for the "var blah2"
// above.
var refIdentifier = path.node.value.name;
var typeIdentifierNode = path.parentPath.node.properties.find(function (property) {
return t.isObjectProperty(property) && property.key.name === 'type';
});
var propsIdentifierNode = path.parentPath.node.properties.find(function (property) {
return t.isObjectProperty(property) && property.key.name === 'props';
});
var typeIdentifierValueIsIdentifier = t.isIdentifier(typeIdentifierNode.value);
// variable "type" is a MemberExpression in production code
var typeIdentifierValueIsMemberExpression = t.isMemberExpression(typeIdentifierNode.value);
if (!(typeIdentifierValueIsIdentifier || typeIdentifierValueIsMemberExpression) || !t.isIdentifier(propsIdentifierNode.value)) {
return;
}
var typeIdentifier = typeIdentifierValueIsIdentifier ? typeIdentifierNode.value.name : typeIdentifierNode.value.object.name;
var propsIdentifier = propsIdentifierNode.value.name;
// at long last, insert our code before the object declaration
// https://github.com/facebook/react/blob/bbb9cb116dbf7b6247721aa0c4bcb6ec249aa8af/packages/react/src/ReactElement.js#L149
var fabricRefCodeAST = babylon.parse(_createFabricRefCode(refIdentifier, typeIdentifier, propsIdentifier));
path.getStatementParent().insertBefore(fabricRefCodeAST.program.body);
}
/* eslint-disable complexity */
function _default(_ref) {
var t = _ref.types;
return {
visitor: {
/* Looks like we don't currently need to add this to the interface declaration
InterfaceDeclaration(path, state) {
fixUIManagerJSInterface(path);
}, */
ClassDeclaration: function ClassDeclaration(path, state) {
fixPressability(t, path);
},
VariableDeclaration: function VariableDeclaration(path, state) {
fixReactNativeViewConfig(path);
fixReactNativeViewAttributes(path);
fixTouchableMixin(t, path);
},
ObjectProperty: function ObjectProperty(path, state) {
var reactFilesRegex = /node_modules\/react\/cjs\/.*\.js$/;
// only rewrite files in react/cjs directory
if (reactFilesRegex.test(state.file.opts.filename)) {
extendReactElementWithRef(path);
}
},
JSXAttribute: function JSXAttribute(path) {
// disable view optimization for only View component
if (path.parent.name.name !== 'View') return;
// must be manually annotated with at least one fs attribute
if (path.node.name.name !== 'fsClass' && path.node.name.name !== 'fsTagName' && path.node.name.name !== 'fsAttribute') {
return;
}
// check if view optimization is already disabled
var isViewOptimizationDisabled = path.container.some(function (attribute) {
return t.isJSXIdentifier(attribute.name, {
name: 'testID'
}) || t.isJSXIdentifier(attribute.name, {
name: 'id'
}) || t.isJSXIdentifier(attribute.name, {
name: 'nativeID'
});
});
if (isViewOptimizationDisabled) {
return;
}
path.insertAfter(t.jsxAttribute(t.jsxIdentifier('nativeID'), t.stringLiteral('__FS_NATIVEID')));
}
}
};
}
{
"name": "@fullstory/babel-plugin-react-native",
"version": "1.0.3",
"version": "1.1.0",
"description": "The official FullStory React Native babel plugin",

@@ -23,3 +23,5 @@ "repository": "git://github.com/fullstorydev/fullstory-babel-plugin-react-native.git",

"build": "babel src -d lib",
"test": "mocha --require babel-core/register"
"lint": "eslint ./src",
"test": "jest",
"test:watch": "jest --watch"
},

@@ -31,15 +33,28 @@ "dependencies": {

"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-helper-plugin-test-runner": "^6.24.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-syntax-flow": "^6.18.0",
"babel-preset-env": "^1.7.0",
"mocha": "^9.2.2"
"@babel/cli": "^7.0.0",
"@babel/core": "^7.0.3",
"@babel/eslint-parser": "^7.22.15",
"@babel/helper-plugin-test-runner": "^7.0.0",
"@babel/plugin-syntax-flow": "^7.0.0",
"@babel/plugin-syntax-jsx": "^7.0.0",
"@babel/preset-env": "7.0.0",
"babel-plugin-tester": "^11.0.4",
"eslint": "^8.52.0",
"eslint-config-prettier": "^9.0.0",
"jest": "^29.7.0",
"prettier": "3.0.3"
},
"jest": {
"roots": [
"<rootDir>/__tests__/"
],
"testPathIgnorePatterns": [
"<rootDir>/__tests__/fixtures/*"
]
},
"babel": {
"presets": [
"env"
"@babel/preset-env"
]
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc