| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
better use https://github.com/ungap/custom-elements#readme ? Warning: [@ungap/custom-elements](https://github.com/ungap/custom-elements#readme) is what you are looking for! |
Sorry, something went wrong.
| } | ||
|
|
||
| doConnectedCallback () { | ||
| ANode.prototype.connectedCallback.call(this); |
There was a problem hiding this comment.
what's wrong with:
super.connectedCallback();? 🤔
Sorry, something went wrong.
| // Custom Elements v1 polyfill | ||
| if (!window.customElements) { | ||
| const customElementsPolyfill = require('@webreflection/custom-elements'); | ||
| customElementsPolyfill(window || global); |
There was a problem hiding this comment.
you check for !window.customElements without checking if window exists at all, so this will never pass through the ||, or better, code will fail anyway if window is not around. I suggest to either remove that || global, as never reached, and maybe use self instead of window for Worker cases, or even better: globalThis.
That being said, you could use the proper, maintained, polyfill instead.
Sorry, something went wrong.
| global.document = _window.document; | ||
| global.screen = {}; | ||
| global.HTMLElement = _window.Element; | ||
| global.window.customElements = {define: function () {}}; |
There was a problem hiding this comment.
FYI LinkeDOM has customElements too
Sorry, something went wrong.
|
@kylebakerio Does this PR fix the issue with the camera? |
Sorry, something went wrong.
| } | ||
|
|
||
| this.addToParent(); | ||
| AEntity.prototype.doConnectedCallback.call(this); |
There was a problem hiding this comment.
We can use simply this.doConnectedCallback() here right?
Sorry, something went wrong.
| if (this.isScene) { return; } | ||
| doConnectedCallback () { | ||
| var assetsEl; // Asset management system element. | ||
| var sceneEl = this.sceneEl; |
There was a problem hiding this comment.
Does this thing work?
From my understanding, this.sceneEl is defined when executing ANode connectedCallback() but you call it after here.
Sorry, something went wrong.
There was a problem hiding this comment.
I confirm, I just added a console.log, this.sceneEl is always undefined here. If you put super.connectedCallback(); above, it will contain the scene element.
Sorry, something went wrong.
| connectedCallback () { | ||
| // Defer if DOM is not ready. | ||
| if (document.readyState === 'loading') { | ||
| document.addEventListener('DOMContentLoaded', this.connectedCallback.bind(this)); |
There was a problem hiding this comment.
Same here, you wanted to write this.doConnectedCallback.bind(this) right?
Sorry, something went wrong.
| if (this.timeout) { clearTimeout(this.timeout); } | ||
| } | ||
| }, | ||
| ANode.prototype.connectedCallback.call(this); |
There was a problem hiding this comment.
simply super.connectedCallback()
Sorry, something went wrong.
| connectedCallback () { | ||
| // Defer if DOM is not ready. | ||
| if (document.readyState === 'loading') { | ||
| document.addEventListener('DOMContentLoaded', this.connectedCallback.bind(this)); |
There was a problem hiding this comment.
I don't understand why you created a doConnectedCallback function if you don't use it here. The second time connectedCallback is called, we know the condition is false, so you intended do use this.doConnectedCallback.bind(this) here to not evaluate the condition again, right?
Sorry, something went wrong.
There was a problem hiding this comment.
It's effectively the same but this way when read it's more clear to see that we're just deferring the call. Don't have to read understand doConnectedCallback
Sorry, something went wrong.
There was a problem hiding this comment.
evaluating the condition only happens once so perf-wise is negligible over more clear code
Sorry, something went wrong.
There was a problem hiding this comment.
In your logic, if it's more clear to you to see that we're just deferring the call, and I can agree with that, then you don't even need to create a separate function doConnectedCallback, you can just put the code inside connectedCallback after the condition, unless I'm missing something why you created it. That's why it bothered me reading this code, when I have this pattern I usually create a function like this to use it as the callback, mostly important when the condition is costly so it's not executed a second time. Here I agree the condition cost is negligible.
To me, the condition is evaluated twice when the readyState is loading:
in comparison, using doConnectedCallback as the callback:
Sorry, something went wrong.
There was a problem hiding this comment.
I created it for readability. I like small focused functions when possible
Sorry, something went wrong.
There was a problem hiding this comment.
even if evaluated twice cost is negligible and it happens before the scene loads. Dynamically added entities once the DOM has loaded won't defer the call.
Sorry, something went wrong.
| connectedCallback () { | ||
| // Defer if DOM is not ready. | ||
| if (document.readyState === 'loading') { | ||
| document.addEventListener('DOMContentLoaded', this.connectedCallback.bind(this)); |
There was a problem hiding this comment.
use doConnectedCallback here
Sorry, something went wrong.
| disconnectedCallback () { | ||
| // Remove from scene index. | ||
| var sceneIndex = scenes.indexOf(this); | ||
| super.disconnectedCallback.call(this); |
There was a problem hiding this comment.
simply super.disconnectedCallback();
Sorry, something went wrong.
| return; | ||
| } | ||
| // ANode method. | ||
| super.connectedCallback(); |
There was a problem hiding this comment.
This line should really be at the top.
Sorry, something went wrong.
There was a problem hiding this comment.
@dmarcos there is actually no issue here, but a rather confusing code. I actually didn't see you do this.sceneEl twice here. You do this here:
var sceneEl = this.sceneEl; // but we know it's actually undefined because we didn't call super.connectedCallback() ... super.connectedCallback(); ... sceneEl = this.sceneEl;
so I'd suggest just to use
var sceneEl; ... super.connectedCallback(); ... sceneEl = this.sceneEl;
or
super.connectedCallback(); var sceneEl = this.sceneEl;
Sorry, something went wrong.
There was a problem hiding this comment.
I see you chose the first suggestion, great.
Sorry, something went wrong.
| for (componentName in this.components) { | ||
| this.removeComponent(componentName, false); | ||
| } | ||
| super.disconnectedCallback(); |
There was a problem hiding this comment.
We didn't have this call before. We call it a second time below.
Sorry, something went wrong.
There was a problem hiding this comment.
I tested the previous code, putting a console.log in detachedCallback and removing an a-entity element via the chrome inspector, it was called twice, I'm not sure why twice.
Here in the new code, this is called four times. Removing this line, disconnectedCallback is called twice, no error, tests are all passing.
Sorry, something went wrong.
There was a problem hiding this comment.
Thanks. I removed the duplicated call but don't see disconnectedCallback called twice. Can you double check or share steps to reproduce? Thanks
Sorry, something went wrong.
There was a problem hiding this comment.
You can add a console.log exactly where you just removed the line, open the inspector, right click on the node and remove. Anyway it's the same behavior than in the previous version now.
Sorry, something went wrong.
There was a problem hiding this comment.
Ah I just understood why I have it twice, I was removing a-entity that has a child a-camera, so I'm removing two entities at the same time that's why.
Sorry, something went wrong.
| } | ||
| }, | ||
| this.removeFromParent(); | ||
| super.disconnectedCallback.call(this); |
There was a problem hiding this comment.
simply super.disconnectedCallback();
Sorry, something went wrong.
| return element; | ||
| }); | ||
| observer.observe(this, observerConfig); | ||
| } |
There was a problem hiding this comment.
This is similar to what we had in the polyfill https://github.com/dmarcos/document-register-element/blob/cd665644367686d5645048f853d22fef9584bbf0/src/document-register-element.js#L529-L560 right? Previously we had a single MutationObserver instance for the whole document, here we have a MutationObserver instance for each node. Do we have to worry about performance here?
Sorry, something went wrong.
There was a problem hiding this comment.
I'm not too familiar about how the old polyfill worked. Not sure about the overhead of an observer. Any ideas on how to do it with one are welcome. it's a bit unfortunate that customElements V1 observed attributes can only be declared statically.
Sorry, something went wrong.
There was a problem hiding this comment.
I'm not familiar with it either, it was actually the first time I saw a MutationObserver object myself. Not sure about the performance really, I was just reading the comment about perf above the code I linked, this comment https://github.com/dmarcos/document-register-element/blob/cd665644367686d5645048f853d22fef9584bbf0/src/document-register-element.js#L526-L528
Sorry, something went wrong.
There was a problem hiding this comment.
if you check WebKit source code around MO you realize having one or many doesn't make much of a difference.
Sorry, something went wrong.
There was a problem hiding this comment.
Thanks @WebReflection for checking that. So we're good then.
Sorry, something went wrong.
There was a problem hiding this comment.
thanks @vincentfretin and @WebReflection for the feedback
Sorry, something went wrong.
Tested it. seems it does. |
Sorry, something went wrong.
| this.setAttribute('screenshot', ''); | ||
| this.setAttribute('vr-mode-ui', ''); | ||
| this.setAttribute('device-orientation-permission-ui', ''); | ||
| super.connectedCallback(); |
There was a problem hiding this comment.
Note that in previous code, the super method was called before setting the default components. This super method should be called at the top, an example super.connectedCallback(); is initializing (currently wrongly) this.sceneEl, and the component init may use this.sceneEl but it's probably not the case here.
Sorry, something went wrong.
Thanks so much for taking the time to test it. Much appreciated. |
Sorry, something went wrong.
| window.Promise = window.Promise || require('promise-polyfill'); | ||
|
|
||
| require('@ungap/custom-elements'); | ||
|
|
There was a problem hiding this comment.
@WebReflection with this statement the polyfill is a pass-through if custom elements API is defined? Just following the how-to: https://github.com/ungap/custom-elements#how-to
Thanks for the feedback
Sorry, something went wrong.
There was a problem hiding this comment.
the poly includes features detection and leave untouched browsers that implement latest status of the specs:
Sorry, something went wrong.
There was a problem hiding this comment.
Thanks @WebReflection. Just to double check. We're good just requiring the polyfill, are we? No other checks or initialization necessary?
Sorry, something went wrong.
There was a problem hiding this comment.
the poly includes features detection for all cases, including jurassic one where customElements is not a thing ... if you want to rise your target browsers, the Safari/WebKit only is an option but it requires manual feature detection ... happy to help with that though
Sorry, something went wrong.
There was a problem hiding this comment.
P.S. if you've fully switched to customElements without builtin extends support, that might even not be needed
Sorry, something went wrong.
|
Two important issues I commented that are not about code style #5136 (comment) and #5136 (comment) are not addressed yet, see my proposed changes here dmarcos#6 |
Sorry, something went wrong.
| return; | ||
| } | ||
| ANode.prototype.doConnectedCallback.call(this); | ||
| this.doConnectedCallback(); |
There was a problem hiding this comment.
This change was wrong, we need to put back the previous line.
I get this error with the change:
a-entity.js:73 Uncaught RangeError: Maximum call stack size exceeded
at a.doConnectedCallback (a-entity.js:73:3)
at a.connectedCallback (a-node.js:42:10)
at a.doConnectedCallback (a-entity.js:75:11)
at a.connectedCallback (a-node.js:42:10)
at a.doConnectedCallback (a-entity.js:75:11)
at a.connectedCallback (a-node.js:42:10)
at a.doConnectedCallback (a-entity.js:75:11)
at a.connectedCallback (a-node.js:42:10)
at a.doConnectedCallback (a-entity.js:75:11)
at a.connectedCallback (a-node.js:42:10)
Sorry, something went wrong.
There was a problem hiding this comment.
For a-scene, a-assets, a-mixin, we can use this.doConnectedCallback(); because we don't inherit from those.
But for a-node and a-entity, you can't use it, because it will call the doConnectedCallback from the derived class, we don't want that here.
Sorry, something went wrong.
|
I'm currently using a build with my changes in my project. I'll let you know if I find any other issue while I'm developing on it. |
Sorry, something went wrong.
|
I think this is close to ready. If you give me your blessing I'll go ahead and merge. |
Sorry, something went wrong.
|
There is just one last confusing code here https://github.com/aframevr/aframe/pull/5136/files#r1003525392 otherwise good to merge for me. |
Sorry, something went wrong.
|
All right! Merging. This PR is a scary one 😱 🤞 Perfect for Halloween. Thanks everybody for the feedback. Much much appreciated. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
A-Frame is still using custom elements v0 but always running through polyfill since the old API has been deprecated.
This modernizes the code base and makes use of the native APIs shipped in browsers today. Polyfill only kicks in for browser without an implementation of custom elements v1 API.
This will help us to better reason about #5124 and address the root cause.
This PR unifies behavior of all A-Frame defined HTML elements. All connectedCallback associated logic is deferred until DOMContentLoaded fires. This should eliminate the problems with entity inter-dependencies (e.g I want to query an entity from the init method of a component or system that might not have yet been initialized).