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

Acroforms not working with zone.js (Angular 7 dependency) #2429

Closed
sirhcybe opened this issue Apr 17, 2019 · 10 comments
Closed

Acroforms not working with zone.js (Angular 7 dependency) #2429

sirhcybe opened this issue Apr 17, 2019 · 10 comments

Comments

@sirhcybe
Copy link

I've got an Angular 7 app and I want to generate some PDFs using jsPDF from it. I can generate text based PDFs with no problems but when I try to add an Acroform field the PDF is generated but the fields are missing. Here's the steps to reproduce the problem:

Create a new Angular app with Angular-CLI:

ng new jspdfTester
cd jspdfTester

Install jspdf
npm install -s jspdf
Add jspdf code to the app.component.ts file

import { Component } from '@angular/core';
import * as jsPDF from 'jspdf';

declare global {
  const TextField: any;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'jspdfTester';

  constructor() {
    const doc = new jsPDF();
    const textField = new TextField();
    textField.Rect = [50, 50, 30, 10];
    doc.addField(textField);
    doc.text('test', 50, 40);
    doc.save('sample.pdf');
  }
}

Run the app and a PDF will download that contains the test text but no text field.

After careful debugging it looks like the Object.getOwnPropertyDescriptor method from zone.js is being called instead of the browser's Object.getOwnPropertyDescriptor method. Apparently they work differently and it's breaking jsPDF because jsPDF expects some properties not to be configurable (line 667 of src/modules/acroform.js) and zone.js is reporting them as configurable.

@sirhcybe
Copy link
Author

sirhcybe commented Apr 17, 2019

As I'm digging into this more I found that, the problem is not with the zone.js override of Object.getOwnPropertyDescriptor but rather with its override of Object.defineProperty. If you take the "DA" property of an AcroForm object and step into the code where it's being defined, you will see that because the prop name is 'DA' and not 'prototype' and the desc object is not frozen, the configurable property of the desc object will be changed to true. Offending code is lines 27 and 70 here: https://github.com/angular/zone.js/blob/a5fe09b0fac27ac5df1fa746042f96f05ccb6a00/lib/browser/define-property.ts

So maybe the fix for this is to use Object.preventExtensions on the property description objects?

I also verified that a simple <script src="https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.9.0/zone.js"></script> should be able to reproduce this issue on any site that uses zone.js.

@sirhcybe sirhcybe changed the title Acroforms not working in Angular 7 - zone.js conflict Acroforms not working with zone.js (Angular 7 dependency) Apr 17, 2019
@sirhcybe
Copy link
Author

I've got a fork going to test that potential fix: https://github.com/sirhcybe/jsPDF/tree/master

@sirhcybe
Copy link
Author

I actually needed to use Object.freeze but I can confirm that this fixes the issue. The branch I tested with is https://github.com/sirhcybe/jsPDF/tree/zone.js-fix.

@Uzlopak
Copy link
Collaborator

Uzlopak commented Apr 17, 2019

Ok?! but why dont you report to zone.js that their Function does not work as expected?

@Uzlopak
Copy link
Collaborator

Uzlopak commented Apr 17, 2019

And why dont you just change Object.defineProperty in your local code to fix this issue of zone.js?

var origDefineProperty = Object.prototype.defineProperty;

Object.prototype.defineProperty = function() {
return origDefineProperty.call(this, arguments[0], arguments[1], Object.freeze(arguments[2]);
}

Not tested.

@Uzlopak Uzlopak closed this as completed Apr 17, 2019
@Uzlopak Uzlopak reopened this Apr 17, 2019
@sirhcybe
Copy link
Author

sirhcybe commented Apr 17, 2019

@arasabbasi You make a good point about reporting to zone.js so I've opened an issue with them as well.

I'm afraid to re-override Object.defineProperty because zone.js is tied so tightly into Angular that
I'm afraid I'll break core Angular functionality if I change something like that without understanding why it's there. I'm fairly confident that freezing the objects in jsPDF won't cause any subtle bugs to pop up in my production app.

@github-actions
Copy link

This issue is stale because it has been open 90 days with no activity. It will be closed soon. Please comment/reopen if this issue is still relevant.

@Eranot
Copy link

Eranot commented Jul 16, 2020

Did anyone find a solution for this?

@HackbrettXXX
Copy link
Collaborator

Could you check if this is still an issue when using the files from #2804? Run npm run build to get the bundles.

@sirhcybe
Copy link
Author

I think they fixed it with a subsequent release of zone.js.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants