How to fix v8 deprecated GetFunction? - node.js

I'm trying to repair node-osmium so that it works with Node 12 as I've got some old code I'd like to run.
v8 has now fully deprecated a lot of APIs that do not signal failure properly. These were previously only warnings of deprecation soon, they're now errors so it will no longer build. I (think I've) fixed most of these by following this CPP STYLE GUIDE.md's use maybe version of v8 APIs section.
But, i'm stuck with this error for GetFunction:
../src/utils.hpp:39:67: error: no matching function for call to ‘v8::FunctionTemplate::GetFunction()’
Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(T::constructor)->GetFunction(), 1, &ext);
I assume it's a similar fix as the other functions, but where do I get the context from in this constructor?
extract from node-osmium/src/utils.hpp:
namespace node_osmium {
template<class T>
auto unwrap(const v8::Local<v8::Object>& object) -> decltype(Nan::ObjectWrap::Unwrap<T>(object)->get()) {
return Nan::ObjectWrap::Unwrap<T>(object)->get();
}
template<class T, class... Args>
v8::Local<v8::Object> new_external(Args&&... args) {
Nan::EscapableHandleScope scope;
v8::Local<v8::Value> ext = Nan::New<v8::External>(new T(std::forward<Args>(args)...));
Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(T::constructor)->GetFunction(context), 1, &ext);
if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Buffer instance");
return scope.Escape(maybe_local.ToLocalChecked());
}
v8::Local<v8::Value> create_js_box(const osmium::Box& box);
osmium::osm_entity_bits::type object_to_entity_bits(v8::Local<v8::Object> options);
} // namespace node_osmium

Related

Can asynchronous module definitions be used with abstract syntax trees on v8 engine to read third party dependencies? This is for Cloudflare Workers

I understand eval string-to-function is impossible to use on the browsers' application programming interfaces, but there must be another strategy to use third party dependencies without node.js on v8 engine, given Cloudflare does it in-house, unless they disable the exclusive method by necessity or otherwise on their edge servers for Workers. I imagine I could gather the AST of the commonjs module, as I was able to by rollup watch, but what might the actual steps be, by tooling? I mention AMD for it seems to rely on string-to-function (to-which I've notice Mozilla MDN says nothing much about it).
I have been exploring the require.js repositories, and they either use eval or AST
function DEFNODE(type, props, methods, base) {
if (arguments.length < 4) base = AST_Node;
if (!props) props = [];
else props = props.split(/\s+/);
var self_props = props;
if (base && base.PROPS) props = props.concat(base.PROPS);
var code = "return function AST_" + type + "(props){ if (props) { ";
for (var i = props.length; --i >= 0; ) {
code += "this." + props[i] + " = props." + props[i] + ";";
}
var proto = base && new base();
if ((proto && proto.initialize) || (methods && methods.initialize))
code += "this.initialize();";
code += "}}";
//constructor
var cnstor = new Function(code)();
if (proto) {
cnstor.prototype = proto;
cnstor.BASE = base;
}
if (base) base.SUBCLASSES.push(cnstor);
cnstor.prototype.CTOR = cnstor;
cnstor.PROPS = props || null;
cnstor.SELF_PROPS = self_props;
cnstor.SUBCLASSES = [];
if (type) {
cnstor.prototype.TYPE = cnstor.TYPE = type;
}
if (methods)
for (i in methods)
if (HOP(methods, i)) {
if (/^\$/.test(i)) {
cnstor[i.substr(1)] = methods[i];
} else {
cnstor.prototype[i] = methods[i];
}
}
//a function that returns an object with [name]:method
cnstor.DEFMETHOD = function (name, method) {
this.prototype[name] = method;
};
if (typeof exports !== "undefined") exports[`AST_${type}`] = cnstor;
return cnstor;
}
var AST_Token = DEFNODE(
"Token",
"type value line col pos endline endcol endpos nlb comments_before file raw",
{},
null
);
https://codesandbox.io/s/infallible-darwin-8jcl2k?file=/src/mastercard-backbank/uglify/index.js
https://www.youtube.com/watch?v=EF7UW9HxOe4
Is it possible to make a C++ addon just to add a default object for
node.js named exports or am I Y’ing up the wrong X
'.so' shared library for C++ dlopen/LoadLibrary (or #include?)
“I have to say that I'm amazed that there is code out there that loads one native addon from another native addon! Is it done by acquiring and then calling an instance of the require() function, or perhaps by using uv_dlopen() directly?”
N-API: An api for embedding Node in applications
"[there is no ]napi_env[ just yet]."
node-api: allow retrieval of add-on file name - Missing module in Init
Andreas Rossberg - is AST parsing, or initialize node.js abstraction for native c++, enough?
v8::String::NewFromUtf8(isolate, "Index from C++!");
Rising Stack - Node Source
"a macro implicit" parameter - bridge object between
C++ and JavaScript runtimes
extract a function's parameters and set the return value.
#include <nan.h>
int build () {
NAN_METHOD(Index) {
info.GetReturnValue().Set(
Nan::New("Index from C++!").ToLocalChecked()
);
}
}
// Module initialization logic
NAN_MODULE_INIT(Initialize) {
/*Export the `Index` function
(equivalent to `export function Index (...)` in JS)*/
NAN_EXPORT(target, Index);
}
New module "App" Initialize function from NAN_MODULE_INIT (an atomic?-macro)
"__napi_something doesn't exist."
"node-addon-API module for C++ code (N-API's C code's headers)"
NODE_MODULE(App, Initialize);
Sep 17, 2013, 4:42:17 AM to v8-u...#googlegroups.com "This comes up
frequently, but the answer remains the same: scrap the idea. ;)
Neither the V8 parser nor its AST are designed for external
interfacing. In particular (1) V8's AST does not necessarily reflect
JavaScript syntax 1-to-1, (2) we change it all the time, and (3) it
depends on various V8 internals. And since all these points are
important for V8, don't expect the situation to change.
/Andreas"
V8 c++: How to import module via code to script context (5/28/22, edit)
"The export keyword may only be used in a module interface unit.
The keyword is attached to a declaration of an entity, and causes that
declaration (and sometimes the definition) to become visible to module
importers[ - except for] the export keyword in the module-declaration, which is just a re-use of the keyword (and does not actually “export” ...entities)."
SyntheticModule::virtual
ScriptCompiler::CompileModule() - "Corresponds to the ParseModule abstract operation in the ECMAScript specification."
Local<Function> foo_func = ...;//external
Local<Module> module = Module::CreateSyntheticModule(
isolate, name,
{String::NewFromUtf8(isolate, "foo")},
[](Local<Context> context, Local<Module> module) {
module->SetSyntheticModuleExport(
String::NewFromUtf8(isolate, "foo"), foo_func
);
});
Context-Aware addons from node.js' commonjs modules
export module index;
export class Index {
public:
const char* app() {
return "done!";
}
};
import index;
import <iostream>;
int main() {
std::cout << Index().app() << '\n';
}
node-addon-api (new)
native abstractions (old)
"Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.12 to 4.0, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect NODE_MODULE_VERSION and get yourself into a macro-tangle[ macro = extern atomics?]."
Scope Isolate (v8::Isolate), variable Local (v8::Local)
typed_array_to_native.cc
"require is part of the Asynchronous Module Definition AMD API[, without "string-to-function" eval/new Function()],"
node.js makes objects, for it is written in C++.
"According to the algorithm, before finding
./node_modules/_/index.js, it tried looking for express in the
core Node.js modules. This didn’t exist, so it looked in node_modules,
and found a directory called _. (If there was a
./node_modules/_.js, it would load that directly.) It then
loaded ./node_modules/_/package.json, and looked for an exports
field, but this didn’t exist. It also looked for a main field, but
this didn’t exist either. It then fell back to index.js, which it
found. ...require() looks for node_modules in all of the parent directories of the caller."
But java?
I won't accept this answer until it works, but this looks promising:
https://developer.oracle.com/databases/nashorn-javascript-part1.html
If not to run a jar file or something, in the Worker:
https://github.com/nodyn/jvm-npm
require and build equivalent in maven, first, use "dist/index.js".
Specifically: [ScriptEngineManager][21]
https://stackoverflow.com/a/15787930/11711280
Actually: js.commonjs-require experimental
https://docs.oracle.com/en/graalvm/enterprise/21/docs/reference-manual/js/Modules/
Alternatively/favorably: commonjs builder in C (v8 and node.js)
https://www.reddit.com/r/java/comments/u7elf4/what_are_your_thoughts_on_java_isolates_on_graalvm/
Here I will explore v8/node.js src .h and .cc for this purpose
https://codesandbox.io/s/infallible-darwin-8jcl2k?file=/src/c.cpp
I'm curious why there is near machine-level C operability in Workers if not to use std::ifstream, and/or build-locally, without node.js require.

Broken code generation for out function parameters

I made my own interface, simplistic version looks like this:
#ifndef _FOO_IDL_
#define _FOO_IDL_
module FOO {
typedef unsigned long Bar;
interface FOOInterface {
void getBar(out FOO::Bar b);
};
};
#endif
After that I made "REDHAWK IDL Project", used that IDL, compiled, installed.
Then I made Redhawk component, added output port and used that interface on it, did code generation. During compilation I got error:
port_impl.h:26:29: error: expected ‘,’ or ‘...’ before ‘&&’ token
void getBar(FOO::Bar&& b);
It looks like code generator adds excessive ampersand. What could I do about it?
Thank you.

Pubnub library not compiling on Particle Photon

I am trying to publish a message using pubnub on the Particle Photon. The code snippet below comes straight out of the Pubnub example code.
The code will not compile, with the message from the compiler as follows:
PubNub/PubNub.h:87:47: error: expected class-name before '{' token
class PubSubClient: public PubNub_BASE_CLIENT {
^
PubNub/PubNub.h: In constructor 'PubSubClient::PubSubClient()':
PubNub/PubNub.h:23:28: error: class 'PubSubClient' does not have any field named 'WiFiClient'
#define PubNub_BASE_CLIENT WiFiClient
^
The code for this tiny project is as follows:
// This #include statement was automatically added by the Particle IDE.
#include "PubNub/PubNub.h"
char pubkey[] = "<key here>";
char subkey[] = "<key here>";
char channel[] = "Channel";
void setup() {
Serial.begin(9600);
Particle.publish("Serial set up");
PubNub.begin(pubkey, subkey);
}
void loop() {
TCPClient *client;
char msg[64] = "{\"photon\":\"on\"}";
client = PubNub.publish(channel, msg);
client->stop();
Delay (30000);
}
Has anyone had a similar problem, and if so, can you guide me as to how to fix this.
Thanks.
It looks like the library available in Build IDE was in an older version (0.0.1). Fixed, latest version (0.0.2) has been published.
To update library in your app you need to remove the PubNub library from your app in Apps drawer:
And then go to Libraries drawer, find PubNub library, click Include in App, select your app and confirm:

GoogleTest CMake doesn't recognize TEST_F: Like it's not recognizing GTest something

OK, I admit it, this is a unique case. When we build our application we are using make, so I've included my tests in a test folder under src. Then at the same level as our release folder we have created a unit-test folder that includes all of our source files and our test source files.
But my IDE is CLion, which uses CMake. In my CMakeLists.txt file, I have included:
enable_testing()
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(TestProject ${SOURCE_FILES})
target_link_libraries(TestProject ${GTEST_BOTH_LIBRARIES})
I am creating my first Test Fixture. Here is the code:
#include "OPProperties.h"
#include "gtest/gtest.h"
namespace {
// The fixture for testing class OPPropertiesTestTest.
class OPPropertiesTestTest : public ::testing::Test {
protected:
// You can remove any or all of the following functions if its body
// is empty.
OPPropertiesTestTest() {
// You can do set-up work for each test here.
}
virtual ~OPPropertiesTestTest() {
// You can do clean-up work that doesn't throw exceptions here.
}
// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following methods:
virtual void SetUp() {
// Code here will be called immediately after the constructor (right
// before each test).
}
virtual void TearDown() {
// Code here will be called immediately after each test (right
// before the destructor).
}
// Objects declared here can be used by all tests in the test case for OPPropertiesTestTest.
};
TEST_F(OPPropertiesTestTest, ThisTestWillFail) {
EXPECT_EQ(0, 2);
}
} // namespace
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Here is an image capture:
Notice the syntax checker errors in my TEST_F function. When I started to type TEST_F code completion is trying to find a Boost Test Function.
Can someone tell me what else I need to add to the CMakeLists.txt file or what I am not doing that GTest functions are not being recognized?
As πάντα ῥεῖ pointed out, I hadn't actually tried to build the code. When I did I first received a linker error for pthread, so we added the following line the the CMakeLists.txt file:
target_link_libraries(OnePrint pthread)
Then I tried again to build and received these errors:
/home/user/gtest-1.7.0/lib/.libs/libgtest.so: undefined reference to `pthread_key_create'
/home/user/gtest-1.7.0/lib/.libs/libgtest.so: undefined reference to `pthread_getspecific'
/home/user/gtest-1.7.0/lib/.libs/libgtest.so: undefined reference to `pthread_key_delete'
/home/user/gtest-1.7.0/lib/.libs/libgtest.so: undefined reference to `pthread_setspecific'
collect2: error: ld returned 1 exit status
So, I ran a search on these errors and found this question.
The answer that worked for me was here.

error: cannot allocate an object of abstract type ‘FRONTEND_RFInfo_In_i

Using:
Redhawk 1.9 / CentOS 6.4 (32 bit) / C++ implementation
Creating a new FRONTEND::TUNER device
Using default setting on code generation
The following error message happens when I add the following port required for FRONTEND Digital Tuner and regenerate the code.
<ports>
<provides repid="IDL:FRONTEND/DigitalTuner:1.0" providesname="DigitalTuner"/>
<provides repid="IDL:FRONTEND/RFInfo:1.0" providesname="RFInfo"/>
</ports>
Error message (Problems window):
cannot allocate an object of abstract type
‘FRONTEND_RFInfo_In_i’ TestFrontEndDevice_base.cpp /TestFrontEndDevice/cpp line 50 C/C++ Problem
Error message (console):
port_impl.h:56: note: because the following virtual functions are
pure within ‘FRONTEND_RFInfo_In_i’:
/usr/local/redhawk/core/include/redhawk/FRONTEND/RFInfo.h:323: note:
virtual void FRONTEND::_impl_RFInfo::rf_flow_id(const char*)
/usr/local/redhawk/core/include/redhawk/FRONTEND/RFInfo.h:325: note:
virtual void FRONTEND::_impl_RFInfo::rfinfo_pkt(const
FRONTEND::RFInfoPkt&)
make: * [TestFrontEndDevice-TestFrontEndDevice_base.o] Error 1
There appears to be a bug in the code generation for the RFInfo class. If you compare the signatures of the generated code in the port_impl.h file to those of the "unimplemented" ones above, you'll notice that for the rf_flow_id function in port_impl.h there is no const keyword. The same can be said about the rfinfo_pkt method. It is missing the const keyword and an ampersand in the function declaration.
To fix this, simply add the const keywords and the ampersand in the appropriate places in both the declaration in the port_impl.h file and the definition in the port_impl.cpp file.
This is a known issue that has been fixed for the 1.9.1 release.
The problem is the result of the RFInfo port function signatures in
the generated port_impl.* files being different from those in the
parent/base class, which also happen to be pure virtual. To fix the
issue in your code, you'll need to add "const" to rf_flow_id, and both
"const" and "&" to rfinfo_pkt, as shown below:
In port_impl.h:
- void rf_flow_id( char* data);
+ void rf_flow_id( const char* data);
- void rfinfo_pkt( FRONTEND::RFInfoPkt data);
+ void rfinfo_pkt( const FRONTEND::RFInfoPkt& data);
In port_impl.cpp:
-void FRONTEND_RFInfo_In_i::rf_flow_id( char* data)
+void FRONTEND_RFInfo_In_i::rf_flow_id( const char* data)
-void FRONTEND_RFInfo_In_i::rfinfo_pkt( FRONTEND::RFInfoPkt data)
+void FRONTEND_RFInfo_In_i::rfinfo_pkt( const FRONTEND::RFInfoPkt& data)

Resources