Skip to content

Resolve macros before encoding for analytics variables#26271

Merged
micajuine-ho merged 22 commits intoampproject:masterfrom
micajuine-ho:expand_before_encode
Feb 6, 2020
Merged

Resolve macros before encoding for analytics variables#26271
micajuine-ho merged 22 commits intoampproject:masterfrom
micajuine-ho:expand_before_encode

Conversation

@micajuine-ho
Copy link
Copy Markdown
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.

@micajuine-ho micajuine-ho removed the request for review from zhouyx January 22, 2020 19:50
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Contributor Author

cc @estherkim for presubmit-checks.js

@micajuine-ho
Copy link
Copy Markdown
Contributor Author

cc @jridgewell for string.js

Copy link
Copy Markdown
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
const replacementPromise =
typeof replacer === 'function'
? replacer.apply(null, arguments)
: replacer;
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
const stringBuilder = [];
let lastIndex = 0;
if (typeof replacer === 'string') {
stringBuilder.push(Promise.resolve(str.replace(regex, replacer)));
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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 calebcordry and zhouyx 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