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

Node.js 6.0.0 complains about deprecated v8::FunctionTemplate::Set() with non-primitive values #13

Closed
bsergeev opened this issue Apr 28, 2016 · 3 comments

Comments

@bsergeev
Copy link

When I run some C++ nbind-ed code with node v5.10.0, everything works fine.
But node v6.0.0 returns several warnings:

(node) v8::FunctionTemplate::Set() with non-primitive values is deprecated
(node) and will stop working in the next major release.

==== JS stack trace =========================================

Security context: 000001CC471C9FC9 <JS Object>#0#
    1: .node [module.js:568] [pc=000003D81714F664] (this=00000230B60B7749 <an Object with map 000000C2A2317241>#1#,module=00000230B60D74A9 <a Module with map 000000C2A2317819>#2#,filename=00000230B60D7001 <String[60]: build\Release\nbind.node>)
    2: load [module.js:456] [pc=000003D81713AAF2] (this=00000230B60D74A9 <a Module with map 000000C2A2317819>#2#,filename=00000230B60D7001 <String[60]: build\Release\nbind.node>)
    3: tryModuleLoad(aka tryModuleLoad) [module.js:415] [pc=000003D81713A61D] (this=000001CC47104189 <undefined>,module=00000230B60D74A9 <a Module with map 000000C2A2317819>#2#,filename=00000230B60D7001 <String[60]: build\Release\nbind.node>)
    4: _load [module.js:407] [pc=000003D817135A62] (this=00000230B6075361 <JS Function Module (SharedFunctionInfo 00000112075282E1)>#3#,request=00000230B60D7001 <String[60]: build\Release\nbind.node>,parent=00000230B60C6571 <a Module with map 000000C2A2317819>#4#,isMain=000001CC47104299 <false>)
    5: require [module.js:466] [pc=000003D817144E73] (this=00000230B60C6571 <a Module with map 000000C2A2317819>#4#,path=00000230B60D7001 <String[60]: build\Release\nbind.node>)
    6: require(aka require) [internal/module.js:20] [pc=000003D817144BA6] (this=000001CC47104189 <undefined>,path=00000230B60D7001 <String[60]: build\Release\nbind.node>)
    7: init [node_modules\nbind\index.js:96] [pc=000003D81714C458] (this=00000230B60CB051 <an Object with map 000000C2A2319659>#5#,basePath=00000230B60CB199 <String[42]: src/..>)
    8: /* anonymous */ [src\test.js:3] [pc=000003D8171443C1] (this=000001CC471E9141 <JS Global Object>#6#)
    9: /* anonymous */ [src\test.js:14] [pc=000003D817144678] (this=00000230B60BB1A9 <an Object with map 00000241D4F07B71>#7#,exports=00000230B60BB1A9 <an Object with map 00000241D4F07B71>#7#,require=00000230B60BD8F9 <JS Function require (SharedFunctionInfo 0000011207558DB9)>#8#,module=00000230B60BB0B1 <a Module with map 000000C2A2317819>#9#,__filename=00000230B60BB011 <String[47]: src\test.js>,__dirname=00000230B60BD821 <String[39]: src>)
   10: _compile [module.js:541] [pc=000003D817144064] (this=00000230B60BB0B1 <a Module with map 000000C2A2317819>#9#,content=00000230B60BD1A9 <String[361]\: (function(){\r\n  var nbind = require('nbind');\r\n      nbind.init(__dirname+"/..");\r\n  var WSM = nbind.module.ServerWSMWrapper;\r\n\r\n  function Pair(first, second) {\r\n      this.first  = first;\r\n      this.second = second;\r\n  }\r\n  nbind.bind('IntPair', Pair);\r\n\r\n  const ver = WSM.GetWSMVersion(); \r\n  console.log("WSM version "+ ver.first +"."+ ver.second);\r\n})();>,filename=00000230B60BB011 <String[47]: src\test.js>)
   11: .js [module.js:550] [pc=000003D81713CB8B] (this=00000230B60B7749 <an Object with map 000000C2A2317241>#1#,module=00000230B60BB0B1 <a Module with map 000000C2A2317819>#9#,filename=00000230B60BB011 <String[47]: src\test.js>)
   12: load [module.js:456] [pc=000003D81713AAF2] (this=00000230B60BB0B1 <a Module with map 000000C2A2317819>#9#,filename=00000230B60BB011 <String[47]: src\test.js>)
   13: tryModuleLoad(aka tryModuleLoad) [module.js:415] [pc=000003D81713A61D] (this=000001CC47104189 <undefined>,module=00000230B60BB0B1 <a Module with map 000000C2A2317819>#9#,filename=00000230B60BB011 <String[47]: src\test.js>)
   14: _load [module.js:407] [pc=000003D817135A62] (this=00000230B6075361 <JS Function Module (SharedFunctionInfo 00000112075282E1)>#3#,request=00000230B606FD39 <String[47]: src\test.js>,parent=000001CC47104101 <null>,isMain=000001CC47104231 <true>)
   15: runMain [module.js:575] [pc=000003D81713552A] (this=00000230B6075361 <JS Function Module (SharedFunctionInfo 00000112075282E1)>#3#)
   16: startup(aka startup) [node.js:159] [pc=000003D817040A3E] (this=000001CC47104189 <undefined>)
   17: /* anonymous */(aka /* anonymous */) [node.js:444] [pc=000003D81703E6D2] (this=000001CC47104101 <null>,process=000001CC471E52E1 <a process with map 00000241D4F10D89>#10#)
=====================

How can this be fixed? If I hade more insight of how nbind works, I would love to try fixing this...

@jjrv
Copy link
Member

jjrv commented Apr 29, 2016

Sorry, I'll be busy until Monday and not sure if I can look into this.

I updated all dependencies to the latest versions and saw lots of warnings running npm test.

Here's a related issue from another project and here's the fix.

The problematic code is probably here.

@jjrv
Copy link
Member

jjrv commented Apr 29, 2016

Basically nbind works by creating some classes and constructors and instantiates them through macros, just to get some code in the constructor to run as soon as the library is loaded. That's the block you write using NBIND_CLASS. The code just adds names of classes, methods, functions etc. in a global table, together with their signature (information about types they accept and return) as defined in classes under include/nbind/signature and discovered through template magic in include/nbind/BindDefiner.h.

When Node.js wants to initialize the module, it calls static void initModule implemented in src/v8/Binding.cc (that entry point is passed to Node.js in that same file using the NODE_MODULE macro). That function loops through the above mentioned global table and registers everything with Node.js.

Finally, when you actually call your C++ code from JavaScript, it actually calls wrappers under include/nbind/signature (because only function pointers can be called, not class methods). Those wrappers retrieve external data stored with the function pointer and handle type conversions.

For example when a method gets called, the path is:

  1. MethodSignature :: call - a static function, member of a templated class to ensure a copy gets created for each possible signature. Pointer to this is given to Node.js.
  2. BaseSignature :: callInnerSafely - Bigger function to check argument validity and throw errors. Inside a regular non-templated class so its code isn't duplicated in the compiled module's binary. Uses BaseSignature :: typesAreValid and Checker to test type compatibility.
  3. MethodSignature :: callInner - now we know the call is valid, so call another wrapper handling type conversion and pass its return value to JavaScript.
  4. The wrapper is defined in this typedef which maps C++ types to more general types that JavaScript values convert to, for example all JavaScript floats are doubles. At compile time the template uses ArgFromWire or its overloads, which use fromWireType for example defined here for numbers.
  5. Caller :: callMethod or its specialization for void return type which makes the final call to the actual C++ method.

The problem should be where the module is initialized (src/v8/Binding.cc) because that's where function pointers are passed to Node.js. The only other place passing them should be value object handling here.

@jjrv
Copy link
Member

jjrv commented May 2, 2016

Fixed in new release 0.1.2.

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

No branches or pull requests

2 participants