-
Notifications
You must be signed in to change notification settings - Fork 216
fix(analytics): validate against incomplete/invalid app_remove events #1738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request provides a solid fix for a crash caused by malformed user properties in analytics events. The approach is robust, adding defensive checks in unwrapValueAsString
and filtering invalid properties during event construction. The addition of a new test case that covers various invalid inputs is excellent for ensuring correctness and preventing future regressions. I have one suggestion to improve the readability of the new filtering logic.
.filter(([, v]) => { | ||
if (v === null || v === undefined) { | ||
return false; | ||
} | ||
if (typeof v !== "object") { | ||
return false; | ||
} | ||
const vObj = v as Record<string, unknown>; | ||
// Filter out empty objects | ||
if (Object.keys(vObj).length === 0) { | ||
return false; | ||
} | ||
// Filter if 'value' property exists but is null/undefined/empty object | ||
if ("value" in vObj) { | ||
const value = vObj.value; | ||
if ( | ||
value === null || | ||
value === undefined || | ||
(typeof value === "object" && value !== null && Object.keys(value).length === 0) | ||
) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The filtering logic here is comprehensive but also quite complex and spread across multiple conditional statements, which could affect readability and future maintenance. To make the logic clearer and more self-documenting, you could refactor it slightly by grouping related checks and adding comments to explain each validation step.
.filter(([, v]) => {
// Property must be a non-empty object.
if (v == null || typeof v !== "object") {
return false;
}
if (Object.keys(v).length === 0) {
return false;
}
// If 'value' field exists, it must not be null, undefined, or an empty object.
if ("value" in v) {
const value = (v as { value: unknown }).value;
if (value == null || (typeof value === "object" && value !== null && Object.keys(value).length === 0)) {
return false;
}
}
return true;
})
This draft PR is a proposed solution to resolve #1712
Problem
When an analytics event payload contains malformed user properties, the SDK throws a
TypeError
before the user's callback can execute:Error:
TypeError: Cannot convert undefined or null to object
at Function.keys ()
at unwrapValueAsString (analytics.js:206)
Solution