Skip to content

Commit f55657c

Browse files
committed
avoid direct call to hasOwnProperty
ignore IDE auto formatting
1 parent c13a961 commit f55657c

File tree

6 files changed

+119
-93
lines changed

6 files changed

+119
-93
lines changed

spec/nfr_spec.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
import { XMLParser, XMLBuilder, XMLValidator } from "../src/fxp.js";
3+
4+
describe("XMLParser", function () {
5+
6+
it("should process XML with js properties hasOwnProperty, toString", function () {
7+
const xmlData = `
8+
<root>
9+
<hasOwnProperty>1</hasOwnProperty>
10+
<constructor>1</constructor>
11+
<toString>2</toString>
12+
</root>
13+
`;
14+
const expected = {
15+
"root": {
16+
"hasOwnProperty": 1,
17+
"constructor": 1,
18+
"toString": 2
19+
}
20+
}
21+
const parser = new XMLParser();
22+
let result = parser.parse(xmlData);
23+
// console.log(JSON.stringify(result, null,4));
24+
expect(result).toEqual(expected);
25+
});
26+
});

src/v6/OptionsBuilder.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
import {JsObjOutputBuilder} from './OutputBuilders/JsObjBuilder.js';
2+
import { JsObjOutputBuilder } from './OutputBuilders/JsObjBuilder.js';
33

44
export const defaultOptions = {
55
preserveOrder: false,
@@ -9,16 +9,16 @@ export const defaultOptions = {
99
// isArray: () => false, //User will set it
1010
htmlEntities: false,
1111
// skipEmptyListItem: false
12-
tags:{
12+
tags: {
1313
unpaired: [],
14-
nameFor:{
14+
nameFor: {
1515
cdata: false,
1616
comment: false,
1717
text: '#text'
1818
},
1919
separateTextProperty: false,
2020
},
21-
attributes:{
21+
attributes: {
2222
ignore: false,
2323
booleanType: true,
2424
entities: true,
@@ -34,19 +34,19 @@ export const defaultOptions = {
3434
stop: [], //given tagPath will not be parsed. innerXML will be set as string value
3535
OutputBuilder: new JsObjOutputBuilder(),
3636
};
37-
38-
export const buildOptions = function(options) {
39-
const finalOptions = { ... defaultOptions};
40-
copyProperties(finalOptions,options)
37+
38+
export const buildOptions = function (options) {
39+
const finalOptions = { ...defaultOptions };
40+
copyProperties(finalOptions, options)
4141
return finalOptions;
4242
};
4343

4444
function copyProperties(target, source) {
4545
for (let key in source) {
46-
if (source.hasOwnProperty(key)) {
46+
if (Object.prototype.hasOwnProperty.call(source, key)) {
4747
if (key === 'OutputBuilder') {
4848
target[key] = source[key];
49-
}else if (typeof source[key] === 'object' && !Array.isArray(source[key])) {
49+
} else if (typeof source[key] === 'object' && !Array.isArray(source[key])) {
5050
// Recursively copy nested properties
5151
if (typeof target[key] === 'undefined') {
5252
target[key] = {};

src/v6/OutputBuilders/ParserOptionsBuilder.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import booleanParser from "../valueParsers/booleanParser.js";
33
import currencyParser from "../valueParsers/currency.js";
44
import numberParser from "../valueParsers/number.js";
55

6-
const defaultOptions={
7-
nameFor:{
6+
const defaultOptions = {
7+
nameFor: {
88
text: "#text",
99
comment: "",
1010
cdata: "",
@@ -22,11 +22,11 @@ const defaultOptions={
2222
// "date",
2323
]
2424
},
25-
attributes:{
25+
attributes: {
2626
prefix: "@_",
2727
suffix: "",
2828
groupBy: "",
29-
29+
3030
valueParsers: [
3131
// "trim",
3232
// "boolean",
@@ -35,35 +35,35 @@ const defaultOptions={
3535
// "date",
3636
]
3737
},
38-
dataType:{
38+
dataType: {
3939

4040
}
4141
}
4242

4343
//TODO
44-
const withJoin = ["trim","join", /*"entities",*/"number","boolean","currency"/*, "date"*/]
45-
const withoutJoin = ["trim", /*"entities",*/"number","boolean","currency"/*, "date"*/]
44+
const withJoin = ["trim", "join", /*"entities",*/"number", "boolean", "currency"/*, "date"*/]
45+
const withoutJoin = ["trim", /*"entities",*/"number", "boolean", "currency"/*, "date"*/]
4646

47-
export function buildOptions(options){
47+
export function buildOptions(options) {
4848
//clone
49-
const finalOptions = { ... defaultOptions};
49+
const finalOptions = { ...defaultOptions };
5050

5151
//add config missed in cloning
5252
finalOptions.tags.valueParsers.push(...withJoin)
53-
if(!this.preserveOrder)
53+
if (!this.preserveOrder)
5454
finalOptions.tags.valueParsers.push(...withoutJoin);
5555

5656
//add config missed in cloning
5757
finalOptions.attributes.valueParsers.push(...withJoin)
5858

5959
//override configuration
60-
copyProperties(finalOptions,options);
60+
copyProperties(finalOptions, options);
6161
return finalOptions;
6262
}
6363

6464
function copyProperties(target, source) {
6565
for (let key in source) {
66-
if (source.hasOwnProperty(key)) {
66+
if (Object.prototype.hasOwnProperty.call(source, key)) {
6767
if (typeof source[key] === 'object' && !Array.isArray(source[key])) {
6868
// Recursively copy nested properties
6969
if (typeof target[key] === 'undefined') {
@@ -78,16 +78,16 @@ function copyProperties(target, source) {
7878
}
7979
}
8080

81-
export function registerCommonValueParsers(options){
81+
export function registerCommonValueParsers(options) {
8282
return {
8383
"trim": new trimParser(),
8484
// "join": this.entityParser.parse,
8585
"boolean": new booleanParser(),
8686
"number": new numberParser({
87-
hex: true,
88-
leadingZeros: true,
89-
eNotation: true
90-
}),
87+
hex: true,
88+
leadingZeros: true,
89+
eNotation: true
90+
}),
9191
"currency": new currencyParser(),
9292
// "date": this.entityParser.parse,
9393
}

src/validator.js

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
import {getAllMatches, isName} from './util.js';
3+
import { getAllMatches, isName } from './util.js';
44

55
const defaultOptions = {
66
allowBooleanAttributes: false, //A tag can have attributes without any value
@@ -24,19 +24,19 @@ export function validate(xmlData, options) {
2424
// check for byte order mark (BOM)
2525
xmlData = xmlData.substr(1);
2626
}
27-
27+
2828
for (let i = 0; i < xmlData.length; i++) {
2929

30-
if (xmlData[i] === '<' && xmlData[i+1] === '?') {
31-
i+=2;
32-
i = readPI(xmlData,i);
30+
if (xmlData[i] === '<' && xmlData[i + 1] === '?') {
31+
i += 2;
32+
i = readPI(xmlData, i);
3333
if (i.err) return i;
34-
}else if (xmlData[i] === '<') {
34+
} else if (xmlData[i] === '<') {
3535
//starting of tag
3636
//read until you reach to '>' avoiding any '>' in attribute value
3737
let tagStartPos = i;
3838
i++;
39-
39+
4040
if (xmlData[i] === '!') {
4141
i = readCommentAndCDATA(xmlData, i);
4242
continue;
@@ -72,14 +72,14 @@ export function validate(xmlData, options) {
7272
if (tagName.trim().length === 0) {
7373
msg = "Invalid space after '<'.";
7474
} else {
75-
msg = "Tag '"+tagName+"' is an invalid name.";
75+
msg = "Tag '" + tagName + "' is an invalid name.";
7676
}
7777
return getErrorObject('InvalidTag', msg, getLineNumberForPosition(xmlData, i));
7878
}
7979

8080
const result = readAttributeStr(xmlData, i);
8181
if (result === false) {
82-
return getErrorObject('InvalidAttr', "Attributes for '"+tagName+"' have open quote.", getLineNumberForPosition(xmlData, i));
82+
return getErrorObject('InvalidAttr', "Attributes for '" + tagName + "' have open quote.", getLineNumberForPosition(xmlData, i));
8383
}
8484
let attrStr = result.value;
8585
i = result.index;
@@ -100,17 +100,17 @@ export function validate(xmlData, options) {
100100
}
101101
} else if (closingTag) {
102102
if (!result.tagClosed) {
103-
return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' doesn't have proper closing.", getLineNumberForPosition(xmlData, i));
103+
return getErrorObject('InvalidTag', "Closing tag '" + tagName + "' doesn't have proper closing.", getLineNumberForPosition(xmlData, i));
104104
} else if (attrStr.trim().length > 0) {
105-
return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, tagStartPos));
105+
return getErrorObject('InvalidTag', "Closing tag '" + tagName + "' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, tagStartPos));
106106
} else if (tags.length === 0) {
107-
return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' has not been opened.", getLineNumberForPosition(xmlData, tagStartPos));
107+
return getErrorObject('InvalidTag', "Closing tag '" + tagName + "' has not been opened.", getLineNumberForPosition(xmlData, tagStartPos));
108108
} else {
109109
const otg = tags.pop();
110110
if (tagName !== otg.tagName) {
111111
let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos);
112112
return getErrorObject('InvalidTag',
113-
"Expected closing tag '"+otg.tagName+"' (opened in line "+openPos.line+", col "+openPos.col+") instead of closing tag '"+tagName+"'.",
113+
"Expected closing tag '" + otg.tagName + "' (opened in line " + openPos.line + ", col " + openPos.col + ") instead of closing tag '" + tagName + "'.",
114114
getLineNumberForPosition(xmlData, tagStartPos));
115115
}
116116

@@ -131,10 +131,10 @@ export function validate(xmlData, options) {
131131
//if the root level has been reached before ...
132132
if (reachedRoot === true) {
133133
return getErrorObject('InvalidXml', 'Multiple possible root nodes found.', getLineNumberForPosition(xmlData, i));
134-
} else if(options.unpairedTags.indexOf(tagName) !== -1){
134+
} else if (options.unpairedTags.indexOf(tagName) !== -1) {
135135
//don't push into stack
136136
} else {
137-
tags.push({tagName, tagStartPos});
137+
tags.push({ tagName, tagStartPos });
138138
}
139139
tagFound = true;
140140
}
@@ -148,18 +148,18 @@ export function validate(xmlData, options) {
148148
i++;
149149
i = readCommentAndCDATA(xmlData, i);
150150
continue;
151-
} else if (xmlData[i+1] === '?') {
151+
} else if (xmlData[i + 1] === '?') {
152152
i = readPI(xmlData, ++i);
153153
if (i.err) return i;
154-
} else{
154+
} else {
155155
break;
156156
}
157157
} else if (xmlData[i] === '&') {
158158
const afterAmp = validateAmpersand(xmlData, i);
159159
if (afterAmp == -1)
160160
return getErrorObject('InvalidChar', "char '&' is not expected.", getLineNumberForPosition(xmlData, i));
161161
i = afterAmp;
162-
}else{
162+
} else {
163163
if (reachedRoot === true && !isWhiteSpace(xmlData[i])) {
164164
return getErrorObject('InvalidXml', "Extra text at the end", getLineNumberForPosition(xmlData, i));
165165
}
@@ -170,28 +170,28 @@ export function validate(xmlData, options) {
170170
}
171171
}
172172
} else {
173-
if ( isWhiteSpace(xmlData[i])) {
173+
if (isWhiteSpace(xmlData[i])) {
174174
continue;
175175
}
176-
return getErrorObject('InvalidChar', "char '"+xmlData[i]+"' is not expected.", getLineNumberForPosition(xmlData, i));
176+
return getErrorObject('InvalidChar', "char '" + xmlData[i] + "' is not expected.", getLineNumberForPosition(xmlData, i));
177177
}
178178
}
179179

180180
if (!tagFound) {
181181
return getErrorObject('InvalidXml', 'Start tag expected.', 1);
182-
}else if (tags.length == 1) {
183-
return getErrorObject('InvalidTag', "Unclosed tag '"+tags[0].tagName+"'.", getLineNumberForPosition(xmlData, tags[0].tagStartPos));
184-
}else if (tags.length > 0) {
185-
return getErrorObject('InvalidXml', "Invalid '"+
186-
JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\r?\n/g, '')+
187-
"' found.", {line: 1, col: 1});
182+
} else if (tags.length == 1) {
183+
return getErrorObject('InvalidTag', "Unclosed tag '" + tags[0].tagName + "'.", getLineNumberForPosition(xmlData, tags[0].tagStartPos));
184+
} else if (tags.length > 0) {
185+
return getErrorObject('InvalidXml', "Invalid '" +
186+
JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\r?\n/g, '') +
187+
"' found.", { line: 1, col: 1 });
188188
}
189189

190190
return true;
191191
};
192192

193-
function isWhiteSpace(char){
194-
return char === ' ' || char === '\t' || char === '\n' || char === '\r';
193+
function isWhiteSpace(char) {
194+
return char === ' ' || char === '\t' || char === '\n' || char === '\r';
195195
}
196196
/**
197197
* Read Processing insstructions and skip
@@ -327,25 +327,25 @@ function validateAttributeString(attrStr, options) {
327327
for (let i = 0; i < matches.length; i++) {
328328
if (matches[i][1].length === 0) {
329329
//nospace before attribute name: a="sd"b="saf"
330-
return getErrorObject('InvalidAttr', "Attribute '"+matches[i][2]+"' has no space in starting.", getPositionFromMatch(matches[i]))
330+
return getErrorObject('InvalidAttr', "Attribute '" + matches[i][2] + "' has no space in starting.", getPositionFromMatch(matches[i]))
331331
} else if (matches[i][3] !== undefined && matches[i][4] === undefined) {
332-
return getErrorObject('InvalidAttr', "Attribute '"+matches[i][2]+"' is without value.", getPositionFromMatch(matches[i]));
332+
return getErrorObject('InvalidAttr', "Attribute '" + matches[i][2] + "' is without value.", getPositionFromMatch(matches[i]));
333333
} else if (matches[i][3] === undefined && !options.allowBooleanAttributes) {
334334
//independent attribute: ab
335-
return getErrorObject('InvalidAttr', "boolean attribute '"+matches[i][2]+"' is not allowed.", getPositionFromMatch(matches[i]));
335+
return getErrorObject('InvalidAttr', "boolean attribute '" + matches[i][2] + "' is not allowed.", getPositionFromMatch(matches[i]));
336336
}
337337
/* else if(matches[i][6] === undefined){//attribute without value: ab=
338338
return { err: { code:"InvalidAttr",msg:"attribute " + matches[i][2] + " has no value assigned."}};
339339
} */
340340
const attrName = matches[i][2];
341341
if (!validateAttrName(attrName)) {
342-
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is an invalid name.", getPositionFromMatch(matches[i]));
342+
return getErrorObject('InvalidAttr', "Attribute '" + attrName + "' is an invalid name.", getPositionFromMatch(matches[i]));
343343
}
344-
if (!attrNames.hasOwnProperty(attrName)) {
344+
if (!Object.prototype.hasOwnProperty.call(attrNames, attrName)) {
345345
//check for duplicate attribute.
346346
attrNames[attrName] = 1;
347347
} else {
348-
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is repeated.", getPositionFromMatch(matches[i]));
348+
return getErrorObject('InvalidAttr', "Attribute '" + attrName + "' is repeated.", getPositionFromMatch(matches[i]));
349349
}
350350
}
351351

src/xmlbuilder/orderedJs2Xml.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ function propName(obj) {
103103
const keys = Object.keys(obj);
104104
for (let i = 0; i < keys.length; i++) {
105105
const key = keys[i];
106-
if (!obj.hasOwnProperty(key)) continue;
106+
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
107107
if (key !== ":@") return key;
108108
}
109109
}
@@ -112,7 +112,7 @@ function attr_to_str(attrMap, options) {
112112
let attrStr = "";
113113
if (attrMap && !options.ignoreAttributes) {
114114
for (let attr in attrMap) {
115-
if (!attrMap.hasOwnProperty(attr)) continue;
115+
if (!Object.prototype.hasOwnProperty.call(attrMap, attr)) continue;
116116
let attrVal = options.attributeValueProcessor(attr, attrMap[attr]);
117117
attrVal = replaceEntitiesValue(attrVal, options);
118118
if (attrVal === true && options.suppressBooleanAttributes) {

0 commit comments

Comments
 (0)