Monkey patching constructors in builtin class hierarchies?

/#!/JoePea joe at trusktr.io
Tue Oct 24 17:25:18 UTC 2017


Well, I know I can set accessors on a prototype easily, but what I
mean is, I need each instance of an `Element` to have exactly one
instance of something right after construction during the same
synchronous operation.

For example, if we have an application with a bunch of pre-existing
Elements that do not extend from any classes of mine, I'd like for the
all to have `foo` properties, so that I can do this:

```js
const el = new SomeCustomElementThatWasDefinedCreatedByMe
console.log(el.foo) // it exists and is specific to the instance, not
a prototype property

// or

const div = document.createElement('div')
console.log(div.foo) // it exists and is specific to the instance, not
a prototype property
```

Can this be done?
/#!/JoePea


On Tue, Oct 24, 2017 at 10:19 AM, /#!/JoePea <joe at trusktr.io> wrote:
>> This feels like a problem similar to https://esdiscuss.org/topic/block-scoped-prototype-extensions
>
> @Boris, even if it were scoped, how do we monkey patch a
> *constructor*? By the way, for some reason your link to
> `https://esdiscuss.org/topic/block-scoped-prototype-extensions` posted
> as `https://esdiscuss.org/topic/block` which is 404. If you can edit
> it it would help others not to stumble on a broken link.
>
>> if that would be possible, then everyone could just monkey patch Object, right?
>
> But everyone can monkey patch the entire class already, aside from the
> constructor, by modifying the prototype. Obviously if someone returns
> something new from the constructor they might break everything, but it
> will be completely obvious and people then won't do that. The same
> applies with methods and properties, it is super easy to break entire
> applications monkey patching methods.
>
> ---
>
> So suppose I want to "polyfill" a concept. For example, I want all
> elements to have a new "foo" accessor after they've been constructed.
> Or for example, suppose `HTMLElement.prototype.style` and
> `SVGElement.prototype.style` didn't exist yet. How would I patch those
> in?
> /#!/JoePea
>
>
> On Tue, Oct 24, 2017 at 10:07 AM, Michał Wadas <michalwadas at gmail.com> wrote:
>> AFAIR DOM classes are not extensible by any means.
>>
>>
>>
>> On 24 Oct 2017 6:51 pm, "/#!/JoePea" <joe at trusktr.io> wrote:
>>>
>>> Is it possible to monkey-patch an intermediate constructor of a built-in
>>> subclass?
>>>
>>> For example, suppose I want all `Element` instances in a web app to have
>>> new instance properties, is there a way to monkey-patch the Element
>>> constructor so that when I make a custom element by extending a subclass of
>>> `Element` that the new logic will fire?
>>>
>>> For example:
>>>
>>> ```js
>>> // monkey-patch the Element constructor somehow so that it logs "patched
>>> in Element".
>>>
>>> // then
>>> class FooBar extends HTMLElement {}
>>> customElement.define('foo-bar', FooBar)
>>> new FooBar // "patched in Element"
>>> ```
>>>
>>> I tried
>>>
>>> ```js
>>> const OldElement = window.Element
>>>
>>> window.Element = function Element() {
>>>   const _this = new OldElement
>>>   console.log("patched in Element")
>>>   return _this
>>> }
>>>
>>> window.Element.prototype = OldElement.prototype
>>> window.Element.prototype.constructor = window.Element
>>>
>>> class FooBar extends HTMLElement {}
>>> customElements.define('f-b', FooBar)
>>> new FooBar // does not log "patched in Element"
>>> ```
>>>
>>> But when I make a new custom element, constructing it seems to use the old
>>> Element constructor, as if a non-global reference to the original
>>> constructor is kept inside a module so that modifying the global wouldn't
>>> have any effect.
>>>
>>> Is there a way to monkey patch a constructor in the middle of a built-in
>>> prototype chain or to otherwise inject construction logic to base classes of
>>> existing class hierarchies?
>>>
>>>
>>> /#!/JoePea
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>


More information about the es-discuss mailing list