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

Commit 383b479

Browse files
committed
fix: wrap non-configurable custom element callbacks
Closes #24
1 parent f127fd4 commit 383b479

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

test/patch/registerElement.spec.js

+24
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,28 @@ describe('document.registerElement', function () {
106106
});
107107
});
108108

109+
110+
it('should work with prototypes that have non-writable, non-configurable descriptors', function () {
111+
runs(function () {
112+
var proto = Object.create(HTMLElement.prototype);
113+
Object.defineProperty(proto, 'createdCallback', {
114+
writeable: false,
115+
configurable: false,
116+
value: flagAndCheckZone
117+
});
118+
document.registerElement('x-prop-desc', {
119+
prototype: proto
120+
});
121+
var elt = document.createElement('x-prop-desc');
122+
});
123+
124+
waitsFor(function() {
125+
return flag;
126+
}, 'createdCallback to fire', 100);
127+
128+
runs(function() {
129+
expect(hasParent).toBe(true);
130+
});
131+
});
132+
109133
});

zone.js

+49-1
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ Zone.patch = function patch () {
368368
}
369369
Zone.patchMutationObserverClass('MutationObserver');
370370
Zone.patchMutationObserverClass('WebKitMutationObserver');
371+
Zone.patchDefineProperty();
371372
Zone.patchRegisterElement();
372373
};
373374

@@ -512,6 +513,49 @@ Zone.patchMutationObserverClass = function (className) {
512513
}
513514
};
514515

516+
// might need similar for object.freeze
517+
// i regret nothing
518+
Zone.patchDefineProperty = function () {
519+
var _defineProperty = Object.defineProperty;
520+
var _getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
521+
522+
Object.defineProperty = function (obj, prop, desc) {
523+
if (isUnconfigurable(obj, prop)) {
524+
throw new TypeError('Cannot assign to read only property \'' + prop + '\' of ' + obj);
525+
}
526+
return rewriteDescriptor(obj, prop, desc);
527+
};
528+
529+
Object.getOwnPropertyDescriptor = function (obj, prop) {
530+
var desc = _getOwnPropertyDescriptor(obj, prop);
531+
if (isUnconfigurable(obj, prop)) {
532+
desc.configurable = false;
533+
}
534+
return desc;
535+
};
536+
537+
Zone._redefineProperty = function (obj, prop, desc) {
538+
return rewriteDescriptor(obj, prop, desc);
539+
};
540+
541+
function isUnconfigurable (obj, prop) {
542+
return obj && obj.__unconfigurables && obj.__unconfigurables[prop];
543+
}
544+
545+
function rewriteDescriptor (obj, prop, desc) {
546+
if (!desc.configurable) {
547+
desc.configurable = true;
548+
if (!obj.__unconfigurables) {
549+
_defineProperty(obj, '__unconfigurables', {
550+
value: {}
551+
});
552+
}
553+
obj.__unconfigurables[prop] = true;
554+
}
555+
return _defineProperty(obj, prop, desc);
556+
}
557+
};
558+
515559
Zone.patchRegisterElement = function () {
516560
if (!('registerElement' in document)) {
517561
return;
@@ -526,7 +570,11 @@ Zone.patchRegisterElement = function () {
526570
document.registerElement = function (name, opts) {
527571
callbacks.forEach(function (callback) {
528572
if (opts.prototype[callback]) {
529-
opts.prototype[callback] = zone.bind(opts.prototype[callback]);
573+
var descriptor = Object.getOwnPropertyDescriptor(opts.prototype, callback);
574+
if (descriptor.value) {
575+
descriptor.value = zone.bind(descriptor.value);
576+
Zone._redefineProperty(opts.prototype, callback, descriptor);
577+
}
530578
}
531579
});
532580
return _registerElement.apply(document, [name, opts]);

0 commit comments

Comments
 (0)