Svg.js: "elements" not mapped properly: Uncaught TypeError: adopter_elements[className] is not a constructor in adopter.js

Created on 26 Feb 2019  Â·  10Comments  Â·  Source: svgdotjs/svg.js

Bug report

Fiddle

The code I'm trying to run is:

SVG('#circles').size(300, 300);

where #circles is a DOM element that exists.

I'm using v3.0.12 and Webpack v4.22.

Explanation

  • What is the behaviour you expect?

The code should run. I'm upgrading from from v2.6.x so I'm not 100% sure this should work but I don't expect the error I'm getting.

  • What is happening instead?

The code runs through adopter.js#makeInstance as expected calling the adopter function like this return adopter(globals.document.querySelector(element)).

In adopter.js#adopter node is the correct DOM element and className ends up getting mapped to "Dom". However, all the keys in the elements map look to be wrong. "Dom" does not exist, instead there is "Dom_Dom". Similarly there is "Circle_Circle", "Matrix_Matrix" and so on.

It looks like element.name is wrong in the adopter.js#register function. It's not really clear to me where element.name is coming from though.

  • What error message are you getting?

The error message that appears in the console is:

adopter.js:67 Uncaught TypeError: adopter_elements[className] is not a constructor

Most helpful comment

see #1005

All 10 comments

Thats odd. Thanks for digging this up. I assume you used webpack to compile svg.js into your bundle? This could be the issue. When we register our classes, we use Function.name. It could be, that your minimizer renames the classes or that a polyfill for Function.name screws up or something like that. Can you take a look into your generated bundle and see whats in there? Are the classes still named correctly?

The classes are renamed to "Dom_Dom", etc. in the generated bundle. Names aren't mangled so I suspect this is happening in Babel. Looking some more.

I suspect I know whats going on. Extrapolating from your error message:

adopter.js:67 Uncaught TypeError: adopter_elements[className] is not a constructor

it seems like every variable is namespaced by putting the filename in front. In case of classes, the filename is the same as the class name which leads to that duplication. Well - That shouldnt happen. On the other hand: Maybe we shoudnt rely on Function.name for this!?!

In looking some more I couldn't find anything obvious. I'm going to put off the upgrade for now as it's not critical currently and I don't have more time to spend on this right now.

Given the API of the adopter.js#register function one possible fix is to manually pass the second param in rather than read the name property off the first param. Given that the code is using string constants to look up the values this might be best to avoid any mangling/minification issues down the line. Then again, maybe not. ¯_(ツ)_/¯

Maybe we shoudnt rely on Function.name for this!?!

Yeah, thinking about it some more this seems the most solid solution that will work regardless of Babel/Webpack/Rollup/Whatever configuration settings.

I commited that fix. Maybe you wanna test it?

Sorry it took me a few days to test this. Your change fixed this issue for me. Thank you for the quick turnaround!

thanks @Fuzzyma for the fix
I was running into the same issue with webpack 4

Having the same issue. Any plans to publish a new version to npm yet?

see #1005

Was this page helpful?
0 / 5 - 0 ratings

Related issues

HJWAJ picture HJWAJ  Â·  3Comments

Pangeli70 picture Pangeli70  Â·  7Comments

wout picture wout  Â·  4Comments

mixn picture mixn  Â·  9Comments

mtbradle-ge picture mtbradle-ge  Â·  6Comments