Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

fix($httpParamSerializerJQLike): call functions as jQuery does #16139

Closed
wants to merge 3 commits into from
Closed

fix($httpParamSerializerJQLike): call functions as jQuery does #16139

wants to merge 3 commits into from

Conversation

frederikprijck
Copy link
Contributor

Closes #16138

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
Bug fix

What is the current behavior? (You can also link to an open issue here)
Previously, httpParamSerializerJQLike did not handle properties of type function.

What is the new behavior (if this is a feature change)?
This commit ensures function properties are executed and the return value is used.

Does this PR introduce a breaking change?
See: #16138 (comment)

Please check if the PR fulfills these requirements

Other information:

Copy link
Member

@gkalpak gkalpak left a comment

Choose a reason for hiding this comment

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

There are no tests with functions inside arrays 😞

Can you also change the commit message to make it more clear that previously function were stringified (not ignored). This will make it easier for people understand what differences to expect.

src/ng/http.js Outdated
@@ -122,8 +122,12 @@ function $HttpParamSerializerJQLikeProvider() {
(topLevel ? '' : ']'));
});
} else {
parts.push(encodeUriQuery(prefix) + '=' +
(toSerialize == null ? '' : encodeUriQuery(serializeValue(toSerialize))));
if (isFunction(toSerialize)) {
Copy link
Member

@gkalpak gkalpak Aug 1, 2017

Choose a reason for hiding this comment

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

EDIT: This comment is now obsolete.

Merge with the else above for consistency:

  ...
} else if (isFunction(toSerialize)) {
  ...
} else {
  ...
}

expect(jqrSer({a: function() { return { b: 'c' }; }, foo: {'bar': 'barv', 'baz': 'bazv'}})).toEqual(
'a%5Bb%5D=c&foo%5Bbar%5D=barv&foo%5Bbaz%5D=bazv');
//a[b]=c&foo[bar]=barv&foo[baz]=bazv
});
Copy link
Member

Choose a reason for hiding this comment

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

These two tests are testing more (independent) things than necessary. They should focus on the function part. The rest is irrelevant.

//a=b&foo[bar]=barv&foo[baz]=bazv
});

it('should serialize nested objects with function properties returning an object by repeating param name with [key] suffix', function() {
Copy link
Member

Choose a reason for hiding this comment

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

👍

src/ng/http.js Outdated
parts.push(encodeUriQuery(prefix) + '=' +
(toSerialize == null ? '' : encodeUriQuery(serializeValue(toSerialize))));
if (isFunction(toSerialize)) {
serialize(toSerialize(), prefix);
Copy link
Member

Choose a reason for hiding this comment

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

Actually, this is not how jQuery does it. They do not recursively serialize a returned object. They just use the returned value.

@frederikprijck
Copy link
Contributor Author

Updated the PR, added a test for a function in an array aswell!

Copy link
Member

@gkalpak gkalpak left a comment

Choose a reason for hiding this comment

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

Please add some test for array inside object (e.g. {foo: {bar: [valueFn('baz')]}}).

src/ng/http.js Outdated
} else {
parts.push(encodeUriQuery(prefix) + '=' +
(toSerialize == null ? '' : encodeUriQuery(serializeValue(toSerialize))));
(toSerialize == null ? '' : encodeUriQuery(serializeValue(toSerialize))));
Copy link
Member

Choose a reason for hiding this comment

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

Wrong indentation 😁

Copy link
Member

Choose a reason for hiding this comment

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

Actually, you can avoid code duplication with:

  ...
} else {
  if (isFunction(toSerialize)) {
    toSerialize = toSerialize();
  }
  parts.push(encodeUriQuery(prefix) + '=' +
      (toSerialize == null ? '' : encodeUriQuery(serializeValue(toSerialize))));
}

@@ -2364,17 +2364,45 @@ describe('$http param serializers', function() {
expect(decodeURIComponent(jqrSer({a: 'b', foo: ['bar', 'baz']}))).toEqual('a=b&foo[]=bar&foo[]=baz');
});

it('should serialize arrays with functions', function() {
expect(jqrSer({foo:[function() { return 'bar'; }]})).toEqual('foo%5B%5D=bar');
Copy link
Member

Choose a reason for hiding this comment

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

Missing space after :. 😁
BTW, you an probably use valueFn('bar') to save some typing 😎

it('should serialize objects by repeating param name with [key] suffix', function() {
expect(jqrSer({a: 'b', foo: {'bar': 'barv', 'baz': 'bazv'}})).toEqual('a=b&foo%5Bbar%5D=barv&foo%5Bbaz%5D=bazv');
//a=b&foo[bar]=barv&foo[baz]=bazv
});

it('should serialize objects with function properties by repeating param name with [key] suffix', function() {
expect(jqrSer({a: function() { return 'b'; }})).toEqual(
'a=b');
Copy link
Member

Choose a reason for hiding this comment

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

Remove the "by repeating param name with [key] suffix" part, which is irrelevant (here and below).
Weird line-splitting (here and below) 😕

it('should serialize objects with function properties returning an object by repeating param name with [key] suffix', function() {
expect(jqrSer({a: function() { return { b: 'c' }; }})).toEqual(
'a=%7B%22b%22:%22c%22%7D');
//a={"b": "c"}
Copy link
Member

Choose a reason for hiding this comment

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

There is no space after :.


it('should serialize objects with function properties returning an object by repeating param name with [key] suffix', function() {
expect(jqrSer({a: function() { return { b: 'c' }; }})).toEqual(
'a=%7B%22b%22:%22c%22%7D');
Copy link
Member

Choose a reason for hiding this comment

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

This is not exactly how jQuery does it, but that is not related to this PR 😁

it('should serialize nested objects with function properties returning an object by repeating param name with [key] suffix', function() {
expect(jqrSer({foo: {'bar': function() { return { bav: 'barv' }; }}})).toEqual(
'foo%5Bbar%5D=%7B%22bav%22:%22barv%22%7D');
//foo[bar]={"bav": "barv"}
Copy link
Member

Choose a reason for hiding this comment

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

No space after :.

it('should serialize nested objects by repeating param name with [key] suffix', function() {
expect(jqrSer({a: ['b', {c: 'd'}], e: {f: 'g', 'h': ['i', 'j']}})).toEqual(
'a%5B%5D=b&a%5B1%5D%5Bc%5D=d&e%5Bf%5D=g&e%5Bh%5D%5B%5D=i&e%5Bh%5D%5B%5D=j');
//a[]=b&a[1][c]=d&e[f]=g&e[h][]=i&e[h][]=j
});

it('should serialize nested objects with function properties by repeating param name with [key] suffix', function() {
expect(jqrSer({foo: {'bar': function() { return 'barv'; }}})).toEqual(
Copy link
Member

Choose a reason for hiding this comment

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

No need for quoting bar (here and below).

@frederikprijck
Copy link
Contributor Author

Updated!

src/ng/http.js Outdated
parts.push(encodeUriQuery(prefix) + '=' +
(toSerialize == null ? '' : encodeUriQuery(serializeValue(toSerialize))));
(toSerialize == null ? '' : encodeUriQuery(serializeValue(toSerialize))));
Copy link
Member

Choose a reason for hiding this comment

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

Wrong indentation. 😞

it('should serialize nested objects with function properties by repeating param name with [key] suffix', function() {
expect(jqrSer({foo: {'bar': function() { return 'barv'; }}})).toEqual(
it('should serialize nested objects with function properties', function() {
expect(jqrSer({foo: {bar: valueFn('barv')}})).toEqual(
'foo%5Bbar%5D=barv');
Copy link
Member

Choose a reason for hiding this comment

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

Weird line break (here and below) 😕

it('should serialize nested objects with function properties returning an object by repeating param name with [key] suffix', function() {
expect(jqrSer({foo: {'bar': function() { return { bav: 'barv' }; }}})).toEqual(
it('should serialize nested objects with function properties returning an object', function() {
expect(jqrSer({foo: {bar: valueFn({ bav: 'barv' })}})).toEqual(
Copy link
Member

Choose a reason for hiding this comment

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

Inconsistent whitespace after { and before } 😁

Previously, `httpParamSerializerJQLike` stringified function properties without executing them.

This commit ensures function properties are executed and the return value is used.

Closes #16138
@@ -2364,17 +2364,41 @@ describe('$http param serializers', function() {
expect(decodeURIComponent(jqrSer({a: 'b', foo: ['bar', 'baz']}))).toEqual('a=b&foo[]=bar&foo[]=baz');
});

it('should serialize arrays with functions', function() {
expect(jqrSer({foo: [valueFn('bar')]})).toEqual('foo%5B%5D=bar');
Copy link
Member

Choose a reason for hiding this comment

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

Where's the decoded comment (foo[]=bar)? 😁

expect(jqrSer({a: valueFn('b')})).toEqual('a=b');
});

it('should serialize objects with function properties returning an object by repeating param name with [key] suffix', function() {
Copy link
Member

Choose a reason for hiding this comment

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

Inaccurate description.

});

it('should serialize nested objects with function properties returning an object', function() {
expect(jqrSer({foo: {bar: valueFn({ bav: 'barv'})}})).toEqual('foo%5Bbar%5D=%7B%22bav%22:%22barv%22%7D'); //foo[bar]={"bav":"barv"}
Copy link
Member

Choose a reason for hiding this comment

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

Extra whitespace in { bav. 😱

@gkalpak gkalpak closed this in a784fab Aug 3, 2017
@gkalpak
Copy link
Member

gkalpak commented Aug 3, 2017

Merging to master only, since it has already deviated from 1.6.x (not converting empty strings to null).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

fix($httpParamSerializerJQLike): call functions as jQuery does
3 participants