Metadata placement inconsistency with replaced classes
Closed this issue · 4 comments
Metadata on the prototype is assigned prior to replacement classes whereas static metadata is after. While this should mostly be OK due to metadata inheritance (depending on shadowing), it could cause problems for direct references to the original class, for example from those made within the class itself.
const META = Symbol('meta')
function setMeta (data) {
return function (value, { setMetadata }) {
setMetadata(META, data)
}
}
function replace (C) {
return class Replacer extends C {}
}
@replace
class C {
@setMeta('static')
static x = 1;
@setMeta('instance')
x = 2;
reportMeta () {
console.log(C[Symbol.metadata][META].public.x) // undefined <- Expected?
console.log(C.prototype[Symbol.metadata][META].public.x) // "instance"
}
}
console.log(C[Symbol.metadata][META].public.x) // "static" (C here is Replacer)
C
in both cases would refer to Replacer
, all references to the original class are rebound to the replacement classes provided by any decorators.
That was the intent of the design, if I made a mistake in the spec would definitely appreciate your help in pointing it out. I will be rereviewing and doing another round of refinement in the near future, but am currently focused on implementing the Babel plugin.
The outcome of #329 was that classes would continue to be applied before static class fields are applied. If decorators wish to run code after the class has been fully constructed and static class fields had been assigned, then they could use @init
to add an initializer which would run at that time.
Closing: intended design should not exhibit this behavior. Added a comment in the PR.