Skip to content
This repository was archived by the owner on Nov 8, 2024. It is now read-only.

Commit fdb70bf

Browse files
committed
fix(core): inherit fixed attribute in valueOf (#564)
1 parent 9d2ab4e commit fdb70bf

File tree

5 files changed

+238
-33
lines changed

5 files changed

+238
-33
lines changed

packages/api-elements/CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# API Elements (JavaScript) CHANGELOG
22

3-
## 0.3.2 (2020-09-15)
3+
## 0.3.2 (2020-09-23)
4+
5+
### Bug Fixes
6+
7+
- Inherit fixed attribute in `valueOf`
48

59
### Enhancements
610

packages/api-elements/lib/define-value-of.js

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const {
77
} = require('minim');
88
const {
99
isFixed,
10+
isFixedType,
1011
isRequired,
1112
isNullable,
1213
isOptional,
@@ -27,17 +28,20 @@ const {
2728
/**
2829
* Map the element values
2930
* @param {element} e - element
31+
* @param {boolean} inheritFixed - inherited fixed attribute
3032
* @param {function} f - map function
3133
* @param {object=} elements - object map of elements to look for inherited types
3234
* @return {any}
3335
*/
34-
function mapValue(e, f, elements) {
36+
function mapValue(e, f, inheritFixed, elements) {
3537
if (e === undefined) {
3638
return undefined;
3739
}
3840

41+
const isElementFixed = inheritFixed || isFixed(e);
42+
3943
if (e.content && !isEmptyArray(e, elements) && !isObjectWithUndefinedValues(e, elements)) {
40-
const result = f(e, elements, 'content');
44+
const result = f(e, isElementFixed, elements, 'content');
4145

4246
if (result !== undefined) {
4347
return result;
@@ -46,31 +50,31 @@ function mapValue(e, f, elements) {
4650

4751
const sample = getFirstSample(e);
4852
if (sample) {
49-
const result = f(sample, elements, 'sample');
53+
const result = f(sample, isElementFixed, elements, 'sample');
5054
if (result !== undefined) {
5155
return result;
5256
}
5357
}
5458

5559
const dflt = getDefault(e);
5660
if (dflt) {
57-
const result = f(dflt, elements, 'default');
61+
const result = f(dflt, isElementFixed, elements, 'default');
5862
if (result !== undefined) {
5963
return result;
6064
}
6165
}
6266

6367
// reconsider content for array and object element (prefer sample/default first)
6468
if (isNonEmptyArray(e, elements) && isObject(e, elements)) {
65-
const result = f(e, elements, 'content');
69+
const result = f(e, isElementFixed, elements, 'content');
6670

6771
if (result !== undefined) {
6872
return result;
6973
}
7074
}
7175

7276
if (isNullable(e)) {
73-
const result = f(new NullElement(), elements, 'nullable');
77+
const result = f(new NullElement(), isElementFixed, elements, 'nullable');
7478
if (result !== undefined) {
7579
return result;
7680
}
@@ -82,24 +86,24 @@ function mapValue(e, f, elements) {
8286
const inheritedElements = R.filter(el => !el.id.equals(e.content), elements);
8387

8488
if (e.path && e.path.toValue() === 'content') {
85-
return mapValue(result.content, f, inheritedElements);
89+
return mapValue(result.content, f, isElementFixed, inheritedElements);
8690
}
8791

88-
return mapValue(result, f, inheritedElements);
92+
return mapValue(result, f, isElementFixed, inheritedElements);
8993
}
9094

9195
const result = elements[e.element];
9296
if (result !== undefined) {
9397
const inheritedElements = R.filter(el => !el.id.equals(e.element), elements);
94-
return mapValue(result, f, inheritedElements);
98+
return mapValue(result, f, isElementFixed, inheritedElements);
9599
}
96100
}
97101

98102
if (isEnum(e, elements)) {
99103
const content = getStructureMembers(e, elements);
100104

101105
if (content && content[0]) {
102-
const result = f(content[0], elements, 'generated');
106+
const result = f(content[0], isElementFixed, elements, 'generated');
103107
if (result !== undefined) {
104108
return result;
105109
}
@@ -108,14 +112,14 @@ function mapValue(e, f, elements) {
108112

109113
const trivial = trivialValue(e);
110114
if (trivial) {
111-
const result = f(trivial, elements, 'generated');
115+
const result = f(trivial, isElementFixed, elements, 'generated');
112116
if (result !== undefined) {
113117
return result;
114118
}
115119
}
116120

117121
if ((isArray(e, elements) && e.isEmpty) || isObject(e, elements)) {
118-
return f(e, elements, 'generated');
122+
return f(e, isElementFixed, elements, 'generated');
119123
}
120124

121125
return undefined;
@@ -124,12 +128,13 @@ function mapValue(e, f, elements) {
124128
/**
125129
* Reduce the element value
126130
* @param {element} e - element
131+
* @param {boolean} inheritFixed - inherited fixed attribute
127132
* @param {object=} elements - object map of elements to look for inherited types
128133
* @return {any}
129134
*/
130-
function reduceValue(e, elements) {
135+
function reduceValue(e, inheritFixed, elements) {
131136
if (e.content === undefined) {
132-
return mapValue(e, e => e.content, elements);
137+
return mapValue(e, e => e.content, inheritFixed, elements);
133138
}
134139

135140
if (isPrimitive(e, elements)) {
@@ -141,20 +146,19 @@ function reduceValue(e, elements) {
141146
}
142147

143148
if (isEnum(e, elements)) {
144-
return mapValue(e.content, reduceValue, elements);
149+
return mapValue(e.content, reduceValue, inheritFixed, elements);
145150
}
146151

147152
if (isObject(e, elements)) {
148153
let result = {};
149154

150-
const isFixedElement = isFixed(e);
151-
152155
const content = getStructureMembers(e, elements);
156+
const isElementFixedType = isFixedType(e);
153157

154158
content.some((item) => {
155-
const isSkippable = isOptional(item) || (!isFixedElement && !isRequired(item));
159+
const isSkippable = isOptional(item) || (!inheritFixed && !isElementFixedType && !isRequired(item));
156160

157-
const key = mapValue(item.key, reduceValue, elements);
161+
const key = mapValue(item.key, reduceValue, inheritFixed, elements);
158162
if (key === undefined) {
159163
if (isSkippable) {
160164
return false;
@@ -164,7 +168,7 @@ function reduceValue(e, elements) {
164168
return true;
165169
}
166170

167-
const value = mapValue(item.value, reduceValue, elements);
171+
const value = mapValue(item.value, reduceValue, inheritFixed, elements);
168172
if (value === undefined) {
169173
if (isSkippable) {
170174
return false;
@@ -183,9 +187,9 @@ function reduceValue(e, elements) {
183187

184188
if (isArray(e, elements)) {
185189
const content = getStructureMembers(e, elements);
186-
const result = content.map(item => mapValue(item, reduceValue, elements));
190+
const result = content.map(item => mapValue(item, reduceValue, inheritFixed, elements));
187191

188-
if (!isFixed(e)) {
192+
if (!inheritFixed && !isFixedType(e)) {
189193
return result.filter(item => item !== undefined);
190194
}
191195

@@ -207,15 +211,18 @@ module.exports = () => {
207211
Object.defineProperty(Element.prototype, 'valueOf', {
208212
value(flags, elements) {
209213
if (flags && flags.source) {
210-
return mapValue(this, (value, elements, source) => {
211-
const result = reduceValue(value, elements);
214+
return mapValue(this, (value, attrs, elements, source) => {
215+
const result = reduceValue(value, attrs, elements);
216+
212217
if (result === undefined) {
213218
return undefined;
214219
}
215-
return [reduceValue(value, elements), source];
216-
}, elements);
220+
221+
return [result, source];
222+
}, false, elements);
217223
}
218-
return mapValue(this, value => reduceValue(value, elements), elements);
224+
225+
return mapValue(this, reduceValue, false, elements);
219226
},
220227
});
221228
};

packages/api-elements/lib/utils.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,18 @@ function hasTypeAttribute(e, attribute) {
3232
}
3333

3434
/**
35-
* Check if element has 'fixed' or 'fixedType' typeAttribute set
35+
* Check if element has 'fixed' typeAttribute set
3636
* @param {element} e - element
3737
* @return {boolean}
3838
*/
39-
const isFixed = e => hasTypeAttribute(e, 'fixed') || hasTypeAttribute(e, 'fixedType');
39+
const isFixed = e => hasTypeAttribute(e, 'fixed');
40+
41+
/**
42+
* Check if element has 'fixedType' typeAttribute set
43+
* @param {element} e - element
44+
* @return {boolean}
45+
*/
46+
const isFixedType = e => hasTypeAttribute(e, 'fixedType');
4047

4148
/**
4249
* Check if element has 'required' typeAttribute set
@@ -358,6 +365,7 @@ function getStructureMembers(e, elements) {
358365

359366
module.exports = {
360367
isFixed,
368+
isFixedType,
361369
isRequired,
362370
isNullable,
363371
isOptional,

packages/api-elements/test/utils-test.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const { expect } = require('chai');
22
const {
33
isFixed,
4+
isFixedType,
45
isRequired,
56
isNullable,
67
isOptional,
@@ -42,19 +43,28 @@ describe('isFixed', () => {
4243
expect(value).to.be.true;
4344
});
4445

46+
it('returns `false` if the element typeAttributes do not contain`fixed`', () => {
47+
const element = new Element();
48+
const value = isFixed(element);
49+
50+
expect(value).to.be.false;
51+
});
52+
});
53+
54+
describe('isFixedType', () => {
4555
it('returns `true` if the element typeAttributes contain `fixedType`', () => {
4656
const element = new Element();
4757
element.attributes.set('typeAttributes', new ArrayElement([
4858
new StringElement('fixedType'),
4959
]));
50-
const value = isFixed(element);
60+
const value = isFixedType(element);
5161

5262
expect(value).to.be.true;
5363
});
5464

55-
it('returns `false` if the element typeAttributes do not contain`fixed` or `fixedType`', () => {
65+
it('returns `false` if the element typeAttributes do not contain `fixedType`', () => {
5666
const element = new Element();
57-
const value = isFixed(element);
67+
const value = isFixedType(element);
5868

5969
expect(value).to.be.false;
6070
});

0 commit comments

Comments
 (0)