Skip to content
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

Commit 6cd6efe

Browse files
author
Alexander Vakrilov
authored
fix: Unbound namespace error with ios and android (#1053)
1 parent 45e2411 commit 6cd6efe

File tree

2 files changed

+73
-9
lines changed

2 files changed

+73
-9
lines changed

Diff for: xml-namespace-loader.spec.ts

+56
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,17 @@ function getContext(
2727
done: DoneFn,
2828
{ resolveMap, expectedDeps, expectedRegs, assureNoDeps, ignore, expectError }: TestSetup) {
2929
const actualDeps: string[] = [];
30+
let callbackCalled = false;
3031

3132
const loaderContext = {
3233
rootContext: "app",
3334
context: "app/component",
3435
async: () => (error, source: string) => {
36+
if (callbackCalled) {
37+
done.fail("Callback called more than once!");
38+
}
39+
callbackCalled = true;
40+
3541
expectedDeps.forEach(expectedDep => expect(actualDeps).toContain(expectedDep));
3642

3743
expectedRegs.forEach(({ name, path }) => {
@@ -221,4 +227,54 @@ describe("XmlNamespaceLoader", () => {
221227

222228
xmlNsLoader.call(loaderContext, testXml);
223229
})
230+
231+
it("doesn't throw with ios and android platform namespaces", (done) => {
232+
const resolveMap = {};
233+
const expectedDeps = [];
234+
const expectedRegs = [];
235+
236+
const testXml = `
237+
<Page xmlns="http://www.nativescript.org/tns.xsd">
238+
<ios:GridLayout />
239+
<android:GridLayout />
240+
</Page>`;
241+
242+
const loaderContext = getContext(done, { resolveMap, expectedDeps, expectedRegs, assureNoDeps: true });
243+
244+
xmlNsLoader.call(loaderContext, testXml);
245+
})
246+
247+
it("doesn't throw with ios and android platform namespaces", (done) => {
248+
const resolveMap = {};
249+
const expectedDeps = [];
250+
const expectedRegs = [];
251+
252+
const testXml = `
253+
<Page xmlns="http://www.nativescript.org/tns.xsd">
254+
<ios:GridLayout />
255+
<ios:GridLayout></ios:GridLayout>
256+
<android:GridLayout />
257+
<android:GridLayout></android:GridLayout>
258+
</Page>`;
259+
260+
const loaderContext = getContext(done, { resolveMap, expectedDeps, expectedRegs, assureNoDeps: true });
261+
262+
xmlNsLoader.call(loaderContext, testXml);
263+
})
264+
265+
it("throws with unbound namespace namespaces", (done) => {
266+
const resolveMap = {};
267+
const expectedDeps = [];
268+
const expectedRegs = [];
269+
270+
const testXml = `
271+
<Page xmlns="http://www.nativescript.org/tns.xsd">
272+
<custom1:CustomComponent />
273+
<custom2:CustomComponent />
274+
</Page>`;
275+
276+
const loaderContext = getContext(done, { resolveMap, expectedDeps, expectedRegs, expectError: true });
277+
278+
xmlNsLoader.call(loaderContext, testXml);
279+
})
224280
});

Diff for: xml-namespace-loader.ts

+17-9
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,20 @@ interface NamespaceEntry {
1212

1313
const loader: loader.Loader = function (source: string, map) {
1414
const { ignore } = this.query;
15+
16+
let callbackCalled = false;
1517
const callback = this.async();
18+
const callbackWrapper = (error?: Error, content?: string, map?: any) => {
19+
if (!callbackCalled) {
20+
callbackCalled = true;
21+
callback(error, content, map);
22+
}
23+
}
24+
1625

1726
const resolvePromise = promisify(this.resolve);
1827
const promises: Promise<any>[] = [];
1928
const namespaces: NamespaceEntry[] = [];
20-
let parsingError = false;
2129

2230
const handleOpenTag = (namespace: string, elementName: string) => {
2331
const moduleName = `${namespace}/${elementName}`;
@@ -88,11 +96,15 @@ const loader: loader.Loader = function (source: string, map) {
8896
}
8997

9098
const saxParser = parser(true, { xmlns: true });
99+
100+
// Register ios and android prefixes as namespaces to avoid "unbound xml namespace" errors
101+
(<any>saxParser).ns["ios"] = "http://schemas.nativescript.org/tns.xsd";
102+
(<any>saxParser).ns["android"] = "http://schemas.nativescript.org/tns.xsd";
103+
91104
saxParser.onopentag = (node: QualifiedTag) => { handleOpenTag(node.uri, node.local); };
92105
saxParser.onerror = (err) => {
93106
saxParser.error = null;
94-
parsingError = true;
95-
callback(err);
107+
callbackWrapper(err);
96108
};
97109
saxParser.write(source).close();
98110

@@ -113,13 +125,9 @@ const loader: loader.Loader = function (source: string, map) {
113125

114126
const wrapped = `${moduleRegisters.join("")}\nmodule.exports = ${json}`;
115127

116-
if (!parsingError) {
117-
callback(null, wrapped, map);
118-
}
128+
callbackWrapper(null, wrapped, map);
119129
}).catch((err) => {
120-
if (!parsingError) {
121-
callback(err);
122-
}
130+
callbackWrapper(err);
123131
})
124132
}
125133

0 commit comments

Comments
 (0)