Merged PR 277951: Remove legacy object-transporter.

Remove legacy object-transporter.
This commit is contained in:
Daiyi Peng 2017-05-26 00:11:45 +00:00 коммит произвёл Daiyi Peng
Родитель 7cc3a722bc
Коммит f8551f93b0
26 изменённых файлов: 3 добавлений и 911 удалений

Просмотреть файл

@ -5,7 +5,6 @@
<ProjectFile Include="async-number\dirs.proj" />
<ProjectFile Include="hello-world\dirs.proj" />
<ProjectFile Include="plus-number\dirs.proj" />
<ProjectFile Include="plus-number-transporter\dirs.proj" />
</ItemGroup>
<Import Project="$(ExtendedTargetsPath)\Traversal.targets" />

Просмотреть файл

@ -1,204 +0,0 @@
# Plus Number Transporter
This example shows how to pass the object instance to a module. It serializes/deserializes object's pointer and passes to
a module. This is useful when a host application needs to pass a native object to a module and
serialization/deserialization cost is too expensive. Napa provides helper APIs to serialize and deserialize an existing
object or new object. The important thing is that applicaiton owner is responsible for making an object alive until Napa
finishes processing a request containing a passing object. Napa helps type check, but not lifetime management.
## Serialization APIs
These APIs creates an object holder instance and its pointer value to pass to a module.
### Serialize existing object
```cpp
template <typename T>
static std::pair<uintptr_t, std::unique_ptr<ObjectTransporter>> ObjectTransporter::Serialize(T* object)
```
Since a module doesn't know about object's lifetime, this API is good for a global object. *ObjectTransporter* instance
must survive during request processing.
### Serialize new object
```cpp
template <typename T>
static std::pair<uintptr_t, std::unique_ptr<ObjectTransporter>> ObjectTransporter::Serialize(std::shared_ptr<T> object)
```
*ObjectTransporter* instance must survive during request processing.
## Deserialization APIs
```cpp
template <typename T>
static std::shared_ptr<T> ObjectTransporter::Deserialize(uintptr_t pointer)
```
It returns a passing object instance after deserializing a pointer value to object holder.
## Create new class
When you creates new class to be serializable, inherit from this class.
```cpp
template <typename T>
class TransportableObject
```
This provides *Serialize()* method as follows,
```cpp
std::pair<uintptr_t, std::unique_ptr<ObjectTransporter>> Serialize()
```
## Passing class
*plus-number-transporter.h* declares ths class with one constructor and one method, *Add()*. It's the subclass of
*TransportableObject<PlusNumberTransporter>* to enable serialization.
```h
#include <napa/object-transportable.h>
namespace napa {
namespace demo {
/// <summary> Example class to show how to pass object pointer to a module. </summary>
class PlusNumberTransporter : public module::TransportableObject<PlusNumberTransporter> {
public:
/// <summary> Constructor with initial value. </summary>
PlusNumberTransporter(double value = 0.0);
/// <summary> Add the given value and return the result. </summary>
double Add(double value);
private:
double _value;
};
} // napespace demo
} // namespace napa
```
## Module
*addon.cpp* defines a module, which has two methods *createPlusNumberTransporter* and *add*.
```cpp
#include <napa-module.h>
#include <napa/object-transport-v8-helpers.h>
#include <plus-number-transporter.h>
namespace napa {
namespace demo {
using namespace v8;
// Since there is no host to store ObjectTransporter instance, make it globally for test.
std::unique_ptr<module::ObjectTransporter> _objectTransporter;
void CreatePlusNumberTransporter(const FunctionCallbackInfo<Value>& args) {
auto isolate = args.GetIsolate();
HandleScope scope(isolate);
CHECK_ARG(isolate,
args.Length() == 0 || args.Length() == 1,
"Only one or no argument is allowed.");
if (args.Length() == 1) {
CHECK_ARG(isolate,
args[0]->IsNumber(),
"The first argument must be a number.");
}
double value = args[0]->IsUndefined() ? 0.0 : args[0]->NumberValue();
auto plusNumberTransporter = std::make_shared<PlusNumberTransporter>(value);
auto transporter = plusNumberTransporter->Serialize();
_objectTransporter.swap(transporter.second);
auto result = module::object_transport::UintptrToV8Uint32Array(isolate, transporter.first);
args.GetReturnValue().Set(result);
}
void Add(const FunctionCallbackInfo<Value>& args) {
auto isolate = args.GetIsolate();
HandleScope scope(isolate);
CHECK_ARG(isolate,
args.Length() == 1 || args.Length() == 2,
"Only one or two arguments are allowed.");
auto transporter = module::object_transport::V8Uint32ArrayToUintptr(isolate, args[0]);
CHECK_ARG(isolate,
transporter.second,
"The first argument must be a uint32 array.");
if (args.Length() == 2) {
CHECK_ARG(isolate,
args[1]->IsNumber(),
"The second argument must be a number.");
}
double value = args[1]->IsUndefined() ? 0.0 : args[1]->NumberValue();
auto object = module::ObjectTransporter::Deserialize<PlusNumberTransporter>(transporter.first);
CHECK_ARG(isolate,
object != nullptr,
"Can't deserialize ObjectTransporter containing PlusNumberTransporter instance");
auto result = object->Add(value);
args.GetReturnValue().Set(Number::New(isolate, result));
}
void InitAll(Local<Object> exports) {
NAPA_SET_METHOD(exports, "createPlusNumberTransporter", CreatePlusNumberTransporter);
NAPA_SET_METHOD(exports, "add", Add);
}
NAPA_MODULE(addon, InitAll);
} // namespace demo
} // namespace napa
```
* *createPlusNumberTransporter()* returns the uint32 V8 array representation of pointer value to object holder.
* *add()* has two parameters. The first one is the uint32 V8 array pointing to object holder, which is the return value
of *createPlusNumberTransporter()* in this example. The second one is an addend. This function deserializes and
restores a passing object and calls its *Add()* method.
### Napa helper APIs
```h
std::pair<uintptr_t, bool> napa::module::object_transport::V8Uint32ArrayToUintptr(v8::Isolate* isolate, const v8::Local<v8::Value>& source)
```
It converts a uint32 V8 array to uintptr. Return the pair of *{0, false}* if conversion fails.</summary>
```h
v8::Local<v8::Array> napa::module::object_transport::UintptrToV8Uint32Array(v8::Isolate* isolate, uintptr_t source)
```
It converts a uintptr to a uint32 V8 array. </summary>
## Typescript
It's recommended that typescript or typescript definition is provided to let the user know the APIs without
the source codes and develop Typescript project easily.
### plus-number-transporter.ts
```ts
var addon = require('../bin/addon');
export function createPlusNumberTransporter(value: number): any {
return addon.createPlusNumberTransporter(value);
}
export function add(transporter: any, value: number): number {
return addon.add(transporter, value);
}
```
### plus-number.d.ts
```d.ts
export declare function createPlusNumberTransporter(value: number): any;
export declare function add(transporter: any, value: number): number;
```
## Mocha test
```js
var assert = require('assert');
var plusNumberTransporter = require('plus-number-transporter');
describe('Test suite for plus-number-transporter', function() {
it('adds a given value', function() {
var transporter: any = plusNumberTransporter.createPlusNumberTransporter(3);
var result: number = plusNumberTransporter.add(transporter, 4);
assert.equal(result, 7);
});
})
```

Просмотреть файл

@ -1,13 +0,0 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<ItemGroup>
<ProjectFile Include="napa\addon.vcxproj" />
<ProjectFile Include="node\addon.vcxproj" />
<ProjectFile Include="script\script.proj" />
<ProjectFile Include="src\plus-number-transporter.vcxproj" />
<ProjectFile Include="test\dirs.proj" />
</ItemGroup>
<Import Project="$(ExtendedTargetsPath)\Traversal.targets" />
</Project>

Просмотреть файл

@ -1,24 +0,0 @@
#pragma once
#include <napa/module/object-transport.h>
namespace napa {
namespace demo {
/// <summary> Example class to show how to pass object pointer to a module. </summary>
class PlusNumberTransporter : public module::TransportableObject<PlusNumberTransporter> {
public:
/// <summary> Constructor with initial value. </summary>
explicit PlusNumberTransporter(double value = 0.0);
/// <summary> Add the given value and return the result. </summary>
double Add(double value);
private:
double _value;
};
} // napespace demo
} // namespace napa

Просмотреть файл

@ -1,6 +0,0 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AddonType>Napa</AddonType>
</PropertyGroup>
<Import Project="..\node\addon.vcxproj" />
</Project>

Просмотреть файл

@ -1,78 +0,0 @@
#include <napa-module.h>
#include <napa/module/object-transport-v8-helpers.h>
#include <plus-number-transporter.h>
namespace napa {
namespace demo {
using namespace v8;
// Since there is no host to store ObjectTransporter instance, make it globally for test.
std::unique_ptr<module::ObjectTransporter> _objectTransporter;
void CreatePlusNumberTransporter(const FunctionCallbackInfo<Value>& args) {
auto isolate = args.GetIsolate();
HandleScope scope(isolate);
CHECK_ARG(isolate,
args.Length() == 0 || args.Length() == 1,
"Only one or no argument is allowed.");
if (args.Length() == 1) {
CHECK_ARG(isolate,
args[0]->IsNumber(),
"The first argument must be a number.");
}
double value = args[0]->IsUndefined() ? 0.0 : args[0]->NumberValue();
auto plusNumberTransporter = std::make_shared<PlusNumberTransporter>(value);
auto transporter = plusNumberTransporter->Serialize();
_objectTransporter.swap(transporter.second);
auto result = module::object_transport::UintptrToV8Uint32Array(isolate, transporter.first);
args.GetReturnValue().Set(result);
}
void Add(const FunctionCallbackInfo<Value>& args) {
auto isolate = args.GetIsolate();
HandleScope scope(isolate);
CHECK_ARG(isolate,
args.Length() == 1 || args.Length() == 2,
"Only one or two arguments are allowed.");
CHECK_ARG(isolate,
args[0]->IsArray(),
"The first argument must be an array");
auto transporter = module::object_transport::V8Uint32ArrayToUintptr(isolate, Local<Array>::Cast(args[0]));
CHECK_ARG(isolate,
transporter.second,
"The first argument has a wrong pointer representation.");
if (args.Length() == 2) {
CHECK_ARG(isolate,
args[1]->IsNumber(),
"The second argument must be a number.");
}
double value = args[1]->IsUndefined() ? 0.0 : args[1]->NumberValue();
auto object = module::ObjectTransporter::Deserialize<PlusNumberTransporter>(transporter.first);
CHECK_ARG(isolate,
object != nullptr,
"Can't deserialize ObjectTransporter containing PlusNumberTransporter instance");
auto result = object->Add(value);
args.GetReturnValue().Set(Number::New(isolate, result));
}
void InitAll(Local<Object> exports) {
NAPA_SET_METHOD(exports, "createPlusNumberTransporter", CreatePlusNumberTransporter);
NAPA_SET_METHOD(exports, "add", Add);
}
NAPA_MODULE(addon, InitAll);
} // namespace demo
} // namespace napa

Просмотреть файл

@ -1,53 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup>
<AddonName>addon</AddonName>
<TargetName Condition=" '$(AddonType)' != 'Napa' ">$(AddonName)</TargetName>
<TargetName Condition=" '$(AddonType)' == 'Napa' ">$(AddonName)_napa</TargetName>
</PropertyGroup>
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions Condition=" '$(AddonType)' != 'Napa' ">BUILDING_NODE_EXTENSION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition=" '$(AddonType)' == 'Napa' ">BUILDING_NAPA_EXTENSION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\examples\modules\plus-number-transporter\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition=" '$(AddonType)' == 'Napa' ">$(PkgNapa_V8_Library)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies Condition=" '$(AddonType)' == 'Napa' ">$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="$(NapaVanillaRoot)\examples\modules\plus-number-transporter\src\plus-number-transporter.vcxproj" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)\addon.cpp" />
</ItemGroup>
<Target Name="ChangeExtention" AfterTargets="Build">
<Move SourceFiles="$(OutputPath)\$(TargetFileName)" DestinationFiles="$(OutputPath)\$(AddonName).node" Condition=" '$(AddonType)' != 'Napa' " />
<Move SourceFiles="$(OutputPath)\$(TargetFileName)" DestinationFiles="$(OutputPath)\$(AddonName).napa" Condition=" '$(AddonType)' == 'Napa' " />
</Target>
<Import Project="$(PACKAGESROOT)\NodeJs.Library\exports.props" Condition=" '$(AddonType)' != 'Napa' " />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Просмотреть файл

@ -1,8 +0,0 @@
{
"name": "plus-number-transporter",
"version": "0.0.1",
"author": "napav",
"description": "Example of a napa module passing an object by pointer.",
"main": "./lib/plus-number-transporter.js",
"types": "./types/plus-number-transporter.d.ts"
}

Просмотреть файл

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<ItemGroup>
<QCustomProjectReference Include="$(NapaVanillaRoot)\examples\modules\plus-number-transporter\napa\addon.vcxproj" />
<QCustomProjectReference Include="$(NapaVanillaRoot)\examples\modules\plus-number-transporter\node\addon.vcxproj" />
</ItemGroup>
<ItemGroup>
<QCustomInput Include="src\plus-number-transporter.ts" />
<QCustomInput Include="$(NapaBuildRoot)\**\*" />
</ItemGroup>
<Target Name="BuildScripts" AfterTargets="AfterBuild">
<Message Text="Compile scripts." />
<Exec Command="$(TSCompile) src\plus-number-transporter.ts --declaration --typeRoots $(TypesRoot) --outDir $(O)" />
</Target>
<Target Name="CreateNpmPackage" DependsOnTargets="BuildScripts" AfterTargets="AfterBuild">
<Message Text="Create NPM package." />
<MakeDir Directories="$(O)\dist\bin" ContinueOnError="false" Condition="!Exists('$(O)\dist\bin')" />
<MakeDir Directories="$(O)\dist\lib" ContinueOnError="false" Condition="!Exists('$(O)\dist\lib')" />
<MakeDir Directories="$(O)\dist\types" ContinueOnError="false" Condition="!Exists('$(O)\dist\types')" />
<Copy SourceFiles="..\node\$(O)\addon.node" DestinationFolder="$(O)\dist\bin" ContinueOnError="false" SkipUnchangedFiles="true" />
<Copy SourceFiles="..\napa\$(O)\addon.napa" DestinationFolder="$(O)\dist\bin" ContinueOnError="false" SkipUnchangedFiles="true" />
<Copy SourceFiles="$(NapaVanillaRoot)\src\$(O)\napa.dll" DestinationFolder="$(O)\dist\bin" ContinueOnError="false" SkipUnchangedFiles="true" />
<Copy SourceFiles="$(O)\plus-number-transporter.js" DestinationFolder="$(O)\dist\lib" ContinueOnError="false" SkipUnchangedFiles="true" />
<Copy SourceFiles="$(O)\plus-number-transporter.d.ts" DestinationFolder="$(O)\dist\types" ContinueOnError="false" SkipUnchangedFiles="true" />
<Copy SourceFiles="package.json" DestinationFolder="$(O)\dist" ContinueOnError="false" SkipUnchangedFiles="true" />
</Target>
<Import Project="$(ExtendedTargetsPath)\NoTarget.targets" />
</Project>

Просмотреть файл

@ -1,9 +0,0 @@
var addon = require('../bin/addon');
export function createPlusNumberTransporter(value: number): any {
return addon.createPlusNumberTransporter(value);
}
export function add(transporter: any, value: number): number {
return addon.add(transporter, value);
}

Просмотреть файл

@ -1,11 +0,0 @@
#include "plus-number-transporter.h"
using namespace napa::demo;
PlusNumberTransporter::PlusNumberTransporter(double value)
: _value(value) {
}
double PlusNumberTransporter::Add(double value) {
return _value + value;
}

Просмотреть файл

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="plus-number-transporter.cpp" />
</ItemGroup>
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Просмотреть файл

@ -1,10 +0,0 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<ItemGroup>
<ProjectFile Include="library-test\library-test.vcxproj" />
<ProjectFile Include="module-test\plus-number-transporter-test.njsproj" />
</ItemGroup>
<Import Project="$(ExtendedTargetsPath)\Traversal.targets" />
</Project>

Просмотреть файл

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\examples\modules\plus-number-transporter\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\third-party;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="$(NapaVanillaRoot)\examples\modules\plus-number-transporter\src\plus-number-transporter.vcxproj" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Просмотреть файл

@ -1,13 +0,0 @@
#include <plus-number-transporter.h>
#define CATCH_CONFIG_MAIN
#include <catch/catch.hpp>
using namespace napa::demo;
TEST_CASE("PlusNumberTransporter: add the given value", "[add]") {
PlusNumberTransporter plusNumberTransporter(3);
REQUIRE(plusNumberTransporter.Add(2) == 5);
REQUIRE(plusNumberTransporter.Add(3) != 7);
}

Просмотреть файл

@ -1,2 +0,0 @@
build/
tsconfig.json

Просмотреть файл

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<PropertyGroup>
<AssemblyName>plus-number-transporter-test</AssemblyName>
</PropertyGroup>
<!-- Test files -->
<!-- It's using the default tsconfig.json@Napa.DevTools -->
<ItemGroup>
<TypeScriptCompile Include="test.ts" />
</ItemGroup>
<Import Project="$(PkgNapa_DevTools)\Napa.TestAdapter.targets" />
<ItemGroup>
<Robocopy Include="..\..\script\$(IntermediateOutputPath)\dist">
<DestinationFolder>$(QTestDirToDeploy)\app\node_modules\plus-number-transporter</DestinationFolder>
</Robocopy>
</ItemGroup>
</Project>

Просмотреть файл

@ -1,10 +0,0 @@
var assert = require('assert');
var plusNumberTransporter = require('plus-number-transporter');
describe('Test suite for plus-number-transporter', function() {
it('adds a given value', function() {
var transporter: any = plusNumberTransporter.createPlusNumberTransporter(3);
var result: number = plusNumberTransporter.add(transporter, 4);
assert.equal(result, 7);
});
})

Просмотреть файл

@ -1,71 +0,0 @@
#pragma once
#include "object-transport.h"
#include <v8.h>
namespace napa {
namespace module {
namespace object_transport {
/// <summary> Convert a V8 uint32 array to uintptr. </summary>
/// <param name="isolate"> V8 Isolate instance. </summary>
/// <param name="source"> V8 uint32 array holding pointer value. </summary>
/// <returns> The pair of converted pointer value and success/failure. </returns>
inline std::pair<uintptr_t, bool> V8Uint32ArrayToUintptr(v8::Isolate* isolate, const v8::Local<v8::Array>& source) {
if (source->Length() != UINTPTR_SIZE_IN_UINT32) {
return std::make_pair(0, false);
}
auto context = isolate->GetCurrentContext();
uintptr_t result = 0;
for (uint32_t i = 0; i < source->Length(); ++i) {
auto value = source->Get(context, i).ToLocalChecked();
if (!value->IsUint32()) {
return std::make_pair(0, false);
}
result |= static_cast<uintptr_t>(value->Uint32Value()) << 32 * i;
}
return std::make_pair(result, true);
}
/// <summary> Convert a V8 uint32 array to void pointer. </summary>
/// <param name="isolate"> V8 Isolate instance. </summary>
/// <param name="source"> V8 uint32 array holding pointer value. </summary>
/// <returns> The pair of success and converted void pointer. </returns>
template <typename T = void>
inline std::pair<T*, bool> V8Uint32ArrayToPtr(v8::Isolate* isolate, const v8::Local<v8::Array>& source) {
auto result = V8Uint32ArrayToUintptr(isolate, source);
return std::make_pair(static_cast<T*>(reinterpret_cast<void*>(result.first)), result.second);
}
/// <summary> Convert a pointer value to V8 Uint32 array. </summary>
/// <param name="isolate"> V8 Isolate instance. </summary>
/// <param name="source"> Pointer value. </summary>
/// <returns> V8 uint32 array </returns>
inline v8::Local<v8::Array> UintptrToV8Uint32Array(v8::Isolate* isolate, uintptr_t source) {
v8::EscapableHandleScope scope(isolate);
auto context = isolate->GetCurrentContext();
auto target = v8::Array::New(isolate, UINTPTR_SIZE_IN_UINT32);
for (uint32_t i = 0; i < UINTPTR_SIZE_IN_UINT32; ++i) {
auto value = static_cast<uint32_t>(source);
target->CreateDataProperty(context, i, v8::Integer::NewFromUnsigned(isolate, value));
source >>= 32;
}
return scope.Escape(target);
}
/// <summary> Convert a void pointer to V8 Uint32 array. </summary>
/// <param name="isolate"> V8 Isolate instance. </summary>
/// <param name="source"> Void pointer. </summary>
/// <returns> V8 uint32 array </returns>
inline v8::Local<v8::Array> PtrToV8Uint32Array(v8::Isolate* isolate, void* pointer) {
return UintptrToV8Uint32Array(isolate, reinterpret_cast<uintptr_t>(pointer));
}
}
}
}

Просмотреть файл

@ -1,115 +0,0 @@
#pragma once
#include <array>
#include <memory>
#include <typeindex>
namespace napa {
namespace module {
/// <summary>
/// It makes a module to be able to use a host's native object.
/// It doesn't guarantee that object destruction is perfectly detected by a module.
/// So, Host application should make ObjectTransporter instance returned by Serialized() alive until a request is processed.
/// </summary>
class ObjectTransporter final {
public:
/// <summary> Constructor. </summary>
/// <param name="object"> Shared pointer to object instance. </param>
/// <param name="type"> Object type information. </param>
/// <remarks> Serialize() plays a role of factory to create an instance. </remarks>
ObjectTransporter(std::shared_ptr<void> object,
std::type_index type)
: _object(object)
, _type(type) {}
/// <summary> Create an ObjectTransporter instance and its pointer value to pass to a module. </summary>
/// <param name="object"> Object to be accessed by a module. </param>
/// <returns> Pair of ObjectTransporter instance and pointer value. </returns>
/// <remarks> Since a module doesn't know object's lifetime, this API is good to pass a global object. </remarks>
template <typename T>
static std::pair<uintptr_t, std::unique_ptr<ObjectTransporter>> Serialize(T* object) {
return Serialize(std::shared_ptr<T>(object, [](T*) {}));
}
/// <summary> Create an ObjectTransporter instance and its pointer value to pass to a module. </summary>
/// <param name="object"> Shared pointer type of object to be accessed by a module. </param>
/// <returns> Pair of ObjectTransporter instance and pointer value. </returns>
template <typename T>
static std::pair<uintptr_t, std::unique_ptr<ObjectTransporter>> Serialize(std::shared_ptr<T> object) {
auto transporter = std::make_unique<ObjectTransporter>(
std::static_pointer_cast<void>(std::move(object)),
typeid(T));
return std::pair<uintptr_t, std::unique_ptr<ObjectTransporter>>(
reinterpret_cast<uintptr_t>(transporter.get()),
std::move(transporter));
}
/// <summary> Get a passing object instance from pointer value of ObjectTransporter. </summary>
/// <param name="pointer"> Pointer value of ObjectTransporter instance. </param>
/// <returns> Passing object instance. </returns>
template <typename T>
static std::shared_ptr<T> Deserialize(uintptr_t pointer) {
auto transporter = reinterpret_cast<ObjectTransporter*>(pointer);
if (std::type_index(typeid(T)) != transporter->_type) {
return nullptr;
}
return std::static_pointer_cast<T>(transporter->_object);
}
private:
/// <summary> Pointer to passing object. </summary>
std::shared_ptr<void> _object;
/// <summary> Type information of passing object. </summary>
std::type_index _type;
};
template <typename T>
class TransportableObject : public std::enable_shared_from_this<TransportableObject<T>> {
public:
std::pair<uintptr_t, std::unique_ptr<ObjectTransporter>> Serialize() {
auto transporter = std::make_unique<ObjectTransporter>(
std::static_pointer_cast<void>(shared_from_this()),
typeid(T));
return std::pair<uintptr_t, std::unique_ptr<ObjectTransporter>>(
reinterpret_cast<uintptr_t>(transporter.get()),
std::move(transporter));
}
};
static const uint32_t UINTPTR_SIZE_IN_UINT32 = static_cast<uint32_t>(sizeof(uintptr_t) / sizeof(uint32_t));
}
namespace module {
namespace object_transport {
/// <summary> Convert a pointer value to uint32 array. </summary>
/// <param name="source"> Pointer value. </summary>
/// <returns> uint32 array. </returns>
inline std::array<uint32_t, UINTPTR_SIZE_IN_UINT32> UintptrToUint32Array(uintptr_t source) {
std::array<uint32_t, UINTPTR_SIZE_IN_UINT32> target = {};
for (uint32_t i = 0; i < UINTPTR_SIZE_IN_UINT32; ++i, source >>= 32) {
target[i] = static_cast<uint32_t>(source);
}
return target;
}
/// <summary> Convert a uint32 array to uintptr. </summary>
/// <param name="source"> a uint32 array holding pointer value. </summary>
/// <returns> Converted pointer value. </returns>
inline uintptr_t Uint32ArrayToUintptr(const std::array<uint32_t, UINTPTR_SIZE_IN_UINT32>& source) {
uintptr_t result = 0;
for (uint32_t i = 0; i < UINTPTR_SIZE_IN_UINT32; ++i) {
result |= static_cast<uintptr_t>(source[i]) << 32 * i;
}
return result;
}
}
}
}

Просмотреть файл

@ -84,7 +84,6 @@
<ClCompile Include="main.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)\worker-tests.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)\tasks-tests.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)\object-transport-v8-helpers-tests.cpp" />
</ItemGroup>
<!-- Test artifacts binplace -->

Просмотреть файл

@ -1,55 +0,0 @@
#include <catch.hpp>
#include <napa/module/object-transport-v8-helpers.h>
using namespace napa::module;
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
public:
virtual void* Allocate(size_t length) override {
void* data = AllocateUninitialized(length);
return memset(data, 0, length);
}
virtual void* AllocateUninitialized(size_t length) override {
return malloc(length);
}
virtual void Free(void* data, size_t length) override {
free(data);
}
};
TEST_CASE("v8-helpers works as expected", "[v8-helpers]") {
ArrayBufferAllocator allocator;
v8::Isolate::CreateParams createParams;
createParams.array_buffer_allocator = &allocator;
auto isolate = v8::Isolate::New(createParams);
{
v8::Locker locker(isolate);
v8::Isolate::Scope isolateScope(isolate);
v8::HandleScope handleScope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope contextScope(context);
SECTION("pointer value is serialized/deserialized correctly", "[v8-helpers]") {
auto source = reinterpret_cast<uintptr_t>(isolate);
auto v8array = object_transport::UintptrToV8Uint32Array(isolate, source);
auto target = object_transport::V8Uint32ArrayToUintptr(isolate, v8array);
REQUIRE(target.second == true);
REQUIRE(target.first == source);
}
SECTION("pointer is serialized/deserialized correctly", "[v8-helpers]") {
auto v8array = object_transport::PtrToV8Uint32Array(isolate, isolate);
auto target = object_transport::V8Uint32ArrayToPtr(isolate, v8array);
REQUIRE(target.second == true);
REQUIRE(target.first == isolate);
}
}
isolate->Dispose();
}

Просмотреть файл

@ -116,7 +116,7 @@ TEST_CASE("tasks", "[tasks]") {
request.arguments = { NAPA_STRING_REF("3"), NAPA_STRING_REF("5") };
ExecuteResponse response;
TimeoutTaskDecorator<ExecuteTask>(30ms, request, [&](ExecuteResponse res) {
TimeoutTaskDecorator<ExecuteTask>(100ms, request, [&](ExecuteResponse res) {
response = std::move(res);
}).Execute();
@ -159,7 +159,7 @@ TEST_CASE("tasks", "[tasks]") {
request2.arguments = { NAPA_STRING_REF("3"), NAPA_STRING_REF("5") };
ExecuteResponse response2;
TimeoutTaskDecorator<ExecuteTask>(30ms, request2, [&](ExecuteResponse res) {
TimeoutTaskDecorator<ExecuteTask>(100ms, request2, [&](ExecuteResponse res) {
response2 = std::move(res);
}).Execute();

Просмотреть файл

@ -54,7 +54,7 @@ TEST_CASE("worker notifies idle condition", "[scheduler-worker]") {
worker->Schedule(std::make_shared<TestTask>());
std::unique_lock<std::mutex> lock(mutex);
bool idleNotificationReceived = (cv.wait_for(lock, std::chrono::milliseconds(500)) == std::cv_status::no_timeout);
bool idleNotificationReceived = (cv.wait_for(lock, std::chrono::milliseconds(1000)) == std::cv_status::no_timeout);
REQUIRE(idleNotificationReceived == true);
}

Просмотреть файл

@ -51,7 +51,6 @@
<ClCompile Include="main.cpp" />
<ClCompile Include="module\file-system-helpers-tests.cpp" />
<ClCompile Include="module\module-resolver-tests.cpp" />
<ClCompile Include="object-transport\object-transport-tests.cpp" />
<ClCompile Include="scheduler\scheduler-tests.cpp" />
<ClCompile Include="scheduler\timeout-service-tests.cpp" />
<ClCompile Include="settings\parser-tests.cpp" />

Просмотреть файл

@ -1,95 +0,0 @@
#include <catch.hpp>
#include <napa/module/object-transport.h>
using namespace napa;
using namespace napa::module;
class Vehicle {};
class Car : public Vehicle {};
class Sky {};
TEST_CASE("object-transporter serializes and deserializes a stack object correctly.", "[object-transporter]") {
Car car;
auto transporter = ObjectTransporter::Serialize<Car>(&car);
SECTION("object-transporter deserializes an object correctly.") {
auto object = ObjectTransporter::Deserialize<Car>(transporter.first);
REQUIRE(object != nullptr);
REQUIRE(object.get() == &car);
}
SECTION("object-transporter failes on a parent object.") {
auto object = ObjectTransporter::Deserialize<Vehicle>(transporter.first);
REQUIRE(object == nullptr);
}
SECTION("object-transporter failes on different type of object.") {
auto object = ObjectTransporter::Deserialize<Sky>(transporter.first);
REQUIRE(object == nullptr);
}
}
TEST_CASE("object-transporter serializes and deserializes an heap object correctly.", "[object-transporter]") {
auto vehicle = std::make_shared<Vehicle>();
auto transporter = ObjectTransporter::Serialize<Vehicle>(vehicle);
SECTION("object-transporter deserializes an object correctly.") {
auto object = ObjectTransporter::Deserialize<Vehicle>(transporter.first);
REQUIRE(object != nullptr);
REQUIRE(object.get() == vehicle.get());
}
SECTION("object-transporter failes on a child object.") {
auto object = ObjectTransporter::Deserialize<Car>(transporter.first);
REQUIRE(object == nullptr);
}
SECTION("object-transporter failes on different type of object.") {
auto object = ObjectTransporter::Deserialize<Sky>(transporter.first);
REQUIRE(object == nullptr);
}
SECTION("object-transporter deserializes correctly after Vehicle instance is destroyed.") {
auto pointer = vehicle.get();
vehicle.reset();
auto object = ObjectTransporter::Deserialize<Vehicle>(transporter.first);
REQUIRE(object != nullptr);
REQUIRE(object.get() == pointer);
}
}
class Portable : public TransportableObject<Portable> {};
TEST_CASE("object-transporter serializes and deserializes an TransportableObject object correctly.", "[object-transporter]") {
auto portable = std::make_shared<Portable>();
auto transporter = portable->Serialize();
SECTION("object-transporter deserializes an object correctly.") {
auto object = ObjectTransporter::Deserialize<Portable>(transporter.first);
REQUIRE(object != nullptr);
REQUIRE(object.get() == portable.get());
}
SECTION("object-transporter failes on different type of object.") {
auto object = ObjectTransporter::Deserialize<Car>(transporter.first);
REQUIRE(object == nullptr);
}
SECTION("object-transporter deserializes correctly after Car instance is destroyed.") {
auto pointer = portable.get();
portable.reset();
auto object = ObjectTransporter::Deserialize<Portable>(transporter.first);
REQUIRE(object != nullptr);
REQUIRE(object.get() == pointer);
}
}
TEST_CASE("object-transport converts correctly between pointer value and array.", "[object-transporter]") {
auto car = std::make_unique<Car>();
auto source = object_transport::UintptrToUint32Array(reinterpret_cast<uintptr_t>(car.get()));
auto target = object_transport::Uint32ArrayToUintptr(source);
REQUIRE(car.get() == reinterpret_cast<Car*>(target));
}