Skip to content
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

Merged
merged 22 commits into from Feb 6, 2020

Conversation

micajuine-ho
Copy link
Contributor

Clean PR copy + merge fixes of #22379. Closes #21751.

In amp-analytics, as we recursively call expandTemplate(), we want to resolve macros (through url-replacement-service) as we encounter them to avoid premature encoding (eg: QUERY_PARAM(foo, (QUERY_PARAM(bar, default)) should return default 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.

Copy link
Member

@calebcordry calebcordry left a 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 🙃

@micajuine-ho
Copy link
Contributor Author

micajuine-ho commented Jan 22, 2020

LGTM assuming changes are the same. Still some merge conflicts to resolve 🙃

I caused these conflicts :'-)

@micajuine-ho micajuine-ho force-pushed the expand_before_encode branch 2 times, most recently from 2811575 to 77e9f79 Compare January 23, 2020 19:51
@micajuine-ho
Copy link
Contributor Author

cc @estherkim for presubmit-checks.js

@micajuine-ho
Copy link
Contributor Author

cc @jridgewell for string.js

Copy link
Collaborator

@estherkim estherkim left a 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 Show resolved Hide resolved
src/string.js Outdated
const replacementPromise =
typeof replacer === 'function'
? replacer.apply(null, arguments)
: replacer;
Copy link
Contributor

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?

Copy link
Member

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.

Copy link
Contributor

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)).

Copy link
Member

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?

Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Member

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 Show resolved Hide resolved
src/string.js Outdated
const stringBuilder = [];
let lastIndex = 0;
if (typeof replacer === 'string') {
stringBuilder.push(Promise.resolve(str.replace(regex, replacer)));
Copy link
Member

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.

Copy link
Contributor Author

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 () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

* @param {Function|string} replacer
* @return {!Promise<string>}
*/
export function asyncStringReplace(str, regex, replacer) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@micajuine-ho micajuine-ho requested review from zhouyx and calebcordry and removed request for zhouyx February 6, 2020 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

getNameArgs in variables.js doesn't understand nested macros
6 participants