зеркало из https://github.com/microsoft/napajs.git
Merged PR 324526: Enable module tests as part of npm test
Enable module tests as part of npm test
This commit is contained in:
Родитель
42549269cb
Коммит
0dc3a40d00
|
@ -1,6 +1,5 @@
|
|||
bin
|
||||
build
|
||||
cpp-test
|
||||
tools
|
||||
|
||||
.npmrc
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
!node_modules
|
|
@ -1,3 +0,0 @@
|
|||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
#include "napa-catch-reporter.h"
|
|
@ -1,172 +0,0 @@
|
|||
#include "catch.hpp"
|
||||
|
||||
#include "napa-initialization-guard.h"
|
||||
|
||||
#include <napa-memory.h>
|
||||
#include <napa/memory/allocator-debugger.h>
|
||||
#include <napa/stl/allocator.h>
|
||||
#include <napa/stl/string.h>
|
||||
#include <napa/stl/vector.h>
|
||||
#include <napa/stl/map.h>
|
||||
|
||||
using namespace napa::memory;
|
||||
|
||||
// Make sure Napa is initialized exactly once.
|
||||
static NapaInitializationGuard _guard;
|
||||
|
||||
namespace custom_allocator {
|
||||
char buffer[1024];
|
||||
size_t allocated = 0;
|
||||
size_t countMalloc = 0;
|
||||
size_t countFree = 0;
|
||||
|
||||
void* malloc(size_t size) {
|
||||
void* pointer = buffer + allocated;
|
||||
allocated += size;
|
||||
countMalloc++;
|
||||
return pointer;
|
||||
}
|
||||
|
||||
void free(void* pointer, size_t sizeHint) {
|
||||
countFree++;
|
||||
allocated -= sizeHint;
|
||||
|
||||
// Do nothing but check memory are allocated from buffer.
|
||||
if (pointer < buffer && pointer >= buffer + sizeof(buffer)) {
|
||||
throw std::exception("bad memory in free");
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
allocated = 0;
|
||||
countMalloc = 0;
|
||||
countFree = 0;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Napa memory C api tests", "[memory-capi]") {
|
||||
SECTION("C runtime malloc/free from napa.dll") {
|
||||
void* pointer = NAPA_MALLOC(4);
|
||||
REQUIRE(pointer != nullptr);
|
||||
|
||||
NAPA_FREE(pointer, 4);
|
||||
}
|
||||
|
||||
SECTION("Set default allocator and use it") {
|
||||
NAPA_SET_DEFAULT_ALLOCATOR(custom_allocator::malloc, custom_allocator::free);
|
||||
|
||||
size_t size = 5;
|
||||
void* pointer = NAPA_ALLOCATE(size);
|
||||
REQUIRE(pointer == custom_allocator::buffer);
|
||||
REQUIRE(custom_allocator::allocated == size);
|
||||
REQUIRE(custom_allocator::countMalloc == 1);
|
||||
|
||||
NAPA_DEALLOCATE(pointer, size);
|
||||
REQUIRE(custom_allocator::countFree == 1);
|
||||
REQUIRE(custom_allocator::allocated == 0);
|
||||
|
||||
NAPA_RESET_DEFAULT_ALLOCATOR();
|
||||
custom_allocator::reset();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Napa memory allocator tests", "[memory-allocators]") {
|
||||
SECTION("Test CrtAllocator.") {
|
||||
auto& allocator = NAPA_CRT_ALLOCATOR;
|
||||
REQUIRE(std::string(allocator.GetType()) == "CrtAllocator");
|
||||
|
||||
auto pointer = allocator.Allocate(4);
|
||||
REQUIRE(pointer != nullptr);
|
||||
|
||||
allocator.Deallocate(pointer, 4);
|
||||
}
|
||||
|
||||
SECTION("Test GetDefaultAllocator.") {
|
||||
NAPA_SET_DEFAULT_ALLOCATOR(custom_allocator::malloc, custom_allocator::free);
|
||||
|
||||
auto& allocator = NAPA_DEFAULT_ALLOCATOR;
|
||||
REQUIRE(std::string(allocator.GetType()) == "DefaultAllocator");
|
||||
|
||||
size_t size = 5;
|
||||
auto pointer = allocator.Allocate(size);
|
||||
REQUIRE(pointer == custom_allocator::buffer);
|
||||
REQUIRE(custom_allocator::allocated == size);
|
||||
REQUIRE(custom_allocator::countMalloc == 1);
|
||||
|
||||
allocator.Deallocate(pointer, size);
|
||||
REQUIRE(custom_allocator::countFree == 1);
|
||||
REQUIRE(custom_allocator::allocated == 0);
|
||||
|
||||
NAPA_RESET_DEFAULT_ALLOCATOR();
|
||||
custom_allocator::reset();
|
||||
}
|
||||
|
||||
SECTION("Test CreateSimpleAllocatorDebugger") {
|
||||
NAPA_SET_DEFAULT_ALLOCATOR(custom_allocator::malloc, custom_allocator::free);
|
||||
|
||||
SimpleAllocatorDebugger debugger(std::shared_ptr<Allocator>(&GetDefaultAllocator(), [](Allocator*){}));
|
||||
REQUIRE(std::string(debugger.GetType()) == "SimpleAllocatorDebugger<DefaultAllocator>");
|
||||
|
||||
size_t size = 5;
|
||||
auto pointer = debugger.Allocate(size);
|
||||
REQUIRE(pointer == custom_allocator::buffer);
|
||||
REQUIRE(custom_allocator::allocated == size);
|
||||
REQUIRE(custom_allocator::countMalloc == 1);
|
||||
|
||||
debugger.Deallocate(pointer, size);
|
||||
REQUIRE(custom_allocator::countFree == 1);
|
||||
|
||||
REQUIRE(debugger.GetDebugInfo() == "{ \"allocate\": 1, \"deallocate\": 1, \"allocatedSize\": 5, \"deallocatedSize\": 5 }");
|
||||
NAPA_RESET_DEFAULT_ALLOCATOR();
|
||||
custom_allocator::reset();
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
napa::stl::String _str;
|
||||
napa::stl::Vector<int> _vector;
|
||||
napa::stl::Map<size_t, int> _map;
|
||||
Foo(const char* str, size_t size, int elements[])
|
||||
: _str(str) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
_vector.push_back(elements[i]);
|
||||
_map.insert(std::make_pair(i, elements[i]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("Memory helpers", "[memory-helpers]") {
|
||||
NAPA_SET_DEFAULT_ALLOCATOR(custom_allocator::malloc, custom_allocator::free);
|
||||
|
||||
SECTION("NAPA_MAKE_UNIQUE") {
|
||||
constexpr size_t count = 2;
|
||||
int elems[count] = {1, 2};
|
||||
{
|
||||
auto pointer = NAPA_MAKE_UNIQUE<Foo>("hello world", count, elems);
|
||||
REQUIRE(pointer != nullptr);
|
||||
|
||||
REQUIRE(pointer->_str == "hello world");
|
||||
REQUIRE(pointer->_vector.size() == 2);
|
||||
REQUIRE(pointer->_map.size() == 2);
|
||||
}
|
||||
REQUIRE(custom_allocator::allocated == 0);
|
||||
custom_allocator::reset();
|
||||
}
|
||||
|
||||
SECTION("NAPA_MAKE_SHARED") {
|
||||
constexpr size_t count = 2;
|
||||
int elems[count] = { 1, 2 };
|
||||
{
|
||||
auto pointer = NAPA_MAKE_SHARED<Foo>("hello world", count, elems);
|
||||
REQUIRE(pointer != nullptr);
|
||||
|
||||
REQUIRE(pointer->_str == "hello world");
|
||||
REQUIRE(pointer->_vector.size() == 2);
|
||||
REQUIRE(pointer->_map.size() == 2);
|
||||
}
|
||||
REQUIRE(custom_allocator::allocated == 0);
|
||||
custom_allocator::reset();
|
||||
}
|
||||
|
||||
NAPA_RESET_DEFAULT_ALLOCATOR();
|
||||
}
|
|
@ -1,57 +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 Label="Globals">
|
||||
<ProjectGuid>{4D4E992D-79A5-419D-8161-55D93069C606}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<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>
|
||||
<PropertyGroup>
|
||||
<TestDir>$(OutDir)api-tests</TestDir>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)\memory-tests.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)\zone-tests.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(NapaVanillaRoot)\src\napa.vcxproj" />
|
||||
</ItemGroup>
|
||||
<!-- Test artifacts binplace -->
|
||||
<ItemGroup>
|
||||
<Robocopy Include="$(OutputPath)\$(TargetFileName)">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\api-tests\node_modules\napajs\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="$(NapaVanillaRoot)\package\$(IntermediateOutputPath)\node_modules\napajs">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\api-tests\node_modules\napajs</DestinationFolder>
|
||||
</Robocopy>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Use napa catch adapter -->
|
||||
<Import Project="$(NapaVanillaRoot)\tools\catch-adapter\napa-catch.targets" />
|
||||
|
||||
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
|
@ -1,24 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <napa.h>
|
||||
|
||||
class NapaInitializationGuard {
|
||||
public:
|
||||
NapaInitializationGuard() {
|
||||
static NapaInitialization initialization;
|
||||
}
|
||||
|
||||
private:
|
||||
class NapaInitialization {
|
||||
public:
|
||||
NapaInitialization() {
|
||||
// Only call napa::Initialize once per process.
|
||||
napa::Initialize("--loggingProvider console");
|
||||
}
|
||||
|
||||
~NapaInitialization() {
|
||||
// Only call napa::Shutdown once per process.
|
||||
napa::Shutdown();
|
||||
}
|
||||
};
|
||||
};
|
|
@ -1,190 +0,0 @@
|
|||
#include "catch.hpp"
|
||||
|
||||
#include "napa-initialization-guard.h"
|
||||
|
||||
#include <napa.h>
|
||||
|
||||
#include <future>
|
||||
|
||||
// Make sure Napa is initialized exactly once.
|
||||
static NapaInitializationGuard _guard;
|
||||
|
||||
TEST_CASE("zone apis", "[api]") {
|
||||
|
||||
SECTION("create zone") {
|
||||
napa::Zone zone("zone1");
|
||||
|
||||
REQUIRE(zone.GetId() == "zone1");
|
||||
}
|
||||
|
||||
SECTION("broadcast valid javascript") {
|
||||
napa::Zone zone("zone1");
|
||||
|
||||
auto result = zone.BroadcastSync("var i = 3 + 5;");
|
||||
|
||||
REQUIRE(result == NAPA_RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
SECTION("broadcast illegal javascript") {
|
||||
napa::Zone zone("zone1");
|
||||
|
||||
auto result = zone.BroadcastSync("var i = 3 +");
|
||||
|
||||
REQUIRE(result == NAPA_RESULT_BROADCAST_SCRIPT_ERROR);
|
||||
}
|
||||
|
||||
SECTION("broadcast and execute javascript") {
|
||||
napa::Zone zone("zone1");
|
||||
|
||||
auto resultCode = zone.BroadcastSync("function func(a, b) { return Number(a) + Number(b); }");
|
||||
REQUIRE(resultCode == NAPA_RESULT_SUCCESS);
|
||||
|
||||
napa::FunctionSpec spec;
|
||||
spec.function = NAPA_STRING_REF("func");
|
||||
spec.arguments = { NAPA_STRING_REF("2"), NAPA_STRING_REF("3") };
|
||||
|
||||
auto result = zone.ExecuteSync(spec);
|
||||
REQUIRE(result.code == NAPA_RESULT_SUCCESS);
|
||||
REQUIRE(result.returnValue == "5");
|
||||
}
|
||||
|
||||
SECTION("broadcast and execute javascript async") {
|
||||
napa::Zone zone("zone1");
|
||||
|
||||
std::promise<napa::Result> promise;
|
||||
auto future = promise.get_future();
|
||||
|
||||
zone.Broadcast("function func(a, b) { return Number(a) + Number(b); }", [&promise, &zone](napa::ResultCode) {
|
||||
napa::FunctionSpec spec;
|
||||
spec.function = NAPA_STRING_REF("func");
|
||||
spec.arguments = { NAPA_STRING_REF("2"), NAPA_STRING_REF("3") };
|
||||
|
||||
zone.Execute(spec, [&promise](napa::Result result) {
|
||||
promise.set_value(std::move(result));
|
||||
});
|
||||
});
|
||||
|
||||
auto result = future.get();
|
||||
REQUIRE(result.code == NAPA_RESULT_SUCCESS);
|
||||
REQUIRE(result.returnValue == "5");
|
||||
}
|
||||
|
||||
SECTION("broadcast and execute javascript without timing out") {
|
||||
napa::Zone zone("zone1");
|
||||
|
||||
std::promise<napa::Result> promise;
|
||||
auto future = promise.get_future();
|
||||
|
||||
// Warmup to avoid loading napajs on first call
|
||||
zone.BroadcastSync("require('napajs');");
|
||||
|
||||
zone.Broadcast("function func(a, b) { return Number(a) + Number(b); }", [&promise, &zone](napa::ResultCode) {
|
||||
napa::FunctionSpec spec;
|
||||
spec.function = NAPA_STRING_REF("func");
|
||||
spec.arguments = { NAPA_STRING_REF("2"), NAPA_STRING_REF("3") };
|
||||
spec.options.timeout = 100;
|
||||
|
||||
zone.Execute(spec, [&promise](napa::Result result) {
|
||||
promise.set_value(std::move(result));
|
||||
});
|
||||
});
|
||||
|
||||
auto result = future.get();
|
||||
REQUIRE(result.code == NAPA_RESULT_SUCCESS);
|
||||
REQUIRE(result.returnValue == "5");
|
||||
}
|
||||
|
||||
SECTION("broadcast and execute javascript with exceeded timeout") {
|
||||
napa::Zone zone("zone1");
|
||||
|
||||
std::promise<napa::Result> promise;
|
||||
auto future = promise.get_future();
|
||||
|
||||
// Warmup to avoid loading napajs on first call
|
||||
zone.BroadcastSync("require('napajs');");
|
||||
|
||||
zone.Broadcast("function func() { while(true) {} }", [&promise, &zone](napa::ResultCode) {
|
||||
napa::FunctionSpec spec;
|
||||
spec.function = NAPA_STRING_REF("func");
|
||||
spec.options.timeout = 200;
|
||||
|
||||
zone.Execute(spec, [&promise](napa::Result result) {
|
||||
promise.set_value(std::move(result));
|
||||
});
|
||||
});
|
||||
|
||||
auto result = future.get();
|
||||
REQUIRE(result.code == NAPA_RESULT_TIMEOUT);
|
||||
REQUIRE(result.errorMessage == "Terminated due to timeout");
|
||||
}
|
||||
|
||||
SECTION("execute 2 javascript functions, one succeeds and one times out") {
|
||||
napa::Zone zone("zone1");
|
||||
|
||||
// Warmup to avoid loading napajs on first call
|
||||
zone.BroadcastSync("require('napajs');");
|
||||
|
||||
auto res = zone.BroadcastSync("function f1(a, b) { return Number(a) + Number(b); }");
|
||||
REQUIRE(res == NAPA_RESULT_SUCCESS);
|
||||
res = zone.BroadcastSync("function f2() { while(true) {} }");
|
||||
REQUIRE(res == NAPA_RESULT_SUCCESS);
|
||||
|
||||
std::promise<napa::Result> promise1;
|
||||
auto future1 = promise1.get_future();
|
||||
|
||||
std::promise<napa::Result> promise2;
|
||||
auto future2 = promise2.get_future();
|
||||
|
||||
napa::FunctionSpec request1;
|
||||
request1.function = NAPA_STRING_REF("f1");
|
||||
request1.arguments = { NAPA_STRING_REF("2"), NAPA_STRING_REF("3") };
|
||||
request1.options.timeout = 100;
|
||||
|
||||
napa::FunctionSpec request2;
|
||||
request2.function = NAPA_STRING_REF("f2");
|
||||
request2.options.timeout = 100;
|
||||
|
||||
zone.Execute(request1, [&promise1](napa::Result result) {
|
||||
promise1.set_value(std::move(result));
|
||||
});
|
||||
|
||||
zone.Execute(request2, [&promise2](napa::Result result) {
|
||||
promise2.set_value(std::move(result));
|
||||
});
|
||||
|
||||
auto result = future1.get();
|
||||
REQUIRE(result.code == NAPA_RESULT_SUCCESS);
|
||||
REQUIRE(result.returnValue == "5");
|
||||
|
||||
result = future2.get();
|
||||
REQUIRE(result.code == NAPA_RESULT_TIMEOUT);
|
||||
REQUIRE(result.errorMessage == "Terminated due to timeout");
|
||||
}
|
||||
|
||||
SECTION("broadcast javascript requiring a module") {
|
||||
napa::Zone zone("zone1");
|
||||
|
||||
auto resultCode = zone.BroadcastSync("var path = require('path'); function func() { return path.extname('test.txt'); }");
|
||||
REQUIRE(resultCode == NAPA_RESULT_SUCCESS);
|
||||
|
||||
napa::FunctionSpec spec;
|
||||
spec.function = NAPA_STRING_REF("func");
|
||||
|
||||
auto result = zone.ExecuteSync(spec);
|
||||
REQUIRE(result.code == NAPA_RESULT_SUCCESS);
|
||||
REQUIRE(result.returnValue == "\".txt\"");
|
||||
}
|
||||
|
||||
SECTION("execute function in a module") {
|
||||
napa::Zone zone("zone1");
|
||||
|
||||
napa::FunctionSpec spec;
|
||||
spec.module = NAPA_STRING_REF("path");
|
||||
spec.function = NAPA_STRING_REF("extname");
|
||||
spec.arguments = { NAPA_STRING_REF("\"test.txt\"") };
|
||||
|
||||
auto result = zone.ExecuteSync(spec);
|
||||
REQUIRE(result.code == NAPA_RESULT_SUCCESS);
|
||||
REQUIRE(result.returnValue == "\".txt\"");
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
#include "napa-catch-reporter.h"
|
|
@ -1,122 +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 Label="Globals">
|
||||
<ProjectGuid>{2C45E1F3-34B4-4F39-A4F5-4CEE2512878C}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<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>
|
||||
<PropertyGroup>
|
||||
<TestDir>$(OutDir)component-tests</TestDir>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<DisableSpecificWarnings>4100;4251;4459;4996</DisableSpecificWarnings>
|
||||
<PreprocessorDefinitions>NAPA_EXPORTS;NAPA_BINDING_EXPORTS;BUILDING_NAPA_EXTENSION;BUILDING_V8_SHARED;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\test\component;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Winmm.lib;Dbghelp.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
|
||||
<!-- This is for testing only since V8 can export platform APIs at the latest version. -->
|
||||
<AdditionalDependencies>$(Pkgnapa_nodelib_vc140)\lib\$(BuildType)\$(BuildTarget)\v8_libbase.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>$(Pkgnapa_nodelib_vc140)\lib\$(BuildType)\$(BuildTarget)\v8_libplatform.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- Product code that is tested and needs to compile -->
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\api\api.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\memory\built-in-allocators.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\binary-module-loader.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\core-module-loader.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\javascript-module-loader.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\json-module-loader.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-cache.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-loader.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-loader-helpers.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-resolver.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\module.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\platform\win\platform.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\platform\win\thread-local-storage.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\providers\providers.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\settings\settings-parser.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\store\store.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\v8\v8-common.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\async-complete-task.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\call-context.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\call-task.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\eval-task.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\napa-zone.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\node-zone.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\simple-thread-pool.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\terminable-task.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\timeout-service.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\worker.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\worker-context.cpp" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Core modules -->
|
||||
<Import Project="$(NapaVanillaRoot)\src\module\core-modules\napa\napa-core-modules.proj" />
|
||||
<Import Project="$(NapaVanillaRoot)\src\module\core-modules\node\node-core-modules.proj" />
|
||||
|
||||
<!-- Test code -->
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)\node-zone-tests.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)\tasks-tests.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)\worker-tests.cpp" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Test artifacts binplace -->
|
||||
<ItemGroup>
|
||||
<Robocopy Include="$(OutputPath)\$(TargetFileName)">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\component-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="$(NapaVanillaRoot)\lib\$(IntermediateOutputPath)">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\component-tests\lib</DestinationFolder>
|
||||
<FileMatch>*.j*</FileMatch>
|
||||
<IsRecursive>true</IsRecursive>
|
||||
</Robocopy>
|
||||
<Robocopy Include="$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.dll">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\component-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Use napa catch adapter -->
|
||||
<Import Project="$(NapaVanillaRoot)\tools\catch-adapter\napa-catch.targets" />
|
||||
|
||||
<!-- Package dependencies -->
|
||||
<Import Project="$(Pkgboost)\build\native\boost.targets" />
|
||||
<Import Project="$(Pkgboost_chrono_vc140)\build\native\boost_chrono-vc140.targets" />
|
||||
<Import Project="$(Pkgboost_date_time_vc140)\build\native\boost_date_time-vc140.targets" />
|
||||
<Import Project="$(Pkgboost_filesystem_vc140)\build\native\boost_filesystem-vc140.targets" />
|
||||
<Import Project="$(Pkgboost_program_options_vc140)\build\native\boost_program_options-vc140.targets" />
|
||||
<Import Project="$(Pkgboost_regex_vc140)\build\native\boost_regex-vc140.targets" />
|
||||
<Import Project="$(Pkgboost_system_vc140)\build\native\boost_system-vc140.targets" />
|
||||
<Import Project="$(Pkgboost_thread_vc140)\build\native\boost_thread-vc140.targets" />
|
||||
<Import Project="$(Pkgnapa_nodelib_vc140)\exports_v8_includes.props" />
|
||||
|
||||
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
|
@ -1,28 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "providers/providers.h"
|
||||
#include "settings/settings.h"
|
||||
#include "v8/v8-common.h"
|
||||
|
||||
class NapaInitializationGuard {
|
||||
public:
|
||||
NapaInitializationGuard() {
|
||||
static NapaInitialization initialization;
|
||||
}
|
||||
|
||||
private:
|
||||
class NapaInitialization {
|
||||
public:
|
||||
NapaInitialization() {
|
||||
napa::settings::PlatformSettings settings;
|
||||
settings.loggingProvider = "console";
|
||||
napa::providers::Initialize(settings);
|
||||
|
||||
napa::v8_common::Initialize();
|
||||
}
|
||||
|
||||
~NapaInitialization() {
|
||||
napa::v8_common::Shutdown();
|
||||
}
|
||||
};
|
||||
};
|
|
@ -1,53 +0,0 @@
|
|||
#include "catch.hpp"
|
||||
|
||||
#include "zone/node-zone.h"
|
||||
|
||||
#include <future>
|
||||
|
||||
using namespace napa;
|
||||
using namespace napa::zone;
|
||||
|
||||
TEST_CASE("node zone not available before init", "[node-zone]") {
|
||||
auto zone = NodeZone::Get();
|
||||
REQUIRE(zone == nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE("node zone delegate should work after init", "[node-zone]") {
|
||||
auto broadcast = [](const std::string& source, BroadcastCallback callback){
|
||||
callback(NAPA_RESULT_SUCCESS);
|
||||
};
|
||||
|
||||
auto execute = [](const FunctionSpec& spec, ExecuteCallback callback) {
|
||||
callback({ NAPA_RESULT_SUCCESS, "", std::string("hello world"), nullptr });
|
||||
};
|
||||
|
||||
NodeZone::Init(broadcast, execute);
|
||||
|
||||
auto zone = NodeZone::Get();
|
||||
REQUIRE(zone != nullptr);
|
||||
|
||||
{
|
||||
std::promise<ResultCode> promise;
|
||||
auto future = promise.get_future();
|
||||
|
||||
zone->Broadcast("", [&promise](ResultCode resultCode) {
|
||||
promise.set_value(NAPA_RESULT_SUCCESS);
|
||||
});
|
||||
|
||||
REQUIRE(future.get() == NAPA_RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
std::promise<Result> promise;
|
||||
auto future = promise.get_future();
|
||||
|
||||
FunctionSpec spec;
|
||||
zone->Execute(spec, [&promise](Result result) {
|
||||
promise.set_value(std::move(result));
|
||||
});
|
||||
|
||||
auto result = future.get();
|
||||
REQUIRE(result.code == NAPA_RESULT_SUCCESS);
|
||||
REQUIRE(result.returnValue == "hello world");
|
||||
}
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
#include "catch.hpp"
|
||||
|
||||
#include "module/loader/module-loader.h"
|
||||
#include "providers/providers.h"
|
||||
#include "zone/eval-task.h"
|
||||
#include "zone/call-task.h"
|
||||
#include "zone/task-decorators.h"
|
||||
#include "zone/worker-context.h"
|
||||
#include "settings/settings.h"
|
||||
#include "v8/array-buffer-allocator.h"
|
||||
#include "napa-initialization-guard.h"
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace napa;
|
||||
using namespace napa::zone;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
// Make sure V8 it initialized exactly once.
|
||||
static NapaInitializationGuard _guard;
|
||||
|
||||
TEST_CASE("tasks", "[tasks]") {
|
||||
// Create a new Isolate and make it the current one.
|
||||
napa::v8_extensions::ArrayBufferAllocator allocator;
|
||||
v8::Isolate::CreateParams createParams;
|
||||
createParams.array_buffer_allocator = &allocator;
|
||||
auto isolate = v8::Isolate::New(createParams);
|
||||
|
||||
// Required scope/isolate guards
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||
context->SetSecurityToken(v8::Undefined(isolate));
|
||||
v8::Context::Scope contextScope(context);
|
||||
|
||||
INIT_WORKER_CONTEXT();
|
||||
CREATE_MODULE_LOADER();
|
||||
|
||||
EvalTask("require('../lib/index');").Execute();
|
||||
|
||||
SECTION("load valid javascript") {
|
||||
ResultCode loadResponseCode;
|
||||
EvalTask("var i = 3 + 5;", "", [&loadResponseCode](ResultCode code) {
|
||||
loadResponseCode = code;
|
||||
}).Execute();
|
||||
|
||||
REQUIRE(loadResponseCode == NAPA_RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
SECTION("load fails when javascript is malformed") {
|
||||
ResultCode loadResponseCode;
|
||||
EvalTask("var j = 3 +", "", [&loadResponseCode](ResultCode code) {
|
||||
loadResponseCode = code;
|
||||
}).Execute();
|
||||
|
||||
REQUIRE(loadResponseCode == NAPA_RESULT_BROADCAST_SCRIPT_ERROR);
|
||||
}
|
||||
|
||||
SECTION("load fails when javascript exception is thrown") {
|
||||
ResultCode loadResponseCode;
|
||||
EvalTask("throw Error('error');", "", [&loadResponseCode](ResultCode code) {
|
||||
loadResponseCode = code;
|
||||
}).Execute();
|
||||
|
||||
REQUIRE(loadResponseCode == NAPA_RESULT_BROADCAST_SCRIPT_ERROR);
|
||||
}
|
||||
|
||||
SECTION("execute succeeds with a valid and existing function") {
|
||||
EvalTask("function foo(a, b) { return a + b; }").Execute();
|
||||
|
||||
FunctionSpec spec;
|
||||
spec.function = NAPA_STRING_REF("foo");
|
||||
spec.arguments = { NAPA_STRING_REF("3"), NAPA_STRING_REF("5") };
|
||||
|
||||
Result result;
|
||||
CallTask(std::make_shared<CallContext>(spec, [&](Result res) {
|
||||
result = std::move(res);
|
||||
})).Execute();
|
||||
|
||||
REQUIRE(result.code == NAPA_RESULT_SUCCESS);
|
||||
REQUIRE(result.returnValue == "8");
|
||||
}
|
||||
|
||||
SECTION("execute fails for non-existing function") {
|
||||
FunctionSpec spec;
|
||||
spec.function = NAPA_STRING_REF("bar");
|
||||
spec.arguments = { NAPA_STRING_REF("3"), NAPA_STRING_REF("5") };
|
||||
|
||||
Result result;
|
||||
CallTask(std::make_shared<CallContext>(spec, [&](Result res) {
|
||||
result = std::move(res);
|
||||
})).Execute();
|
||||
|
||||
REQUIRE(result.code == NAPA_RESULT_EXECUTE_FUNC_ERROR);
|
||||
}
|
||||
|
||||
SECTION("execute fails when function throws exception") {
|
||||
EvalTask("function f1(a, b) { throw 'an error' }").Execute();
|
||||
|
||||
FunctionSpec spec;
|
||||
spec.function = NAPA_STRING_REF("f1");
|
||||
spec.arguments = { NAPA_STRING_REF("3"), NAPA_STRING_REF("5") };
|
||||
|
||||
Result result;
|
||||
CallTask(std::make_shared<CallContext>(spec, [&](Result res) {
|
||||
result = std::move(res);
|
||||
})).Execute();
|
||||
|
||||
REQUIRE(result.code == NAPA_RESULT_EXECUTE_FUNC_ERROR);
|
||||
REQUIRE(result.errorMessage == "an error");
|
||||
}
|
||||
|
||||
SECTION("execute succeeds when timeout was not exceeded") {
|
||||
EvalTask("function f2(a, b) { return a + b; }").Execute();
|
||||
|
||||
FunctionSpec spec;
|
||||
spec.function = NAPA_STRING_REF("f2");
|
||||
spec.arguments = { NAPA_STRING_REF("3"), NAPA_STRING_REF("5") };
|
||||
|
||||
Result result;
|
||||
TimeoutTaskDecorator<CallTask>(500ms, std::make_shared<CallContext>(spec, [&](Result res) {
|
||||
result = std::move(res);
|
||||
})).Execute();
|
||||
|
||||
REQUIRE(result.code == NAPA_RESULT_SUCCESS);
|
||||
REQUIRE(result.returnValue == "8");
|
||||
}
|
||||
|
||||
SECTION("execute fails when timeout exceeded") {
|
||||
EvalTask("function f3() { while(true) {} }").Execute();
|
||||
|
||||
FunctionSpec spec;
|
||||
spec.function = NAPA_STRING_REF("f3");
|
||||
|
||||
Result result;
|
||||
TimeoutTaskDecorator<CallTask>(500ms, std::make_shared<CallContext>(spec, [&](Result res) {
|
||||
result = std::move(res);
|
||||
})).Execute();
|
||||
|
||||
REQUIRE(result.code == NAPA_RESULT_TIMEOUT);
|
||||
REQUIRE(result.errorMessage == "Terminated due to timeout");
|
||||
}
|
||||
|
||||
SECTION("execute succeeds after a failed task") {
|
||||
EvalTask("function f4() { while(true) {} }").Execute();
|
||||
EvalTask("function f5(a, b) { return Number(a) + Number(b); }").Execute();
|
||||
|
||||
FunctionSpec request1;
|
||||
request1.function = NAPA_STRING_REF("f4");
|
||||
|
||||
Result response1;
|
||||
TimeoutTaskDecorator<CallTask>(500ms, std::make_shared<CallContext>(request1, [&](Result res) {
|
||||
response1 = std::move(res);
|
||||
})).Execute();
|
||||
|
||||
REQUIRE(response1.code == NAPA_RESULT_TIMEOUT);
|
||||
REQUIRE(response1.errorMessage == "Terminated due to timeout");
|
||||
|
||||
FunctionSpec request2;
|
||||
request2.function = NAPA_STRING_REF("f5");
|
||||
request2.arguments = { NAPA_STRING_REF("3"), NAPA_STRING_REF("5") };
|
||||
|
||||
Result response2;
|
||||
TimeoutTaskDecorator<CallTask>(500ms, std::make_shared<CallContext>(request2, [&](Result res) {
|
||||
response2 = std::move(res);
|
||||
})).Execute();
|
||||
|
||||
REQUIRE(response2.code == NAPA_RESULT_SUCCESS);
|
||||
REQUIRE(response2.returnValue == "8");
|
||||
}
|
||||
}
|
|
@ -1,146 +0,0 @@
|
|||
#include "catch.hpp"
|
||||
|
||||
#include "zone/worker.h"
|
||||
#include "napa-initialization-guard.h"
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
using namespace napa;
|
||||
using namespace napa::settings;
|
||||
using namespace napa::zone;
|
||||
|
||||
|
||||
|
||||
class TestTask : public Task {
|
||||
public:
|
||||
TestTask(std::function<std::string(void)> func = []() { return ""; })
|
||||
: numberOfExecutions(0), _func(std::move(func)) {}
|
||||
|
||||
virtual void Execute() override {
|
||||
result = _func();
|
||||
numberOfExecutions++;
|
||||
}
|
||||
|
||||
std::atomic<uint32_t> numberOfExecutions;
|
||||
std::string result;
|
||||
private:
|
||||
std::function<std::string(void)> _func;
|
||||
};
|
||||
|
||||
// Make sure V8 it initialized exactly once.
|
||||
static NapaInitializationGuard _guard;
|
||||
|
||||
TEST_CASE("worker runs setup complete callback", "[scheduler-worker]") {
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
|
||||
auto worker = std::make_unique<Worker>(0, ZoneSettings(), [&cv](WorkerId) {
|
||||
cv.notify_one();
|
||||
}, [](WorkerId) {});
|
||||
|
||||
bool setupCompleted = (cv.wait_for(lock, std::chrono::milliseconds(1000)) == std::cv_status::no_timeout);
|
||||
REQUIRE(setupCompleted == true);
|
||||
}
|
||||
|
||||
TEST_CASE("worker runs scheduled task", "[scheduler-worker]") {
|
||||
auto worker = std::make_unique<Worker>(0, ZoneSettings(), [](WorkerId) {}, [](WorkerId) {});
|
||||
|
||||
auto task = std::make_shared<TestTask>();
|
||||
worker->Schedule(task);
|
||||
|
||||
worker = nullptr; // Wait for worker to complete all tasks.
|
||||
|
||||
REQUIRE(task->numberOfExecutions == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("worker notifies idle condition", "[scheduler-worker]") {
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
|
||||
auto worker = std::make_unique<Worker>(0, ZoneSettings(), [](WorkerId) {}, [&cv](WorkerId) {
|
||||
cv.notify_one();
|
||||
});
|
||||
|
||||
worker->Schedule(std::make_shared<TestTask>());
|
||||
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
bool idleNotificationReceived = (cv.wait_for(lock, std::chrono::milliseconds(1000)) == std::cv_status::no_timeout);
|
||||
|
||||
REQUIRE(idleNotificationReceived == true);
|
||||
}
|
||||
|
||||
TEST_CASE("worker runs all tasks before shutting down", "[scheduler-worker]") {
|
||||
auto worker = std::make_unique<Worker>(0, ZoneSettings(), [](WorkerId) {}, [](WorkerId) {});
|
||||
|
||||
auto task = std::make_shared<TestTask>();
|
||||
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
worker->Schedule(task);
|
||||
}
|
||||
|
||||
worker = nullptr; // Wait for worker to complete all tasks.
|
||||
|
||||
REQUIRE(task->numberOfExecutions == 100);
|
||||
}
|
||||
|
||||
TEST_CASE("worker runs javascript task", "[scheduler-worker]") {
|
||||
auto worker = std::make_unique<Worker>(0, ZoneSettings(), [](WorkerId) {}, [](WorkerId) {});
|
||||
|
||||
auto task = std::make_shared<TestTask>([]() {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
auto context = isolate->GetCurrentContext();
|
||||
|
||||
v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, "'Hello' + ', World!'",
|
||||
v8::NewStringType::kNormal).ToLocalChecked();
|
||||
|
||||
auto script = v8::Script::Compile(context, source).ToLocalChecked();
|
||||
|
||||
auto result = script->Run(context).ToLocalChecked();
|
||||
|
||||
v8::String::Utf8Value utf8(result);
|
||||
|
||||
return std::string(*utf8);
|
||||
});
|
||||
|
||||
worker->Schedule(task);
|
||||
|
||||
worker = nullptr; // Wait for worker to complete all tasks.
|
||||
|
||||
REQUIRE(task->result == "Hello, World!");
|
||||
}
|
||||
|
||||
TEST_CASE("worker runs javascript with stack overflow", "[scheduler-worker]") {
|
||||
auto worker = std::make_unique<Worker>(0, ZoneSettings(), [](WorkerId) {}, [](WorkerId) {});
|
||||
|
||||
auto task = std::make_shared<TestTask>([]() {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
auto context = isolate->GetCurrentContext();
|
||||
|
||||
v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, "function test() { test(); }; test();",
|
||||
v8::NewStringType::kNormal).ToLocalChecked();
|
||||
|
||||
auto script = v8::Script::Compile(context, source).ToLocalChecked();
|
||||
|
||||
v8::TryCatch tryCatch(isolate);
|
||||
script->Run(context);
|
||||
|
||||
if (tryCatch.HasCaught()) {
|
||||
auto exception = tryCatch.Exception();
|
||||
v8::String::Utf8Value errorMessage(exception);
|
||||
|
||||
return std::string(*errorMessage);
|
||||
}
|
||||
|
||||
return std::string();
|
||||
});
|
||||
|
||||
worker->Schedule(task);
|
||||
|
||||
worker = nullptr; // Wait for worker to complete all tasks.
|
||||
|
||||
REQUIRE(task->result == "RangeError: Maximum call stack size exceeded");
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
#include <napa-module.h>
|
||||
#include <napa-async.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
|
||||
using namespace napa;
|
||||
using namespace napa::module;
|
||||
|
||||
using namespace v8;
|
||||
|
||||
namespace {
|
||||
std::atomic<uint32_t> _now(0);
|
||||
}
|
||||
|
||||
/// <summary> It increases a number by a given parameter asynchronously and run a callback at the next execution loop. </summary>
|
||||
void Increase(const FunctionCallbackInfo<Value>& args) {
|
||||
auto isolate = args.GetIsolate();
|
||||
|
||||
CHECK_ARG(isolate,
|
||||
args.Length() == 2 && args[0]->IsUint32() && args[1]->IsFunction(),
|
||||
"It requires unsigned integer and callback as arguments");
|
||||
|
||||
auto value = args[0]->Uint32Value();
|
||||
|
||||
napa::zone::PostAsyncWork(Local<Function>::Cast(args[1]),
|
||||
[value]() {
|
||||
// This runs at the separate thread.
|
||||
_now += value;
|
||||
return reinterpret_cast<void*>(static_cast<uintptr_t>(_now.load()));
|
||||
},
|
||||
[](auto jsCallback, void* result) {
|
||||
// This runs at the same thread as one Increase() is called.
|
||||
auto isolate = Isolate::GetCurrent();
|
||||
|
||||
int32_t argc = 1;
|
||||
Local<Value> argv[] =
|
||||
{ Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(result))) };
|
||||
|
||||
jsCallback->Call(isolate->GetCurrentContext()->Global(), argc, argv);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary> It increases a number by a given parameter synchronously and run a callback at the next execution loop. </summary>
|
||||
void IncreaseSync(const FunctionCallbackInfo<Value>& args) {
|
||||
auto isolate = args.GetIsolate();
|
||||
|
||||
CHECK_ARG(isolate,
|
||||
args.Length() == 2 && args[0]->IsUint32() && args[1]->IsFunction(),
|
||||
"It requires unsigned integer and callback as arguments");
|
||||
|
||||
auto value = args[0]->Uint32Value();
|
||||
|
||||
napa::zone::DoAsyncWork(Local<Function>::Cast(args[1]),
|
||||
[value](auto complete) {
|
||||
// This runs at the same thread.
|
||||
_now += value;
|
||||
complete(reinterpret_cast<void*>(static_cast<uintptr_t>(_now.load())));
|
||||
},
|
||||
[](auto jsCallback, void* result) {
|
||||
// This runs at the same thread as one IncreaseSync() is called.
|
||||
auto isolate = Isolate::GetCurrent();
|
||||
|
||||
int32_t argc = 1;
|
||||
Local<Value> argv[] =
|
||||
{ Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(result))) };
|
||||
|
||||
jsCallback->Call(isolate->GetCurrentContext()->Global(), argc, argv);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary> It returns the current value of a number. </summary>
|
||||
void Now(const FunctionCallbackInfo<Value>& args) {
|
||||
auto isolate = args.GetIsolate();
|
||||
HandleScope scope(isolate);
|
||||
|
||||
args.GetReturnValue().Set(Integer::NewFromUnsigned(isolate, _now));
|
||||
}
|
||||
|
||||
void Init(Local<Object> exports) {
|
||||
NAPA_SET_METHOD(exports, "increase", Increase);
|
||||
NAPA_SET_METHOD(exports, "increaseSync", IncreaseSync);
|
||||
NAPA_SET_METHOD(exports, "now", Now);
|
||||
}
|
||||
|
||||
NAPA_MODULE(addon, Init)
|
|
@ -1,43 +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>
|
||||
<AddonName>async</AddonName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<AddonName>async</AddonName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>BUILDING_NAPA_EXTENSION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)\async.cpp" />
|
||||
</ItemGroup>
|
||||
<Target Name="ChangeExtention" AfterTargets="Build">
|
||||
<Move SourceFiles="$(OutputPath)\$(TargetFileName)" DestinationFiles="$(OutputPath)\$(AddonName).napa" />
|
||||
</Target>
|
||||
<Import Project="$(Pkgnapa_nodelib_vc140)\exports_v8_includes.props" />
|
||||
<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="sample\sample.vcxproj" />
|
||||
<ProjectFile Include="module-loader\napa-module-loader-tests.vcxproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(ExtendedTargetsPath)\Traversal.targets" />
|
||||
</Project>
|
|
@ -1,58 +0,0 @@
|
|||
var assert = require('assert');
|
||||
|
||||
assert(1 == 1);
|
||||
|
||||
const obj1 = { a : { b : 1 } };
|
||||
const obj2 = { a : { b : 2 } };
|
||||
const obj3 = { a : { b : 1 } };
|
||||
const obj4 = Object.create(obj1);
|
||||
|
||||
assert.deepEqual(obj1, obj1);
|
||||
|
||||
assert.notDeepEqual(obj1, obj2);
|
||||
|
||||
assert.deepEqual(obj1, obj3);
|
||||
|
||||
assert.notDeepEqual(obj1, obj4);
|
||||
|
||||
assert.deepEqual({a:1}, {a:'1'});
|
||||
|
||||
assert.notStrictEqual({a:1}, {a:'1'});
|
||||
|
||||
assert.equal(1, 1);
|
||||
|
||||
assert.equal(1, '1');
|
||||
|
||||
assert.deepEqual(1, '1');
|
||||
|
||||
assert.deepEqual(1, 1);
|
||||
|
||||
assert.notStrictEqual(1, '1');
|
||||
|
||||
assert.notEqual(1, 2);
|
||||
|
||||
assert.notEqual({a: {b: 1}}, {a: {b: 1}});
|
||||
|
||||
assert.ifError(0);
|
||||
|
||||
assert.throws(() => { assert.ifError(1);});
|
||||
|
||||
assert.throws(() => { assert.ifError('error');});
|
||||
|
||||
assert.throws(() => { assert.ifError(new Error());});
|
||||
|
||||
assert.throws(() => { assert.fail(1, 2, undefined, '>'); });
|
||||
|
||||
assert.ok(true);
|
||||
|
||||
assert.ok(1);
|
||||
|
||||
assert.throws(() => { assert.ok(false); });
|
||||
|
||||
assert.throws(() => { assert.ok(0); });
|
||||
|
||||
assert.throws(() => {
|
||||
assert.doesNotThrow(() => { throw new TypeError('Wrong value'); }, TypeError);
|
||||
});
|
||||
|
||||
true;
|
|
@ -1,22 +0,0 @@
|
|||
var assert = require('assert');
|
||||
var async = require('./async');
|
||||
|
||||
var now = async.now();
|
||||
assert.equal(now, 0);
|
||||
|
||||
var promise = new Promise((resolve) => {
|
||||
async.increase(3, (value) => {
|
||||
resolve(value);
|
||||
});
|
||||
});
|
||||
|
||||
promise.then((value) => {
|
||||
assert.equal(value, 3);
|
||||
|
||||
now = async.now();
|
||||
assert.equal(now, 6);
|
||||
});
|
||||
|
||||
async.increaseSync(3, (value) => {});
|
||||
|
||||
true;
|
|
@ -1,13 +0,0 @@
|
|||
now = async.now();
|
||||
assert.equal(now, 6);
|
||||
|
||||
async.increaseSync(3, (value) => {
|
||||
assert.equal(value, 9);
|
||||
|
||||
now = async.now();
|
||||
assert.equal(now, 12);
|
||||
});
|
||||
|
||||
async.increaseSync(3, (value) => {});
|
||||
|
||||
true;
|
|
@ -1,10 +0,0 @@
|
|||
var assert = require('assert');
|
||||
|
||||
assert.equal(typeof tfs, 'undefined');
|
||||
var tfs = require('tfs');
|
||||
assert.equal(tfs.runTest(), 'tfs.runTest');
|
||||
|
||||
assert.notEqual(typeof tconsole, 'undefined');
|
||||
assert.equal(tconsole.runTest(), 'tconsole.runTest');
|
||||
|
||||
true;
|
|
@ -1,30 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "assert",
|
||||
"type": "core"
|
||||
},
|
||||
{
|
||||
"name": "events",
|
||||
"type": "core"
|
||||
},
|
||||
{
|
||||
"name": "process",
|
||||
"type": "builtin"
|
||||
},
|
||||
{
|
||||
"name": "tconsole",
|
||||
"type": "builtin"
|
||||
},
|
||||
{
|
||||
"name": "tfs",
|
||||
"type": "core"
|
||||
},
|
||||
{
|
||||
"name": "tty",
|
||||
"type": "core"
|
||||
},
|
||||
{
|
||||
"name": "util",
|
||||
"type": "core"
|
||||
}
|
||||
]
|
|
@ -1,7 +0,0 @@
|
|||
var cycle_a = require('./cycle-a.js');
|
||||
var cycle_b = require('./cycle-b.js');
|
||||
if (cycle_a.done && cycle_b.done) {
|
||||
true;
|
||||
} else {
|
||||
false;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
|
||||
assert.ifError(fs.existsSync('file-not-exist.json'));
|
||||
|
||||
assert.ok(fs.existsSync('fstest.json'));
|
||||
|
||||
var content = JSON.parse(fs.readFileSync('fstest.json'));
|
||||
assert.equal(content.query, 'query');
|
||||
assert.equal(content.document, 'document');
|
||||
|
||||
fs.mkdirSync('fstest-dir');
|
||||
fs.mkdirSync('fstest-dir/1');
|
||||
fs.mkdirSync('fstest-dir/2');
|
||||
fs.writeFileSync('fstest-dir/3.dat', '3.dat');
|
||||
var names = fs.readdirSync('fstest-dir');
|
||||
assert.deepEqual(names, ['1', '2', '3.dat']);
|
||||
|
||||
require('./tests/sub/fstestsub');
|
|
@ -1 +0,0 @@
|
|||
{ "query" : "query", "document" : "document" }
|
|
@ -1,4 +0,0 @@
|
|||
exports.run = function() {
|
||||
global.toGlobal = 'toGlobal';
|
||||
return global.fromGlobal;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
var assert = require('assert');
|
||||
|
||||
assert.equal(global.Math.floor(1.1), 1);
|
||||
|
||||
var test = require('./globaltest-module');
|
||||
global.fromGlobal = 'fromGlobal';
|
||||
assert.equal(test.run(), 'fromGlobal');
|
||||
assert.equal(global.toGlobal, 'toGlobal');
|
||||
|
||||
true;
|
|
@ -1,6 +0,0 @@
|
|||
var exports = module.exports = {};
|
||||
|
||||
exports.print = function(data) {
|
||||
var proxy = require('./test/toproxy');
|
||||
return proxy.run(data);
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
var obj = require('./fstest.json');
|
||||
if (obj.query == 'query' && obj.document == 'document')
|
||||
true;
|
||||
else
|
||||
false;
|
|
@ -1,9 +0,0 @@
|
|||
var tconsole = exports;
|
||||
|
||||
for (var prop in console) {
|
||||
tconsole[prop] = console[prop];
|
||||
}
|
||||
|
||||
tconsole.runTest = function() {
|
||||
return 'tconsole.runTest';
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
var binding = process.binding('fs');
|
||||
var tfs = exports;
|
||||
|
||||
for (var prop in binding) {
|
||||
tfs[prop] = binding[prop];
|
||||
}
|
||||
|
||||
tfs.runTest = function() {
|
||||
return 'tfs.runTest';
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
#include "napa-catch-reporter.h"
|
|
@ -1,393 +0,0 @@
|
|||
#include <catch.hpp>
|
||||
|
||||
#include <module/loader/module-loader.h>
|
||||
#include <napa/module/module-internal.h>
|
||||
#include <napa/v8-helpers.h>
|
||||
#include <platform/dll.h>
|
||||
#include <platform/filesystem.h>
|
||||
#include <platform/platform.h>
|
||||
#include <utils/string.h>
|
||||
#include <zone/scheduler.h>
|
||||
#include <zone/napa-zone.h>
|
||||
#include <v8/array-buffer-allocator.h>
|
||||
#include <v8/v8-common.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <iostream>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
using namespace napa;
|
||||
using namespace napa::module;
|
||||
using namespace napa::settings;
|
||||
using namespace napa::zone;
|
||||
|
||||
|
||||
class V8InitializationGuard {
|
||||
public:
|
||||
V8InitializationGuard() {
|
||||
static V8Initialization initialization;
|
||||
}
|
||||
|
||||
private:
|
||||
class V8Initialization {
|
||||
public:
|
||||
V8Initialization() {
|
||||
v8_common::Initialize();
|
||||
}
|
||||
|
||||
~V8Initialization() {
|
||||
v8_common::Shutdown();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Make sure V8 it initialized exactly once.
|
||||
static V8InitializationGuard _guard;
|
||||
|
||||
bool RunScript(const std::string& input, std::function<bool(v8::Local<v8::Value>)> verifier) {
|
||||
v8_extensions::ArrayBufferAllocator allocator;
|
||||
v8::Isolate::CreateParams params;
|
||||
params.array_buffer_allocator = &allocator;
|
||||
|
||||
auto isolate = v8::Isolate::New(params);
|
||||
|
||||
std::unique_ptr<v8::Isolate, std::function<void(v8::Isolate*)>> deferred(isolate, [](auto isolate) {
|
||||
isolate->Dispose();
|
||||
});
|
||||
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
|
||||
auto context = v8::Context::New(isolate);
|
||||
context->SetSecurityToken(v8::Undefined(isolate));
|
||||
v8::Context::Scope contextScope(context);
|
||||
|
||||
INIT_WORKER_CONTEXT();
|
||||
CREATE_MODULE_LOADER();
|
||||
|
||||
auto source = v8_helpers::MakeV8String(isolate, input);
|
||||
|
||||
v8::TryCatch tryCatch;
|
||||
auto script = v8::Script::Compile(source);
|
||||
if (tryCatch.HasCaught()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto run = script->Run();
|
||||
if (tryCatch.HasCaught()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return verifier(run);
|
||||
}
|
||||
|
||||
bool RunScriptFile(const std::string& filename, std::function<bool(v8::Local<v8::Value>)> verifier) {
|
||||
std::ifstream file(filename);
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
|
||||
return RunScript(buffer.str(), verifier);
|
||||
}
|
||||
|
||||
bool LoadJavascript(int index) {
|
||||
std::string input;
|
||||
input.append("jsmodule").append(std::to_string(index));
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "var js = require('./jsmodule');"
|
||||
<< "js.print('" << input << "');"
|
||||
<< "js = require('./jsmodule.js');"
|
||||
<< "js.print('" << input << "');"
|
||||
<< "js = require('./test/../jsmodule.js');"
|
||||
<< "js.print('" << input << "');";
|
||||
|
||||
return RunScript(oss.str(), [&input](v8::Local<v8::Value> run) {
|
||||
std::transform(input.begin(), input.end(), input.begin(), toupper);
|
||||
|
||||
v8::String::Utf8Value value(run);
|
||||
return input.compare(*value) == 0;
|
||||
});
|
||||
}
|
||||
|
||||
bool LoadNapaModule(int index) {
|
||||
std::string input;
|
||||
input.append("sample").append(std::to_string(index));
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "var sample = require('./sample.napa');"
|
||||
<< "sample.print('" << input << "');"
|
||||
<< "sample = require('./test/../sample.napa');"
|
||||
<< "sample.print('" << input << "');";
|
||||
|
||||
return RunScript(oss.str(), [&input](v8::Local<v8::Value> run) {
|
||||
v8::String::Utf8Value value(run);
|
||||
return input.compare(*value) == 0;
|
||||
});
|
||||
}
|
||||
|
||||
bool LoadObjectWrapModule(int index) {
|
||||
std::ifstream file("sample-test.js");
|
||||
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
|
||||
return RunScript(buffer.str(), [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
}
|
||||
|
||||
void RunAtThreads(std::function<bool(int)> tester) {
|
||||
std::vector<std::future<bool>> futures;
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
futures.push_back(std::async(std::launch::async, tester, i));
|
||||
}
|
||||
|
||||
for (auto& result : futures) {
|
||||
REQUIRE(result.get() == true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("load javascript", "[module-loader]") {
|
||||
RunAtThreads(LoadJavascript);
|
||||
}
|
||||
|
||||
TEST_CASE("load json module", "[module-loader]") {
|
||||
auto result = RunScriptFile("jsontest.js", [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("load napa module", "[module-loader]") {
|
||||
RunAtThreads(LoadNapaModule);
|
||||
}
|
||||
|
||||
TEST_CASE("load object wrap module", "[module-loader]") {
|
||||
RunAtThreads(LoadObjectWrapModule);
|
||||
}
|
||||
|
||||
TEST_CASE("require.resolve", "[module-loader]") {
|
||||
std::ostringstream oss;
|
||||
oss << "require.resolve('./jsmodule.js');";
|
||||
|
||||
auto result = RunScript(oss.str(), [](v8::Local<v8::Value> run) {
|
||||
v8::String::Utf8Value value(run);
|
||||
auto filePath = filesystem::CurrentDirectory() / "jsmodule.js";
|
||||
return filePath.String().compare(*value) == 0;
|
||||
});
|
||||
REQUIRE(result);
|
||||
|
||||
oss.str("");
|
||||
oss << "require.resolve('./jsmodule.napa');";
|
||||
|
||||
result = RunScript(oss.str(), [](v8::Local<v8::Value> run) {
|
||||
v8::String::Utf8Value value(run);
|
||||
return value.length() == 0;
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("core modules", "[module-loader]") {
|
||||
auto result = RunScriptFile("core-module-tests.js", [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("process", "[module-loader]") {
|
||||
std::ostringstream oss;
|
||||
oss << "process.argv.length;";
|
||||
|
||||
auto result = RunScript(oss.str(), [](v8::Local<v8::Value> run) {
|
||||
auto argc = run->Int32Value();
|
||||
return argc > 0;
|
||||
});
|
||||
REQUIRE(result);
|
||||
|
||||
oss.str("");
|
||||
oss << "process.argv[0];";
|
||||
|
||||
result = RunScript(oss.str(), [](v8::Local<v8::Value> run) {
|
||||
v8::String::Utf8Value value(run);
|
||||
return filesystem::Exists(filesystem::Path(*value));
|
||||
});
|
||||
REQUIRE(result);
|
||||
|
||||
oss.str("");
|
||||
oss << "process.execPath;";
|
||||
|
||||
result = RunScript(oss.str(), [](v8::Local<v8::Value> run) {
|
||||
v8::String::Utf8Value value(run);
|
||||
return dll::ThisLineLocation() == *value;
|
||||
});
|
||||
REQUIRE(result);
|
||||
|
||||
result = RunScriptFile("processtest.js", [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("assert", "[module-loader]") {
|
||||
auto result = RunScriptFile("asserttest.js", [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("file system", "[module-loader]") {
|
||||
auto result = RunScriptFile("fstest.js", [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("global", "[module-loader]") {
|
||||
auto result = RunScriptFile("globaltest.js", [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("path", "[module-loader]") {
|
||||
auto result = RunScriptFile("pathtest.js", [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("os", "[module-loader]") {
|
||||
auto result = RunScriptFile("ostest.js", [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("util", "[module-loader]") {
|
||||
auto result = RunScriptFile("utiltest.js", [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("tty", "[module-loader]") {
|
||||
auto result = RunScriptFile("ttytest.js", [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("cycling import", "[module-loader]") {
|
||||
auto result = RunScriptFile("cycle-main.js", [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("resolve modules", "[module-loader]") {
|
||||
auto result = RunScriptFile("module-resolution-test.js", [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
TEST_CASE("resolve full path modules", "[module-loader]") {
|
||||
auto filePath = filesystem::CurrentDirectory() / "tests\\sub\\sub1\\file2.js";
|
||||
auto filePathString = filePath.String();
|
||||
utils::string::ReplaceAll(filePathString, "\\", "\\\\");
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "var file = require('" << filePathString << "');\r\n"
|
||||
<< "(file != null);";
|
||||
|
||||
auto result = RunScript(oss.str(), [](v8::Local<v8::Value> run) {
|
||||
return run->BooleanValue();
|
||||
});
|
||||
REQUIRE(result);
|
||||
}
|
||||
|
||||
class AsyncTestTask : public Task {
|
||||
public:
|
||||
AsyncTestTask(zone::NapaZone* zone, std::string filename)
|
||||
: _zone(zone), _filename(std::move(filename)), _succeeded(false) {}
|
||||
|
||||
void Execute() override {
|
||||
// TODO @suchoi: Remove this line after Asi checks in the separation of zone construct and init.
|
||||
WorkerContext::Set(WorkerContextItem::ZONE, reinterpret_cast<void*>(_zone));
|
||||
|
||||
if (_filename.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
std::ifstream file(_filename);
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
|
||||
auto source = napa::v8_helpers::MakeV8String(isolate, buffer.str());
|
||||
|
||||
std::unique_ptr<std::condition_variable,
|
||||
std::function<void(std::condition_variable*)>> deferred(&_cond, [](auto cond) {
|
||||
cond->notify_one();
|
||||
});
|
||||
|
||||
v8::TryCatch tryCatch;
|
||||
auto script = v8::Script::Compile(source);
|
||||
if (tryCatch.HasCaught()) {
|
||||
_succeeded = false;
|
||||
return;
|
||||
}
|
||||
|
||||
auto run = script->Run();
|
||||
if (tryCatch.HasCaught()) {
|
||||
_succeeded = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_succeeded = true;
|
||||
}
|
||||
|
||||
bool ok() {
|
||||
std::unique_lock<std::mutex> lock(_lock);
|
||||
_cond.wait(lock);
|
||||
|
||||
return _succeeded;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
zone::NapaZone* _zone;
|
||||
|
||||
std::string _filename;
|
||||
bool _succeeded = false;
|
||||
|
||||
std::mutex _lock;
|
||||
std::condition_variable _cond;
|
||||
};
|
||||
|
||||
TEST_CASE("async", "[module-loader]") {
|
||||
ZoneSettings settings;
|
||||
settings.id = "zone";
|
||||
settings.workers = 1;
|
||||
|
||||
auto zone = zone::NapaZone::Create(settings);
|
||||
|
||||
auto scheduler = zone->GetScheduler();
|
||||
scheduler->ScheduleOnAllWorkers(std::make_shared<AsyncTestTask>(zone.get(), std::string()));
|
||||
|
||||
auto task = std::make_shared<AsyncTestTask>(zone.get(), "asynctest1.js");
|
||||
scheduler->Schedule(task);
|
||||
|
||||
REQUIRE(task->ok());
|
||||
|
||||
task = std::make_shared<AsyncTestTask>(zone.get(), "asynctest2.js");
|
||||
scheduler->Schedule(task);
|
||||
|
||||
REQUIRE(task->ok());
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
require('./tests/sub/module-resolution-test-root.js')();
|
|
@ -1,207 +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 Label="Globals">
|
||||
<ProjectGuid>{718EC282-8C1B-44FB-BD98-97F2E09E0389}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<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>
|
||||
<PropertyGroup>
|
||||
<TestDir>$(OutDir)module-tests</TestDir>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<AdditionalDependencies>Winmm.lib;Dbghelp.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
|
||||
<!-- This is for testing only since V8 can export platform APIs at the latest version. -->
|
||||
<AdditionalDependencies>$(Pkgnapa_nodelib_vc140)\lib\$(BuildType)\$(BuildTarget)\v8_libbase.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>$(Pkgnapa_nodelib_vc140)\lib\$(BuildType)\$(BuildTarget)\v8_libplatform.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<DisableSpecificWarnings>4100;4251;4996</DisableSpecificWarnings>
|
||||
<PreprocessorDefinitions>NAPA_EXPORTS;NAPA_BINDING_EXPORTS;BUILDING_NAPA_EXTENSION;BUILDING_V8_SHARED;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="module-loader-tests.cpp" />
|
||||
</ItemGroup>
|
||||
<!-- To avoid exporting module-loader APIs -->
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\binary-module-loader.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\core-module-loader.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\javascript-module-loader.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\json-module-loader.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-cache.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-loader.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-loader-helpers.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-resolver.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\module\module.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\platform\win\platform.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\providers\providers.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\v8\v8-common.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\async-complete-task.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\async-runner.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\call-context.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\call-task.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\eval-task.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\napa-zone.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\node-zone.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\simple-thread-pool.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\terminable-task.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\timeout-service.cpp" />
|
||||
<ClCompile Include="$(NapaVanillaRoot)\src\zone\worker.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(NapaVanillaRoot)\src\module\core-modules\napa\napa-core-modules.proj" />
|
||||
<Import Project="$(NapaVanillaRoot)\src\module\core-modules\node\node-core-modules.proj" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(NapaVanillaRoot)\src\napa.vcxproj" />
|
||||
<ProjectReference Include="$(NapaVanillaRoot)\test\module\async\async.vcxproj" />
|
||||
<ProjectReference Include="$(NapaVanillaRoot)\test\module\sample\sample.vcxproj" />
|
||||
</ItemGroup>
|
||||
<!-- Test artifacts binplace -->
|
||||
<ItemGroup>
|
||||
<Robocopy Include="$(OutputPath)\$(TargetFileName)">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="$(NapaVanillaRoot)\lib\$(IntermediateOutputPath)">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\lib</DestinationFolder>
|
||||
<FileMatch>*.j*</FileMatch>
|
||||
<IsRecursive>true</IsRecursive>
|
||||
</Robocopy>
|
||||
<Robocopy Include="$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.dll">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="$(NapaVanillaRoot)\test\module\async\$(IntermediateOutputPath)\async.napa">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="$(NapaVanillaRoot)\test\module\sample\$(IntermediateOutputPath)\sample.napa">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="asserttest.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="asynctest1.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="asynctest2.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="core-module-tests.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="core-modules.json">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\lib\core</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="cycle-a.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="cycle-b.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="cycle-main.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="jsmodule.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="jsontest.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="fstest.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="fstest.json">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="globaltest.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="globaltest-module.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="module-resolution-test.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="ostest.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="pathtest.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="processtest.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="sample-test.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="ttytest.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="utiltest.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="toproxy.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\test</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="toupper.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\test</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="lib\tconsole.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\lib\core</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="lib\tfs.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\lib\core</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="tests\node_modules\file2.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\tests\node_modules</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="tests\sub\module-resolution-test-root.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\tests\sub</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="tests\sub\fstestsub.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\tests\sub</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="tests\sub\fstestsub.json">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\tests\sub</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="tests\sub\sub1\file1.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\tests\sub\sub1</DestinationFolder>
|
||||
</Robocopy>
|
||||
<Robocopy Include="tests\sub\sub1\file2.js">
|
||||
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\tests\sub\sub1</DestinationFolder>
|
||||
</Robocopy>
|
||||
</ItemGroup>
|
||||
<!-- Use napa catch adapter -->
|
||||
<Import Project="$(NapaVanillaRoot)\tools\catch-adapter\napa-catch.targets" />
|
||||
<Import Project="$(Pkgboost)\build\native\boost.targets" />
|
||||
<Import Project="$(Pkgboost_chrono_vc140)\build\native\boost_chrono-vc140.targets" />
|
||||
<Import Project="$(Pkgboost_date_time_vc140)\build\native\boost_date_time-vc140.targets" />
|
||||
<Import Project="$(Pkgboost_system_vc140)\build\native\boost_system-vc140.targets" />
|
||||
<Import Project="$(Pkgboost_thread_vc140)\build\native\boost_thread-vc140.targets" />
|
||||
<Import Project="$(Pkgboost_filesystem_vc140)\build\native\boost_filesystem-vc140.targets" />
|
||||
<Import Project="$(Pkgnapa_nodelib_vc140)\exports_v8_includes.props" />
|
||||
|
||||
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
|
@ -1,6 +0,0 @@
|
|||
var assert = require('assert');
|
||||
var os = require('os');
|
||||
|
||||
assert(os.type == "Windows_NT" || os.type == "Darwin" || os.type == "Linux");
|
||||
|
||||
true;
|
|
@ -1,106 +0,0 @@
|
|||
var assert = require('assert');
|
||||
var path = require('path');
|
||||
|
||||
assert.equal(
|
||||
path.normalize('a\\b\\..\\c/./d/././.'),
|
||||
"a\\c\\d\\.");
|
||||
|
||||
assert.equal(
|
||||
path.resolve('c:\\foo/bar', "a.txt"),
|
||||
"c:\\foo\\bar\\a.txt");
|
||||
|
||||
assert.equal(
|
||||
path.resolve("abc.txt"),
|
||||
process.cwd() + "\\abc.txt");
|
||||
|
||||
assert.equal(
|
||||
path.resolve("abc", "efg", "../hij", "./xyz.txt"),
|
||||
process.cwd() + "\\abc\\hij\\xyz.txt");
|
||||
|
||||
assert.equal(
|
||||
path.resolve("abc", "d:/a.txt"),
|
||||
"d:\\a.txt");
|
||||
|
||||
assert.equal(
|
||||
path.join("/foo", "bar", "baz/asdf", "quux", ".."),
|
||||
"\\foo\\bar\\baz\\asdf");
|
||||
|
||||
assert.equal(
|
||||
path.dirname("c:"),
|
||||
"c:");
|
||||
|
||||
assert.equal(
|
||||
path.dirname("c:\\windows"),
|
||||
"c:\\");
|
||||
|
||||
assert.equal(
|
||||
path.dirname("c:\\windows\\abc.txt"),
|
||||
"c:\\windows");
|
||||
|
||||
assert.equal(
|
||||
path.basename("c:\\windows\\abc.txt"),
|
||||
"abc.txt");
|
||||
|
||||
assert.equal(
|
||||
path.basename("c:\\windows\\a"),
|
||||
"a");
|
||||
|
||||
assert.equal(
|
||||
path.basename("c:\\windows\\abc.txt", ".txt"),
|
||||
"abc");
|
||||
|
||||
assert.equal(
|
||||
path.basename("c:\\windows\\abc.txt", ".Txt"),
|
||||
"abc.txt");
|
||||
|
||||
assert.equal(
|
||||
path.extname("c:\\windows\\abc.txt"),
|
||||
".txt");
|
||||
|
||||
assert.equal(
|
||||
path.extname("c:\\windows\\a.json.txt"),
|
||||
".txt");
|
||||
|
||||
assert.equal(
|
||||
path.extname("c:\\windows\\a."),
|
||||
".");
|
||||
|
||||
assert.equal(
|
||||
path.isAbsolute("c:\\windows\\a."),
|
||||
true);
|
||||
|
||||
assert.equal(
|
||||
path.isAbsolute("c:/windows/.."),
|
||||
true);
|
||||
|
||||
assert.equal(
|
||||
path.isAbsolute("../abc"),
|
||||
false);
|
||||
|
||||
assert.equal(
|
||||
path.isAbsolute("./abc"),
|
||||
false);
|
||||
|
||||
assert.equal(
|
||||
path.isAbsolute("abc"),
|
||||
false);
|
||||
|
||||
assert.equal(
|
||||
path.relative("c:\\a\\..\\b", "c:\\b"),
|
||||
".");
|
||||
|
||||
assert.equal(
|
||||
path.relative("c:/a", "d:/b/../c"),
|
||||
"d:\\c");
|
||||
|
||||
assert.equal(
|
||||
path.relative("z:/a", "a.txt"),
|
||||
process.cwd() + "\\a.txt");
|
||||
|
||||
assert.equal(
|
||||
path.relative("c:/a", "c:/"),
|
||||
"..");
|
||||
|
||||
assert.notEqual("foo/bar\\baz".indexOf(path.sep), -1);
|
||||
|
||||
true;
|
|
@ -1,29 +0,0 @@
|
|||
var fs = require('fs');
|
||||
var events = require('events');
|
||||
var assert = require('assert');
|
||||
|
||||
process.env.NAPA_TEST = "process";
|
||||
assert.equal(process.env.NAPA_TEST, "process");
|
||||
|
||||
assert(typeof process.platform != undefined && process.platform != null);
|
||||
|
||||
assert(typeof process.umask != undefined);
|
||||
assert(process.umask() == process.umask(0));
|
||||
assert(process.umask() == process.umask("0"));
|
||||
|
||||
try {
|
||||
process.chdir('./test');
|
||||
process.chdir(process.cwd());
|
||||
process.chdir('..');
|
||||
fs.existsSync('napa.dll');
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
assert(typeof process.pid != undefined && !isNaN(process.pid));
|
||||
|
||||
events.defaultMaxListeners = 1;
|
||||
process.on('foo', () => {});
|
||||
assert.throws(() => { process.on('foo', () => {})});
|
||||
|
||||
true;
|
|
@ -1,39 +0,0 @@
|
|||
var sample = require('./sample.napa');
|
||||
|
||||
var runSampleNode = function() {
|
||||
// Create wrapped C++ object.
|
||||
var sampleNode = sample.createSampleNode(1);
|
||||
|
||||
// Calls C++ function through accessor.
|
||||
sampleNode.score = 2;
|
||||
|
||||
// Add property from javascript world.
|
||||
sampleNode.margin = 3;
|
||||
|
||||
// Access new property from C++ world.
|
||||
sampleNode.score += sampleNode.getValue('margin');
|
||||
|
||||
return sampleNode.score;
|
||||
}
|
||||
|
||||
var runSampleContainer = function(score) {
|
||||
var sampleContainer = sample.createSampleContainer();
|
||||
|
||||
// Access built-in member.
|
||||
sampleContainer.node.score = score;
|
||||
|
||||
var sum = sampleContainer.node.score;
|
||||
var sampleNode = sample.createSampleNode(score * 2);
|
||||
|
||||
// replace built-in member.
|
||||
sampleContainer.setNode(sampleNode);
|
||||
sum += sampleContainer.getNode().score;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
if (runSampleNode(3) + runSampleContainer(3) == 14) {
|
||||
true;
|
||||
} else {
|
||||
false;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
module.exports = {}
|
|
@ -1,12 +0,0 @@
|
|||
function fstestsub() {
|
||||
var filesystem = require('fs');
|
||||
var path = require('path');
|
||||
var content = JSON.parse(filesystem.readFileSync(path.resolve(__dirname, 'fstestsub.json')));
|
||||
if (content.subQuery != 'sub-query' || content.subDocument != 'sub-document') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = fstestsub();
|
|
@ -1 +0,0 @@
|
|||
{ "subQuery" : "sub-query", "subDocument" : "sub-document" }
|
|
@ -1,37 +0,0 @@
|
|||
var assert = require('assert');
|
||||
|
||||
//
|
||||
// Test require with path information
|
||||
//
|
||||
module.exports = function () {
|
||||
var paths = [
|
||||
"fs",
|
||||
"./sub1/file1.js",
|
||||
"./sub1/file1",
|
||||
"../sub/sub1/file1.js",
|
||||
// From module root via relative path.
|
||||
"../../sample.napa",
|
||||
"../../sample",
|
||||
// from .\node_modules to parents' recursively.
|
||||
"file2.js",
|
||||
"file2"
|
||||
];
|
||||
|
||||
for (i = 0; i < paths.length; i++) {
|
||||
var file = require(paths[i]);
|
||||
if (file == null) {
|
||||
console.log("Failed to resolve module at " + path[i]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
var path = require('path');
|
||||
|
||||
assert.equal(__filename, path.resolve(__dirname, "module-resolution-test-root.js"));
|
||||
|
||||
assert.equal(__dirname, path.resolve("tests\\sub"));
|
||||
|
||||
assert.equal(module.id, path.resolve(__dirname, "module-resolution-test-root.js"));
|
|
@ -1 +0,0 @@
|
|||
module.exports = {}
|
|
@ -1 +0,0 @@
|
|||
module.exports = {}
|
|
@ -1,6 +0,0 @@
|
|||
var exports = module.exports = {};
|
||||
|
||||
exports.run = function(data) {
|
||||
var toupper = require('./toupper');
|
||||
return toupper.toupper(data);
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
var exports = module.exports = {};
|
||||
|
||||
exports.toupper = function(data) {
|
||||
return data.toUpperCase();
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
var assert = require('assert');
|
||||
var tty = require('tty');
|
||||
|
||||
var result = process.binding('tty_wrap').guessHandleType(1);
|
||||
assert.equal(result, 'UNKNOWN');
|
||||
|
||||
assert.equal(tty.isatty(3), false);
|
||||
|
||||
true;
|
|
@ -1,30 +0,0 @@
|
|||
const assert = require('assert');
|
||||
const util = require('util');
|
||||
const EventEmitter = require('events');
|
||||
|
||||
function MyStream() {
|
||||
EventEmitter.call(this);
|
||||
}
|
||||
|
||||
util.inherits(MyStream, EventEmitter);
|
||||
|
||||
MyStream.prototype.write = function(data) {
|
||||
this.emit('data', data);
|
||||
};
|
||||
|
||||
const stream = new MyStream();
|
||||
|
||||
assert(stream instanceof EventEmitter);
|
||||
assert.equal(MyStream.super_, EventEmitter);
|
||||
|
||||
stream.on('data', (data) => {
|
||||
assert.equal(data, 'test');
|
||||
});
|
||||
stream.write('test');
|
||||
|
||||
var inspect = util.inspect(stream.write);
|
||||
assert.equal(inspect, '[Function]');
|
||||
|
||||
assert.equal(util.format('%s:%s', 'foo', 'bar', 'baz'), 'foo:bar baz');
|
||||
|
||||
true;
|
|
@ -1,214 +0,0 @@
|
|||
#include <napa-module.h>
|
||||
|
||||
using namespace napa;
|
||||
using namespace napa::module;
|
||||
|
||||
class SampleNode : public NAPA_OBJECTWRAP {
|
||||
public:
|
||||
|
||||
static void Init() {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
|
||||
auto functionTemplate = v8::FunctionTemplate::New(isolate, NewCallback);
|
||||
functionTemplate->SetClassName(v8_helpers::MakeV8String(isolate, _exportName));
|
||||
functionTemplate->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "getValue", GetValueCallback);
|
||||
NAPA_SET_ACCESSOR(functionTemplate, "score", GetScoreCallback, SetScoreCallback);
|
||||
|
||||
NAPA_SET_PERSISTENT_CONSTRUCTOR(_exportName, functionTemplate->GetFunction());
|
||||
}
|
||||
|
||||
static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
const int argc = 1;
|
||||
v8::Local<v8::Value> argv[argc] = { args[0] };
|
||||
|
||||
auto constructor = NAPA_GET_PERSISTENT_CONSTRUCTOR(_exportName, SampleNode);
|
||||
auto context = isolate->GetCurrentContext();
|
||||
auto instance = constructor->NewInstance(context, argc, argv).ToLocalChecked();
|
||||
|
||||
args.GetReturnValue().Set(instance);
|
||||
}
|
||||
|
||||
static v8::Local<v8::Object> NewInstance(uint32_t score) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::EscapableHandleScope scope(isolate);
|
||||
|
||||
const int argc = 1;
|
||||
v8::Local<v8::Value> argv[argc] = { v8::Number::New(isolate, score) };
|
||||
|
||||
auto constructor = NAPA_GET_PERSISTENT_CONSTRUCTOR(_exportName, SampleNode);
|
||||
return scope.Escape(constructor->NewInstance(argc, argv));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class SampleContainer;
|
||||
|
||||
static constexpr const char* _exportName = "SampleNode";
|
||||
|
||||
explicit SampleNode(uint32_t score = 0) : _score(score) {}
|
||||
|
||||
static void NewCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
JS_ASSERT(isolate, args.IsConstructCall(), "Only constructor call is allowed");
|
||||
|
||||
uint32_t score = args[0]->IsUndefined() ? 0 : args[0]->Uint32Value();
|
||||
|
||||
auto sampleNode = new SampleNode(score);
|
||||
sampleNode->Wrap(args.Holder());
|
||||
args.GetReturnValue().Set(args.Holder());
|
||||
}
|
||||
|
||||
static void GetScoreCallback(v8::Local<v8::String>,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
auto sampleNode = NAPA_OBJECTWRAP::Unwrap<SampleNode>(args.Holder());
|
||||
args.GetReturnValue().Set(v8::Number::New(isolate, sampleNode->_score));
|
||||
}
|
||||
|
||||
static void SetScoreCallback(v8::Local<v8::String>,
|
||||
v8::Local<v8::Value> value,
|
||||
const v8::PropertyCallbackInfo<void>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
CHECK_ARG(isolate,
|
||||
value->IsUint32(),
|
||||
"Value must be a number.");
|
||||
|
||||
auto sampleNode = NAPA_OBJECTWRAP::Unwrap<SampleNode>(args.Holder());
|
||||
sampleNode->_score = value->Uint32Value();
|
||||
|
||||
args.GetReturnValue().SetUndefined();
|
||||
}
|
||||
|
||||
static void GetValueCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
CHECK_ARG(isolate,
|
||||
args.Length() > 0 && !args[0]->IsUndefined(),
|
||||
"The first argument must be a string.");
|
||||
|
||||
auto that = args.Holder();
|
||||
auto target = that->Get(args[0]->ToString())->ToObject();
|
||||
|
||||
args.GetReturnValue().Set(target);
|
||||
}
|
||||
|
||||
uint32_t _score;
|
||||
};
|
||||
|
||||
class SampleContainer : public NAPA_OBJECTWRAP {
|
||||
public:
|
||||
|
||||
static void Init() {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
|
||||
auto functionTemplate = v8::FunctionTemplate::New(isolate, NewCallback);
|
||||
functionTemplate->SetClassName(v8_helpers::MakeV8String(isolate, _exportName));
|
||||
functionTemplate->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
functionTemplate->InstanceTemplate()->Set(
|
||||
v8_helpers::MakeV8String(isolate, "node"),
|
||||
v8::FunctionTemplate::New(isolate, SampleNode::NewCallback));
|
||||
|
||||
NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "setNode", SetNodeCallback);
|
||||
NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "getNode", GetNodeCallback);
|
||||
|
||||
NAPA_SET_PERSISTENT_CONSTRUCTOR(_exportName, functionTemplate->GetFunction());
|
||||
}
|
||||
|
||||
static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
auto constructor = NAPA_GET_PERSISTENT_CONSTRUCTOR(_exportName, SampleContainer);
|
||||
JS_ASSERT(isolate, !constructor.IsEmpty(), "No registered constructor.");
|
||||
|
||||
auto context = isolate->GetCurrentContext();
|
||||
auto instance = constructor->NewInstance(context).ToLocalChecked();
|
||||
|
||||
args.GetReturnValue().Set(instance);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static constexpr const char* _exportName = "SampleContainer";
|
||||
|
||||
static void NewCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
JS_ASSERT(isolate, args.IsConstructCall(), "Only constructor call is allowed");
|
||||
|
||||
auto container = new SampleContainer();
|
||||
container->Wrap(args.Holder());
|
||||
args.GetReturnValue().Set(args.Holder());
|
||||
}
|
||||
|
||||
static void SetNodeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
CHECK_ARG(isolate,
|
||||
args.Length() > 0 && !args[0]->IsUndefined(),
|
||||
"The first argument must be a SampleNode instance.");
|
||||
|
||||
auto that = args.Holder();
|
||||
that->CreateDataProperty(isolate->GetCurrentContext(),
|
||||
v8_helpers::MakeV8String(isolate, "node"),
|
||||
args[0]->ToObject());
|
||||
|
||||
args.GetReturnValue().SetUndefined();
|
||||
}
|
||||
|
||||
static void GetNodeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
auto that = args.Holder();
|
||||
auto node = that->Get(v8_helpers::MakeV8String(isolate, "node"))->ToObject();
|
||||
|
||||
args.GetReturnValue().Set(node);
|
||||
}
|
||||
};
|
||||
|
||||
void CreateSampleNode(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
SampleNode::NewInstance(args);
|
||||
}
|
||||
|
||||
void CreateSampleContainer(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
SampleContainer::NewInstance(args);
|
||||
}
|
||||
|
||||
void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
CHECK_ARG(isolate,
|
||||
args.Length() > 0 && !args[0]->IsUndefined(),
|
||||
"The first argument must be a string.");
|
||||
|
||||
v8::String::Utf8Value value(args[0]);
|
||||
args.GetReturnValue().Set(v8_helpers::MakeV8String(isolate, *value));
|
||||
}
|
||||
|
||||
void Init(v8::Local<v8::Object> exports) {
|
||||
SampleNode::Init();
|
||||
SampleContainer::Init();
|
||||
|
||||
NAPA_SET_METHOD(exports, "createSampleNode", CreateSampleNode);
|
||||
NAPA_SET_METHOD(exports, "createSampleContainer", CreateSampleContainer);
|
||||
NAPA_SET_METHOD(exports, "print", Print);
|
||||
}
|
||||
|
||||
NAPA_MODULE(addon, Init);
|
|
@ -1,43 +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>
|
||||
<AddonName>sample</AddonName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<AddonName>sample</AddonName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>BUILDING_NAPA_EXTENSION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)\sample.cpp" />
|
||||
</ItemGroup>
|
||||
<Target Name="ChangeExtention" AfterTargets="Build">
|
||||
<Move SourceFiles="$(OutputPath)\$(TargetFileName)" DestinationFiles="$(OutputPath)\$(AddonName).napa" />
|
||||
</Target>
|
||||
<Import Project="$(Pkgnapa_nodelib_vc140)\exports_v8_includes.props" />
|
||||
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
|
@ -19,7 +19,7 @@
|
|||
"install": "cmake-js compile",
|
||||
"buildd": "cmake-js compile --debug",
|
||||
"prepare": "tsc -p lib",
|
||||
"pretest": "tsc -p test",
|
||||
"pretest": "cmake-js compile -d test/module/addon && tsc -p test",
|
||||
"test": "mocha test --recursive",
|
||||
"unittest": "cmake-js compile -d unittest && node unittest/run.js"
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace napa {
|
||||
namespace module {
|
||||
|
||||
|
@ -14,8 +13,6 @@ namespace module {
|
|||
class MetricWrap : public NAPA_OBJECTWRAP {
|
||||
public:
|
||||
|
||||
|
||||
|
||||
/// <summary> Initializes the wrap. </summary>
|
||||
static void Init();
|
||||
|
||||
|
|
|
@ -6,13 +6,18 @@
|
|||
using namespace napa;
|
||||
using namespace napa::module;
|
||||
|
||||
void TypeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
args.GetReturnValue().Set(v8_helpers::MakeV8String(isolate, platform::GetOSType()));
|
||||
}
|
||||
|
||||
void os::Init(v8::Local<v8::Object> exports) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
auto context = isolate->GetCurrentContext();
|
||||
|
||||
(void)exports->CreateDataProperty(context,
|
||||
v8_helpers::MakeV8String(isolate, "type"),
|
||||
v8_helpers::MakeV8String(isolate, platform::GetOSType()));
|
||||
NAPA_SET_METHOD(exports, "type", TypeCallback);
|
||||
}
|
|
@ -0,0 +1,440 @@
|
|||
import * as napa from "..";
|
||||
import * as assert from "assert";
|
||||
import * as path from "path";
|
||||
|
||||
type Zone = napa.zone.Zone;
|
||||
|
||||
describe('napajs/module', function () {
|
||||
this.timeout(0);
|
||||
let napaZone = napa.zone.create('module-tests-zone', { workers: 1 });
|
||||
|
||||
describe('load', function () {
|
||||
it('javascript module', () => {
|
||||
return napaZone.execute((thisFilePath: string) => {
|
||||
var assert = require("assert");
|
||||
var jsmodule = require(thisFilePath + '/module/jsmodule');
|
||||
|
||||
assert.notEqual(jsmodule, undefined);
|
||||
assert.equal(jsmodule.wasLoaded, true);
|
||||
}, [__dirname]);
|
||||
});
|
||||
|
||||
it('json module', () => {
|
||||
return napaZone.execute((thisFilePath: string) => {
|
||||
var assert = require("assert");
|
||||
var jsonModule = require(thisFilePath + '/module/test.json');
|
||||
|
||||
assert.notEqual(jsonModule, undefined);
|
||||
assert.equal(jsonModule.prop1, "val1");
|
||||
assert.equal(jsonModule.prop2, "val2");
|
||||
}, [__dirname]);
|
||||
});
|
||||
|
||||
it('napa module', () => {
|
||||
return napaZone.execute((thisFilePath: string) => {
|
||||
var assert = require("assert");
|
||||
var napaModule = require(thisFilePath + '/module/addon/build/simple-napa-addon.napa');
|
||||
|
||||
assert.notEqual(napaModule, undefined);
|
||||
assert.equal(napaModule.getModuleName(), "simple-napa-addon");
|
||||
}, [__dirname]);
|
||||
});
|
||||
|
||||
it('object wrap module', () => {
|
||||
return napaZone.execute((thisFilePath: string) => {
|
||||
var assert = require("assert");
|
||||
var napaModule = require(thisFilePath + '/module/addon/build/simple-napa-addon.napa');
|
||||
|
||||
var obj = napaModule.createSimpleObjectWrap();
|
||||
assert.notEqual(obj, undefined);
|
||||
obj.setValue(3);
|
||||
assert.equal(obj.getValue(), 3);
|
||||
}, [__dirname]);
|
||||
});
|
||||
|
||||
it('circular dependencies', () => {
|
||||
return napaZone.execute((thisFilePath: string) => {
|
||||
var assert = require("assert");
|
||||
|
||||
var cycle_a = require(thisFilePath + '/module/cycle-a.js');
|
||||
var cycle_b = require(thisFilePath + '/module/cycle-b.js');
|
||||
|
||||
assert(cycle_a.done);
|
||||
assert(cycle_b.done);
|
||||
}, [__dirname]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolve', function () {
|
||||
// TODO: support correct __dirname in annoymous function and move tests from 'esolution-tests.js' here.
|
||||
it('require.resolve', () => {
|
||||
return napaZone.execute(__dirname + "/module/resolution-tests.js", "run", []);
|
||||
});
|
||||
});
|
||||
|
||||
describe('core-modules', function () {
|
||||
describe('process', function () {
|
||||
it.skip('argv', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
|
||||
assert(process.argv.length > 0);
|
||||
assert(process.argv[0].includes('node'));
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('execPath', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
|
||||
assert(process.execPath.includes('node'));
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('env', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
|
||||
process.env.test = "napa-test";
|
||||
assert.equal(process.env.test, "napa-test");
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('platform', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
|
||||
assert(process.platform == 'win32' ||
|
||||
process.platform == 'darwin' ||
|
||||
process.platform == 'linux' ||
|
||||
process.platform == 'freebsd');
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('umask', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
|
||||
var old = process.umask(0);
|
||||
assert.equal(process.umask(old), 0);
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('chdir', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
|
||||
var cwd = process.cwd();
|
||||
process.chdir('..');
|
||||
assert.notEqual(cwd, process.cwd());
|
||||
assert(cwd.includes(process.cwd()));
|
||||
process.chdir(cwd);
|
||||
assert.equal(cwd, process.cwd());
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('pid', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
|
||||
assert.notEqual(typeof process.pid, undefined);
|
||||
assert(!isNaN(process.pid));
|
||||
}, []);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fs', function () {
|
||||
it('existsSync', () => {
|
||||
return napaZone.execute((thisFilePath: string) => {
|
||||
var assert = require("assert");
|
||||
var fs = require('fs');
|
||||
|
||||
assert(fs.existsSync(thisFilePath + '/module/jsmodule.js'));
|
||||
assert.ifError(fs.existsSync('non-existing-file.txt'));
|
||||
}, [__dirname]);
|
||||
});
|
||||
|
||||
it('readFileSync', () => {
|
||||
return napaZone.execute((thisFilePath: string) => {
|
||||
var assert = require("assert");
|
||||
var fs = require('fs');
|
||||
|
||||
var content = JSON.parse(fs.readFileSync(thisFilePath + '/module/test.json'));
|
||||
assert.equal(content.prop1, 'val1');
|
||||
assert.equal(content.prop2, 'val2');
|
||||
}, [__dirname]);
|
||||
});
|
||||
|
||||
it('mkdirSync', () => {
|
||||
return napaZone.execute((thisFilePath: string) => {
|
||||
var assert = require("assert");
|
||||
var fs = require('fs');
|
||||
|
||||
fs.mkdirSync(thisFilePath + '/module/test-dir');
|
||||
assert(fs.existsSync(thisFilePath + '/module/test-dir'));
|
||||
}, [__dirname]).then(()=> {
|
||||
// Cleanup
|
||||
var fs = require('fs');
|
||||
if (fs.existsSync('./module/test-dir')) {
|
||||
fs.rmdir('./module/test-dir');
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it('writeFileSync', () => {
|
||||
return napaZone.execute((thisFilePath: string) => {
|
||||
var assert = require("assert");
|
||||
var fs = require('fs');
|
||||
|
||||
fs.writeFileSync(thisFilePath + '/module/test-file', 'test');
|
||||
assert.equal(fs.readFileSync(thisFilePath + '/module/test-file'), 'test');
|
||||
}, [__dirname]).then(()=> {
|
||||
// Cleanup
|
||||
var fs = require('fs');
|
||||
if (fs.existsSync('./module/test-file')) {
|
||||
fs.unlinkSync('./module/test-file');
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it('readFileSync', () => {
|
||||
return napaZone.execute((thisFilePath: string) => {
|
||||
var assert = require("assert");
|
||||
var fs = require('fs');
|
||||
|
||||
var testDir = thisFilePath + '/module/test-dir';
|
||||
fs.mkdirSync(testDir);
|
||||
fs.writeFileSync(testDir + '/1', 'test');
|
||||
fs.writeFileSync(testDir + '/2', 'test');
|
||||
|
||||
assert.deepEqual(fs.readdirSync(testDir), ['1', '2']);
|
||||
}, [__dirname]).then(()=> {
|
||||
// Cleanup
|
||||
var fs = require('fs');
|
||||
if (fs.existsSync('./module/test-dir')) {
|
||||
fs.unlinkSync('./module/test-dir/1');
|
||||
fs.unlinkSync('./module/test-dir/2');
|
||||
fs.rmdir('./module/test-dir');
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('path', function () {
|
||||
it('normalize', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
var path = require("path");
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
assert.equal(path.normalize('a\\b\\..\\c/./d/././.'), "a\\c\\d");
|
||||
} else {
|
||||
assert.equal(path.normalize('a\\b\\..\\c/./d/././.'), "a/c/d");
|
||||
}
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('resolve', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
var path = require("path");
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
assert.equal(path.resolve('c:\\foo/bar', "a.txt"), "c:\\foo\\bar\\a.txt");
|
||||
assert.equal(path.resolve("abc.txt"), process.cwd() + "\\abc.txt");
|
||||
assert.equal(path.resolve("abc", "efg", "../hij", "./xyz.txt"), process.cwd() + "\\abc\\hij\\xyz.txt");
|
||||
assert.equal(path.resolve("abc", "d:/a.txt"), "d:\\a.txt");
|
||||
} else {
|
||||
assert.equal(path.resolve('/foo/bar', "a.txt"), "/foo/bar/a.txt");
|
||||
assert.equal(path.resolve("abc.txt"), process.cwd() + "/abc.txt");
|
||||
assert.equal(path.resolve("abc", "efg", "../hij", "./xyz.txt"), process.cwd() + "/abc/hij/xyz.txt");
|
||||
assert.equal(path.resolve("abc", "/a.txt"), "/a.txt");
|
||||
}
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('join', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
var path = require("path");
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
assert.equal(path.join("/foo", "bar", "baz/asdf", "quux", ".."), "\\foo\\bar\\baz\\asdf");
|
||||
} else {
|
||||
assert.equal(path.join("/foo", "bar", "baz/asdf", "quux", ".."), "/foo/bar/baz/asdf");
|
||||
}
|
||||
}, []);
|
||||
});
|
||||
|
||||
// TODO: fix bugs
|
||||
// 1. Error: the string "AssertionError: '.' == 'c:'" was thrown, throw an Error :)
|
||||
// 2. Error: the string "AssertionError: 'c:' == 'c:\\\\'" was thrown, throw an Error :)
|
||||
it.skip('dirname', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
var path = require("path");
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
assert.equal(path.dirname("c:"), "c:");
|
||||
assert.equal(path.dirname("c:\\windows"), "c:\\");
|
||||
assert.equal(path.dirname("c:\\windows\\abc.txt"), "c:\\windows");
|
||||
} else {
|
||||
assert.equal(path.dirname("/"), "/");
|
||||
assert.equal(path.dirname("/etc"), "/");
|
||||
assert.equal(path.dirname("/etc/passwd"), "/etc");
|
||||
}
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('basename', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
var path = require("path");
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
assert.equal(path.basename("c:\\windows\\abc.txt"), "abc.txt");
|
||||
assert.equal(path.basename("c:\\windows\\a"), "a");
|
||||
assert.equal(path.basename("c:\\windows\\abc.txt", ".txt"), "abc");
|
||||
assert.equal(path.basename("c:\\windows\\abc.txt", ".Txt"), "abc.txt");
|
||||
} else {
|
||||
assert.equal(path.basename("/test//abc.txt"), "abc.txt");
|
||||
assert.equal(path.basename("/test//a"), "a");
|
||||
assert.equal(path.basename("/test/abc.txt", ".txt"), "abc");
|
||||
assert.equal(path.basename("/windows/abc.txt", ".Txt"), "abc.txt");
|
||||
}
|
||||
}, []);
|
||||
});
|
||||
|
||||
// TODO: fix bugs
|
||||
// 1. Error: the string "AssertionError: '' == '.'" was thrown, throw an Error :)
|
||||
it.skip('extname', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
var path = require("path");
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
assert.equal(path.extname("c:\\windows\\abc.txt"), ".txt");
|
||||
assert.equal(path.extname("c:\\windows\\a.json.txt"), ".txt");
|
||||
assert.equal(path.extname("c:\\windows\\a."), ".");
|
||||
} else {
|
||||
assert.equal(path.extname("/test/abc.txt"), ".txt");
|
||||
assert.equal(path.extname("/test/a.json.txt"), ".txt");
|
||||
assert.equal(path.extname("/test/a."), ".");
|
||||
}
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('isAbsolute', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
var path = require("path");
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
assert.equal(path.isAbsolute("c:\\windows\\a."), true);
|
||||
assert.equal(path.isAbsolute("c:/windows/.."), true);
|
||||
assert.equal(path.isAbsolute("../abc"), false);
|
||||
assert.equal(path.isAbsolute("./abc"), false);
|
||||
assert.equal(path.isAbsolute("abc"), false);
|
||||
} else {
|
||||
assert.equal(path.isAbsolute("/test/a."), true);
|
||||
assert.equal(path.isAbsolute("/test/.."), true);
|
||||
assert.equal(path.isAbsolute("../abc"), false);
|
||||
assert.equal(path.isAbsolute("./abc"), false);
|
||||
assert.equal(path.isAbsolute("abc"), false);
|
||||
}
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('relative', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
var path = require("path");
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
assert.equal(path.relative("c:\\a\\..\\b", "c:\\b"), "");
|
||||
assert.equal(path.relative("c:/a", "d:/b/../c"), "d:\\c");
|
||||
assert.equal(path.relative("z:/a", "a.txt"), process.cwd() + "\\a.txt");
|
||||
assert.equal(path.relative("c:/a", "c:/"), "..");
|
||||
} else {
|
||||
assert.equal(path.relative("/test/a/../b", "/test/b"), "");
|
||||
assert.equal(path.relative("/test/a", "/test1/b/../c"), "/test1/c");
|
||||
assert.equal(path.relative("/test/a", "a.txt"), process.cwd() + "/a.txt");
|
||||
assert.equal(path.relative("/test/a", "/test/"), "..");
|
||||
}
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('sep', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
var path = require("path");
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
assert.equal(path.sep, "\\");
|
||||
} else {
|
||||
assert.equal(path.sep, "/");
|
||||
}
|
||||
}, []);
|
||||
});
|
||||
});
|
||||
|
||||
describe('os', function () {
|
||||
it('type', () => {
|
||||
return napaZone.execute(() => {
|
||||
var assert = require("assert");
|
||||
var os = require("os");
|
||||
|
||||
assert(os.type() == "Windows_NT" || os.type() == "Darwin" || os.type() == "Linux");
|
||||
}, []);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('async', function () {
|
||||
it('post async work', () => {
|
||||
return napaZone.execute((thisFilePath: string) => {
|
||||
var assert = require("assert");
|
||||
var napaModule = require(thisFilePath + '/module/addon/build/simple-napa-addon.napa');
|
||||
|
||||
var obj = napaModule.createSimpleObjectWrap();
|
||||
obj.setValue(3);
|
||||
|
||||
var promise = new Promise((resolve) => {
|
||||
obj.postIncrementWork((newValue: number) => {
|
||||
resolve(newValue);
|
||||
});
|
||||
});
|
||||
|
||||
// The value shouldn't have changed yet.
|
||||
assert.equal(obj.getValue(), 3);
|
||||
|
||||
return promise;
|
||||
}, [__dirname]).then((result) => {
|
||||
assert.equal(result.value, 4);
|
||||
});
|
||||
});
|
||||
|
||||
it('do async work', () => {
|
||||
return napaZone.execute((thisFilePath: string) => {
|
||||
var assert = require("assert");
|
||||
var napaModule = require(thisFilePath + '/module/addon/build/simple-napa-addon.napa');
|
||||
|
||||
var obj = napaModule.createSimpleObjectWrap();
|
||||
obj.setValue(8);
|
||||
|
||||
var promise = new Promise((resolve) => {
|
||||
obj.doIncrementWork((newValue: number) => {
|
||||
resolve(newValue);
|
||||
});
|
||||
});
|
||||
|
||||
// The actual increment happened in the same thread.
|
||||
assert.equal(obj.getValue(), 9);
|
||||
|
||||
return promise;
|
||||
}, [__dirname]).then((result) => {
|
||||
assert.equal(result.value, 9);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
test-dir
|
||||
test-file
|
||||
|
||||
!node_modules
|
||||
|
||||
# unignore js files used for module testing
|
||||
!**/*.js
|
|
@ -0,0 +1,45 @@
|
|||
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
|
||||
|
||||
project("simple-napa-addon")
|
||||
|
||||
set(NAPA_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
|
||||
|
||||
# Require Cxx14 features
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# The target name
|
||||
set(TARGET_NAME ${PROJECT_NAME})
|
||||
|
||||
# The generated library
|
||||
add_library(${TARGET_NAME} SHARED
|
||||
addon.cpp
|
||||
simple-object-wrap.cpp)
|
||||
|
||||
# Change output extension to 'napa'
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "" SUFFIX ".napa")
|
||||
|
||||
# Include directories
|
||||
target_include_directories(${TARGET_NAME}
|
||||
PRIVATE
|
||||
${NAPA_ROOT}/inc
|
||||
${CMAKE_JS_INC})
|
||||
|
||||
# Link libraries
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE ${CMAKE_JS_LIB})
|
||||
|
||||
# Link with napa shared library
|
||||
if (WIN32)
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE ${NAPA_ROOT}/bin/napa.lib)
|
||||
else()
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE ${NAPA_ROOT}/bin/libnapa.so)
|
||||
endif()
|
||||
|
||||
# Compiler definitions
|
||||
target_compile_definitions(${TARGET_NAME} PRIVATE BUILDING_NAPA_EXTENSION)
|
||||
|
||||
# Set output directory for the addon
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/build
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/build
|
||||
)
|
|
@ -0,0 +1,28 @@
|
|||
#include <napa-module.h>
|
||||
|
||||
#include "simple-object-wrap.h"
|
||||
|
||||
using namespace napa;
|
||||
using namespace napa::test;
|
||||
using namespace napa::module;
|
||||
|
||||
|
||||
void GetModuleName(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
args.GetReturnValue().Set(v8_helpers::MakeV8String(isolate, "simple-napa-addon"));
|
||||
}
|
||||
|
||||
void CreateSimpleObjectWrap(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
SimpleObjectWrap::NewInstance(args);
|
||||
}
|
||||
|
||||
void Init(v8::Local<v8::Object> exports) {
|
||||
SimpleObjectWrap::Init();
|
||||
|
||||
NAPA_SET_METHOD(exports, "getModuleName", GetModuleName);
|
||||
NAPA_SET_METHOD(exports, "createSimpleObjectWrap", CreateSimpleObjectWrap);
|
||||
}
|
||||
|
||||
NAPA_MODULE(addon, Init);
|
|
@ -0,0 +1,113 @@
|
|||
#include "simple-object-wrap.h"
|
||||
|
||||
#include <napa.h>
|
||||
#include <napa-assert.h>
|
||||
#include <napa-async.h>
|
||||
#include <napa/v8-helpers.h>
|
||||
|
||||
using namespace napa::module;
|
||||
using namespace napa::test;
|
||||
using namespace napa::v8_helpers;
|
||||
|
||||
NAPA_DEFINE_PERSISTENT_CONSTRUCTOR(SimpleObjectWrap);
|
||||
|
||||
void SimpleObjectWrap::Init() {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
|
||||
// Prepare constructor template.
|
||||
auto functionTemplate = v8::FunctionTemplate::New(isolate, DefaultConstructorCallback<SimpleObjectWrap>);
|
||||
functionTemplate->SetClassName(MakeV8String(isolate, exportName));
|
||||
functionTemplate->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
// Prototypes.
|
||||
NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "getValue", GetValue);
|
||||
NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "setValue", SetValue);
|
||||
NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "doIncrementWork", DoIncrementWork);
|
||||
NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "postIncrementWork", PostIncrementWork);
|
||||
|
||||
// Set persistent constructor into V8.
|
||||
NAPA_SET_PERSISTENT_CONSTRUCTOR(exportName, functionTemplate->GetFunction());
|
||||
}
|
||||
|
||||
void SimpleObjectWrap::NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
auto context = isolate->GetCurrentContext();
|
||||
|
||||
auto constructor = NAPA_GET_PERSISTENT_CONSTRUCTOR(exportName, ZoneWrap);
|
||||
args.GetReturnValue().Set(constructor->NewInstance(context).ToLocalChecked());
|
||||
}
|
||||
|
||||
void SimpleObjectWrap::GetValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
|
||||
auto wrap = ObjectWrap::Unwrap<SimpleObjectWrap>(args.Holder());
|
||||
|
||||
args.GetReturnValue().Set(wrap->value);
|
||||
}
|
||||
|
||||
void SimpleObjectWrap::SetValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
|
||||
CHECK_ARG(isolate, args[0]->IsUint32(), "first argument to setValue must be a uint32");
|
||||
|
||||
auto wrap = ObjectWrap::Unwrap<SimpleObjectWrap>(args.Holder());
|
||||
wrap->value = args[0]->Uint32Value();
|
||||
}
|
||||
|
||||
void SimpleObjectWrap::DoIncrementWork(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
|
||||
CHECK_ARG(isolate, args.Length() == 1 && args[0]->IsFunction(), "It requires a callback as arguments");
|
||||
|
||||
auto wrap = ObjectWrap::Unwrap<SimpleObjectWrap>(args.Holder());
|
||||
|
||||
napa::zone::DoAsyncWork(
|
||||
v8::Local<v8::Function>::Cast(args[0]),
|
||||
[wrap](auto complete) {
|
||||
// This runs at the same thread.
|
||||
auto newValue = ++wrap->value;
|
||||
|
||||
complete(reinterpret_cast<void*>(static_cast<uintptr_t>(newValue)));
|
||||
},
|
||||
[](auto jsCallback, void* result) {
|
||||
// This runs at the same thread as one DoIncrementWork() is called.
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
|
||||
int32_t argc = 1;
|
||||
v8::Local<v8::Value> argv[] = {
|
||||
v8::Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(result)))
|
||||
};
|
||||
|
||||
jsCallback->Call(isolate->GetCurrentContext()->Global(), argc, argv);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void SimpleObjectWrap::PostIncrementWork(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
|
||||
CHECK_ARG(isolate, args.Length() == 1 && args[0]->IsFunction(), "It requires a callback as arguments");
|
||||
|
||||
auto wrap = ObjectWrap::Unwrap<SimpleObjectWrap>(args.Holder());
|
||||
|
||||
napa::zone::PostAsyncWork(
|
||||
v8::Local<v8::Function>::Cast(args[0]),
|
||||
[wrap]() {
|
||||
// This runs at the separate thread.
|
||||
auto newValue = ++wrap->value;
|
||||
|
||||
return reinterpret_cast<void*>(static_cast<uintptr_t>(newValue));
|
||||
},
|
||||
[](auto jsCallback, void* result) {
|
||||
// This runs at the same thread as one PostIncrementWork() is called.
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
|
||||
int32_t argc = 1;
|
||||
v8::Local<v8::Value> argv[] = {
|
||||
v8::Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(result)))
|
||||
};
|
||||
|
||||
jsCallback->Call(isolate->GetCurrentContext()->Global(), argc, argv);
|
||||
}
|
||||
);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
#include <napa-module.h>
|
||||
#include <napa/module/common.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace napa {
|
||||
namespace test {
|
||||
|
||||
/// <summary> A simple object wrap for testing. </summary>
|
||||
class SimpleObjectWrap : public NAPA_OBJECTWRAP {
|
||||
public:
|
||||
|
||||
/// <summary> Exported class name. </summary>
|
||||
static constexpr const char* exportName = "SimpleObjectWrap";
|
||||
|
||||
/// <summary> Initializes the wrap. </summary>
|
||||
static void Init();
|
||||
|
||||
/// <summary> Create a new wrap instance. </summary>
|
||||
static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
std::atomic<uint32_t> value = 0;
|
||||
|
||||
private:
|
||||
|
||||
/// <summary> Declare persistent constructor to create Zone Javascript wrapper instance. </summary>
|
||||
NAPA_DECLARE_PERSISTENT_CONSTRUCTOR;
|
||||
|
||||
// SimpleObjectWrap methods
|
||||
static void GetValue(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetValue(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void DoIncrementWork(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PostIncrementWork(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
/// <summary> Friend default constructor callback. </summary>
|
||||
template <typename WrapType>
|
||||
friend void napa::module::DefaultConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>&);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
exports.wasLoaded = true;
|
|
@ -0,0 +1,38 @@
|
|||
var assert = require('assert');
|
||||
|
||||
function run() {
|
||||
// Core module
|
||||
assert(require.resolve('fs'), 'fs');
|
||||
|
||||
// Full path with extension
|
||||
assert(require.resolve(__dirname + '/sub-folder/file.js'), __dirname + '/sub-folder/file.js');
|
||||
|
||||
// Full path without extension
|
||||
assert(require.resolve(__dirname + '/sub-folder/file'), __dirname + '/sub-folder/file.js');
|
||||
|
||||
// Relative path with extension
|
||||
assert(require.resolve('./sub-folder/file.js'), __dirname + '/sub-folder/file.js');
|
||||
|
||||
// Relative path without extension
|
||||
assert(require.resolve('./sub-folder/file'), __dirname + '/sub-folder/file.js');
|
||||
|
||||
// Relative path with non normalized path
|
||||
assert(require.resolve('./sub-folder/.././sub-folder/file.js'), __dirname + '/sub-folder/file.js');
|
||||
|
||||
// Relative path without extension to napa addon
|
||||
assert(require.resolve('./addon/build/simple-napa-addon'), __dirname + '/addon/build/simple-napa-addon.napa');
|
||||
|
||||
// From node_modules with extension
|
||||
assert(require.resolve('file.js'), __dirname + '/node_modules/file.js');
|
||||
|
||||
// From node_modules without extension
|
||||
assert(require.resolve('file'), __dirname + '/node_modules/file.js');
|
||||
|
||||
// TODO: Fix this issue: require.resolve should throw an exception if file doesn't exist.
|
||||
// Resolving non-existing file should throw
|
||||
// assert.throws(() => {
|
||||
// require.resolve('./sub-folder/non-existing-file.js');
|
||||
// });
|
||||
}
|
||||
|
||||
exports.run = run;
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"prop1": "val1",
|
||||
"prop2": "val2"
|
||||
}
|
Загрузка…
Ссылка в новой задаче