Skip to content

Commit ec67e16

Browse files
Add support for set and get attribute with a NS (#471)
1 parent 0f9db34 commit ec67e16

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

integration-test/test-pages/runtime-checks/pages/basic-run.html

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,32 @@
176176
];
177177
});
178178

179+
test('Support namespaces', async () => {
180+
const scriptElement = document.createElement('script');
181+
scriptElement.id = 'scriptyNS';
182+
scriptElement.setAttribute('type', 'application/javascript');
183+
scriptElement.setAttributeNS(null, 'src', 'test://url');
184+
185+
const getAttributeNS = scriptElement.getAttributeNS(null, 'src');
186+
const getAttribute = scriptElement.getAttribute('src');
187+
188+
document.body.appendChild(scriptElement);
189+
const hadInspectorNode = scriptElement === document.querySelector('ddg-runtime-checks:last-of-type');
190+
// Continue to modify the script element after it has been added to the DOM
191+
scriptElement.madeUpProp = 'val';
192+
const instanceofResult = scriptElement instanceof HTMLScriptElement;
193+
const scripty = document.querySelector('#scriptyNS');
194+
195+
return [
196+
{ name: 'hadInspectorNode', result: hadInspectorNode, expected: true },
197+
{ name: 'expect script to match', result: scripty, expected: scriptElement },
198+
{ name: 'scripty.getAttribute', result: getAttribute, expected: 'test://url' },
199+
{ name: 'scripty.getAttributeNS', result: getAttribute, expected: 'test://url' },
200+
{ name: 'scripty.type', result: scripty.type, expected: 'application/javascript' },
201+
{ name: 'scripty.id', result: scripty.id, expected: 'scriptyNS' }
202+
];
203+
});
204+
179205
// eslint-disable-next-line no-undef
180206
renderResults();
181207
</script>

src/features/runtime-checks.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ const supportedSinks = ['src']
3535
// Store the original methods so we can call them without any side effects
3636
const defaultElementMethods = {
3737
setAttribute: HTMLElement.prototype.setAttribute,
38+
setAttributeNS: HTMLElement.prototype.setAttributeNS,
3839
getAttribute: HTMLElement.prototype.getAttribute,
40+
getAttributeNS: HTMLElement.prototype.getAttributeNS,
3941
removeAttribute: HTMLElement.prototype.removeAttribute,
4042
remove: HTMLElement.prototype.remove,
4143
removeChild: HTMLElement.prototype.removeChild
@@ -259,6 +261,13 @@ class DDGRuntimeChecks extends HTMLElement {
259261
return this._callMethod('getAttribute', name, value)
260262
}
261263

264+
getAttributeNS (namespace, name, value) {
265+
if (namespace) {
266+
return this._callMethod('getAttributeNS', namespace, name, value)
267+
}
268+
return Reflect.apply(DDGRuntimeChecks.prototype.getAttribute, this, [name, value])
269+
}
270+
262271
setAttribute (name, value) {
263272
if (shouldFilterKey(this.#tagName, 'attribute', name)) return
264273
if (supportedSinks.includes(name)) {
@@ -268,6 +277,13 @@ class DDGRuntimeChecks extends HTMLElement {
268277
return this._callMethod('setAttribute', name, value)
269278
}
270279

280+
setAttributeNS (namespace, name, value) {
281+
if (namespace) {
282+
return this._callMethod('setAttributeNS', namespace, name, value)
283+
}
284+
return Reflect.apply(DDGRuntimeChecks.prototype.setAttribute, this, [name, value])
285+
}
286+
271287
removeAttribute (name) {
272288
if (shouldFilterKey(this.#tagName, 'attribute', name)) return
273289
if (supportedSinks.includes(name)) {

0 commit comments

Comments
 (0)