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
Resolve macros before encoding for analytics variables #26271
Resolve macros before encoding for analytics variables #26271
Conversation
9bebe1e
to
9ef788b
Compare
9ef788b
to
b95555c
Compare
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.
LGTM assuming changes are the same. Still some merge conflicts to resolve 🙃
I caused these conflicts :'-) |
2811575
to
77e9f79
Compare
77e9f79
to
d7ab181
Compare
cc @estherkim for |
cc @jridgewell for |
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.
presubmit-checks.js
change LGTM
src/string.js
Outdated
const replacementPromise = | ||
typeof replacer === 'function' | ||
? replacer.apply(null, arguments) | ||
: replacer; |
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 type says this is always a function. How do we get to this else branch?
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.
I think that this is just a bad type on my part, was trying to keep it consistent with string.replace
where the replacer can be a {Function|string}
. e.g. test-string.js L170 in this PR.
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.
Then we need to check it earlier. We can't support the string
replacer here, since we've already passed a function to string.replace()
. But if you check before calling string replace, you can just Promise.resolve(string.replace(regex, replacment))
.
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.
Sorry I don't think I understand the difference. We are only really using native string.replace
to get the matches & offset? Can you give an example that breaks it?
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.
't123'.replace(/t(\d+)/g, '$1')
. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_string_as_a_parameter, the string replacement
value is much more complicated then most realize. Let's either forbid a string, or support it properly.
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.
ah thanks, you are totally right. Moving the check sgtm.
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.
also @micajuine-ho can we add a test case or two using these "special replacement patterns" :)
src/string.js
Outdated
const stringBuilder = []; | ||
let lastIndex = 0; | ||
if (typeof replacer === 'string') { | ||
stringBuilder.push(Promise.resolve(str.replace(regex, replacer))); |
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.
nit: no need to use stringBuilder here, I think the idea was just return Promise.resolve(str.replace(...)))
@jridgewell to confirm.
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.
Yeah, that makes sense 👍
return expect(result).to.eventually.equal('the quick red fox'); | ||
}); | ||
|
||
it('should use replacer with special pattern', async () => { |
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.
Thank you!
207c670
to
3dc0526
Compare
* @param {Function|string} replacer | ||
* @return {!Promise<string>} | ||
*/ | ||
export function asyncStringReplace(str, regex, replacer) { |
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.
LGTM.
d7fcb74
to
b6c1da3
Compare
…l into expand_before_encode
b6c1da3
to
279fb66
Compare
Clean PR copy + merge fixes of #22379. Closes #21751.
In amp-analytics, as we recursively call
expandTemplate()
, we want to resolve macros (throughurl-replacement-service
) as we encounter them to avoid premature encoding (eg:QUERY_PARAM(foo, (QUERY_PARAM(bar, default))
should returndefault
instead of encoding the second QUERY_PARAM).There are caveats to this approach, so documentation will be added in this PR to address it. See test cases in
test-variables.js
.