#2770 JS: Type methods (undefined)

SlimerDude Wed 4 Sep 2019

Methods on a Fantom JS Type don't seem to exist!?

@Js class TestStuff : Test {
    Void testCtor() {
        TestStuff#.methods
    }
}

Heralds:

> fan compilerJs::NodeRunner -test acme::TestStuff

C:\Apps\nodejs-9.4.0\node.exe

-- Run: acme::TestStuff.testCtor...
TypeError: Cannot read property 'size' of undefined (Unknown:Unknown)

Failed:
  acme::TestStuff.testCtor

Is this right?

andy Thu 5 Sep 2019

Not seeing that issue in browsers -- so might be an issue with how we're bootstrapping the nodejs vm -- not sure. Any more details?

SlimerDude Thu 5 Sep 2019

Well, I can do this:

@Js class TestStuff : Test {
    Void testCtor() {
        echo("Hello!")
        try TestStuff#.methods
        catch (Err err) err.trace
    }
}

which gives:

>fan compilerJs::NodeRunner -test acme -keep
C:\Apps\nodejs-10.16.3\node.exe

-- Run: acme::TestStuff.testCtor...
Hello!
sys::Err: Cannot read property 'size' of undefined
TypeError: Cannot read property 'size' of undefined
    at fan.sys.Type.doReflect (    at fan.sys.Type.doReflect (C:\Apps\fantom-1.0.73\temp\nodeRunner\node_modules\sys.js:6468:31)
    at fan.sys.Type.reflect (    at fan.sys.Type.reflect (C:\Apps\fantom-1.0.73\temp\nodeRunner\node_modules\sys.js:6460:6)
    at fan.sys.Type.$mergeType (    at fan.sys.Type.$mergeType (C:\Apps\fantom-1.0.73\temp\nodeRunner\node_modules\sys.js:6491:36)
    at fan.sys.Type.doReflect (    at fan.sys.Type.doReflect (C:\Apps\fantom-1.0.73\temp\nodeRunner\node_modules\sys.js:6469:6)
    at fan.sys.Type.reflect (    at fan.sys.Type.reflect (C:\Apps\fantom-1.0.73\temp\nodeRunner\node_modules\sys.js:6460:6)
    at fan.sys.Type.$mergeType (    at fan.sys.Type.$mergeType (C:\Apps\fantom-1.0.73\temp\nodeRunner\node_modules\sys.js:6491:36)
    at fan.sys.Type.doReflect (    at fan.sys.Type.doReflect (C:\Apps\fantom-1.0.73\temp\nodeRunner\node_modules\sys.js:6469:6)
    at fan.sys.Type.reflect (    at fan.sys.Type.reflect (C:\Apps\fantom-1.0.73\temp\nodeRunner\node_modules\sys.js:6460:6)
    at fan.sys.Type.methods (    at fan.sys.Type.methods (C:\Apps\fantom-1.0.73\temp\nodeRunner\node_modules\sys.js:6317:59)
    at fan.acme.TestStuff.testCtor (    at fan.acme.TestStuff.testCtor (C:\Apps\fantom-1.0.73\temp\nodeRunner\node_modules\acme.js:24:30)

   Pass: acme::TestStuff.testCtor [0]

And the acme.js file looks like:

(function () {
var root=this;
var fan=root.fan;
if (!fan && (typeof require !== 'undefined')) fan = require('sys.js');

if (typeof exports !== 'undefined') {
  fan.acme = exports;
} else {
  fan.acme = root.fan.acme = {};
}

...
...

fan.acme.TestStuff.prototype.testCtor = function()
{
  fan.sys.ObjUtil.echo("Hello!");
  try
  {
    fan.acme.TestStuff.$type.methods();
  }
  ...
  ...

Does that help?

andy Thu 5 Sep 2019

Ticket promoted to #2770 and assigned to andy

Yeah that helps -- will take a look

SlimerDude Thu 23 Jul 2020

Here you go, this tiny check for m_mixins fixes it:

diff --git a/src/sys/js/fan/Type.js b/src/sys/js/fan/Type.js
index b22e04e..02b89a6 100644
--- a/src/sys/js/fan/Type.js
+++ b/src/sys/js/fan/Type.js
@@ -448,5 +448,6 @@ fan.sys.Type.prototype.doReflect = function()
 
   // merge in base class and mixin classes
-  for (var i=0; i<this.m_mixins.size(); i++) this.$mergeType(this.m_mixins.get(i), slots, nameToSlot, nameToIndex);
+  if (this.m_mixins)
+    for (var i=0; i<this.m_mixins.size(); i++) this.$mergeType(this.m_mixins.get(i), slots, nameToSlot, nameToIndex);
   this.$mergeType(this.m_base, slots, nameToSlot, nameToIndex);
 

I do a lot of reflection - so this has been quite the pain point!

matthew Wed 29 Jul 2020

@SlimerDude - I tried your test case to reproduce this error, but I am not able to. Are you getting this error if you run with the latest development changesets?

SlimerDude Wed 29 Jul 2020

Hi Matthew, taking all your updates from yesterday, and running the test as indicated still gives me the same error:

C:\> fan compilerJs::NodeRunner -test acme

C:\Apps\nodejs-10.16.3\node.exe

-- Run: acme::TestStuff.testCtor...
Hello!
sys::Err: Cannot read property 'size' of undefined
TypeError: Cannot read property 'size' of undefined
    at fan.sys.Type.doReflect (    at fan.sys.Type.doReflect (C:\Repositories-Fantom\workDir\temp\nodeRunner\node_modules\sys.js:6516:31)
    at fan.sys.Type.reflect (    at fan.sys.Type.reflect (C:\Repositories-Fantom\workDir\temp\nodeRunner\node_modules\sys.js:6508:6)
    at fan.sys.Type.$mergeType (    at fan.sys.Type.$mergeType (C:\Repositories-Fantom\workDir\temp\nodeRunner\node_modules\sys.js:6539:36)
    at fan.sys.Type.doReflect (    at fan.sys.Type.doReflect (C:\Repositories-Fantom\workDir\temp\nodeRunner\node_modules\sys.js:6517:6)
    at fan.sys.Type.reflect (    at fan.sys.Type.reflect (C:\Repositories-Fantom\workDir\temp\nodeRunner\node_modules\sys.js:6508:6)
    at fan.sys.Type.$mergeType (    at fan.sys.Type.$mergeType (C:\Repositories-Fantom\workDir\temp\nodeRunner\node_modules\sys.js:6539:36)
    at fan.sys.Type.doReflect (    at fan.sys.Type.doReflect (C:\Repositories-Fantom\workDir\temp\nodeRunner\node_modules\sys.js:6517:6)
    at fan.sys.Type.reflect (    at fan.sys.Type.reflect (C:\Repositories-Fantom\workDir\temp\nodeRunner\node_modules\sys.js:6508:6)
    at fan.sys.Type.methods (    at fan.sys.Type.methods (C:\Repositories-Fantom\workDir\temp\nodeRunner\node_modules\sys.js:6365:59)
    at fan.acme.TestStuff.testCtor (    at fan.acme.TestStuff.testCtor (C:\Repositories-Fantom\workDir\temp\nodeRunner\node_modules\acme.js:24:30)

But adding in the one line to check for the existence of m_mixins fixes it.

You can see around line 22 of Type.js that m_mixins is only set in the ctor in an if statement, so it is not guaranteed to have a value:

fan.sys.Type.prototype.$ctor = function(qname, base, mixins, facets, flags)
{
  // workaround for inhertiance
  if (qname === undefined) return;

  // mixins
  if (fan.sys.Type.$type != null)
  {
    var acc = fan.sys.List.make(fan.sys.Type.$type, []);
    for (var i=0; i<mixins.length; i++)
      acc.add(fan.sys.Type.find(mixins[i]));
    this.m_mixins = acc.ro();  // <-- ONLY SET HERE
  }

  ...

And further down (~line 300) there's already another check for existence of m_mixins:

fan.sys.Type.prototype.mixins = function()
{
  // lazy-build mxins list for Obj and Type
  if (this.m_mixins == null)
    this.m_mixins = fan.sys.Type.$type.emptyList();
  return this.m_mixins;
}

matthew Thu 30 Jul 2020

Ticket resolved in 1.0.75

Login or Signup to reply.