Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zone.js patchCallbacks with Lightning Web Components #42546

Closed
ivanovivelin opened this issue Jun 10, 2021 · 5 comments
Closed

Zone.js patchCallbacks with Lightning Web Components #42546

ivanovivelin opened this issue Jun 10, 2021 · 5 comments
Assignees
Labels
area: zones Issues related to zone.js type: bug/fix
Milestone

Comments

@ivanovivelin
Copy link

ivanovivelin commented Jun 10, 2021

Bug Report

Zone.js is incorrectly patching Lightning Web Components hooks when using those within an Angular project.

Description

Using Lightning Web Components in Angular project leads to an exception that comes out of Zone.js. It is trying to patch a attributeChangedCallback in LWC. The name of the method is patchCallbacks

Minimal Reproduction

  • Create a sample LWC and add it your Angular Project either as resource or as part of the build. Once you start the server you will see the error.

Exception or Error


Uncaught TypeError: Cannot assign to read only property 'attributeChangedCallback' of object '[object HTMLElement]'
    at zone.js:2163
    at Array.forEach ()
    at CustomElementRegistry.target. [as define] (zone.js:2147)

Your Environment

Angular Version:


Angular CLI: 12.0.3
Node: 14.15.1
Package Manager: npm 7.9.0
OS: darwin x64

Angular: 12.0.4
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1200.3
@angular-devkit/build-angular   12.0.3
@angular-devkit/core            12.0.3
@angular-devkit/schematics      12.0.3
@angular/cli                    12.0.3
@schematics/angular             12.0.3
rxjs                            6.6.7
typescript                      4.2.4

@alxhub alxhub added the area: zones Issues related to zone.js label Jun 10, 2021
@ngbot ngbot bot added this to the needsTriage milestone Jun 10, 2021
@JiaLiPassion JiaLiPassion self-assigned this Feb 20, 2022
@KunduAbhishek
Copy link

Hi,
I am facing the same issue, are there any developments or updates regarding it?

@ivanovivelin
Copy link
Author

ivanovivelin commented Mar 18, 2022

I had to do a small change to zone.js as attributeChangedCallback is just not a valid lifecycle hook for LWC. It will probably work fine for other web components like LitElement without this change.

function patchCallbacks(api, target, targetName, method, callbacks) {
    const symbol = Zone.__symbol__(method);
    if (target[symbol]) {
        return;
    }
    const nativeDelegate = target[symbol] = target[method];
    target[method] = function (name, opts, options) {
        if (opts && opts.prototype) {
            callbacks.forEach(function (callback) {
                const source = `${targetName}.${method}::` + callback;
                const prototype = opts.prototype;
                if (prototype.hasOwnProperty(callback)) {
                    const descriptor = api.ObjectGetOwnPropertyDescriptor(prototype, callback);
                    if (descriptor && descriptor.value) {
                        descriptor.value = api.wrapWithCurrentZone(descriptor.value, source);
                        api._redefineProperty(opts.prototype, callback, descriptor);
                    }
                    else if (prototype[callback]) {
                        prototype[callback] = api.wrapWithCurrentZone(prototype[callback], source);
                    }
                }
                else if (prototype[callback]) {
                    // here is the change
                    if(callback !== "attributeChangedCallback") {
                        prototype[callback] = api.wrapWithCurrentZone(prototype[callback], source);
                    }
                }
            });
        }
        return nativeDelegate.call(target, name, opts, options);
    };
    api.attachOriginToPatched(target[method], nativeDelegate);
}

@JiaLiPassion
Copy link
Contributor

@ivanovivelin , thank you for the information and the fix, could you provide a reproduce repo so I can check it?

arturovt added a commit to arturovt/angular that referenced this issue Mar 20, 2022
…hable

The `patchCallbacks` is used for patching the `document.registerElement` and
`customElements.define`. We explicitly wrap the patching code into try-catch since
callbacks may be already patched by other web components frameworks (e.g. LWC), and they
make those properties non-writable. This means that patching callback will throw an error
`cannot assign to read-only property`. See this code as an example:
https://github.com/salesforce/lwc/blob/master/packages/@lwc/engine-core/src/framework/base-bridge-element.ts#L180-L186
We don't want to stop the application rendering if we couldn't patch some
callback, e.g. `attributeChangedCallback`.

PR Close angular#42546
@ivanovivelin
Copy link
Author

ivanovivelin commented Mar 21, 2022

@ivanovivelin , thank you for the information and the fix, could you provide a reproduce repo so I can check it?

If you load a LWC into a sample Angular app you should be able to reproduce the issue. You can create a simple LWC app using create-lwc-app and then move the prod bundle JS into the assets of the Angular app and reference the custom element in the angular component.

  <c-my-lwc
    prefill='{"ContextId":"0Q00E00000119VQSAY"}'
    run-mode="localScriptDef"
  >
  </c-my-lwc>

Remember to import

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

I can provide a repo if still needed, but I see the PR is raised ? @JiaLiPassion

dylhunn pushed a commit that referenced this issue Mar 25, 2022
…hable (#45400)

The `patchCallbacks` is used for patching the `document.registerElement` and
`customElements.define`. We explicitly wrap the patching code into try-catch since
callbacks may be already patched by other web components frameworks (e.g. LWC), and they
make those properties non-writable. This means that patching callback will throw an error
`cannot assign to read-only property`. See this code as an example:
https://github.com/salesforce/lwc/blob/master/packages/@lwc/engine-core/src/framework/base-bridge-element.ts#L180-L186
We don't want to stop the application rendering if we couldn't patch some
callback, e.g. `attributeChangedCallback`.

PR Close #42546

PR Close #45400
PiyushAgrawal1243 pushed a commit to PiyushAgrawal1243/angular that referenced this issue Mar 30, 2022
…hable (angular#45400)

The `patchCallbacks` is used for patching the `document.registerElement` and
`customElements.define`. We explicitly wrap the patching code into try-catch since
callbacks may be already patched by other web components frameworks (e.g. LWC), and they
make those properties non-writable. This means that patching callback will throw an error
`cannot assign to read-only property`. See this code as an example:
https://github.com/salesforce/lwc/blob/master/packages/@lwc/engine-core/src/framework/base-bridge-element.ts#L180-L186
We don't want to stop the application rendering if we couldn't patch some
callback, e.g. `attributeChangedCallback`.

PR Close angular#42546

PR Close angular#45400
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Apr 25, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: zones Issues related to zone.js type: bug/fix
Projects
None yet
Development

No branches or pull requests

4 participants