Skip to content

Commit

Permalink
Migrate internals to N-API #1282
Browse files Browse the repository at this point in the history
  • Loading branch information
lovell committed Feb 15, 2020
1 parent d5ecc53 commit 4abb4ed
Show file tree
Hide file tree
Showing 21 changed files with 567 additions and 711 deletions.
2 changes: 1 addition & 1 deletion .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ Any change that modifies the existing public API should be added to the relevant

| Release | WIP branch |
| ------: | :--------- |
| v0.24.0 | wit |
| v0.25.0 | yield |
| v0.26.0 | zoom |

Please squash your changes into a single commit using a command like `git rebase -i upstream/<wip-branch>`.

Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ Lanczos resampling ensures quality is not sacrificed for speed.
As well as image resizing, operations such as
rotation, extraction, compositing and gamma correction are available.

Most modern 64-bit macOS, Windows and Linux systems running
Node versions 10, 12 and 13
Most modern 64-bit macOS, Windows and Linux systems running Node.js v10.16.0+
do not require any additional install or runtime dependencies.

## Examples
Expand Down
7 changes: 4 additions & 3 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
}, {
'target_name': 'sharp',
'dependencies': [
'<!(node -p "require(\'node-addon-api\').gyp")',
'libvips-cpp'
],
'variables': {
Expand All @@ -65,11 +66,11 @@
'src/stats.cc',
'src/operations.cc',
'src/pipeline.cc',
'src/sharp.cc',
'src/utilities.cc'
'src/utilities.cc',
'src/sharp.cc'
],
'include_dirs': [
'<!(node -e "require(\'nan\')")'
'<!@(node -p "require(\'node-addon-api\').include")',
],
'conditions': [
['use_global_libvips == "true"', {
Expand Down
3 changes: 1 addition & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ Lanczos resampling ensures quality is not sacrificed for speed.
As well as image resizing, operations such as
rotation, extraction, compositing and gamma correction are available.

Most modern 64-bit macOS, Windows and Linux systems running
Node versions 10, 12 and 13
Most modern 64-bit macOS, Windows and Linux systems running Node.js v10.16.0+
do not require any additional install or runtime dependencies.

[![Test Coverage](https://coveralls.io/repos/lovell/sharp/badge.png?branch=master)](https://coveralls.io/r/lovell/sharp?branch=master)
Expand Down
9 changes: 9 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## v0.25 - *yield*

Requires libvips TBD

### v0.25.0 - TBD

* Migrate internals to N-API.
[#1282](https://github.com/lovell/sharp/issues/1282)

## v0.24 - "*wit*"

Requires libvips v8.9.0.
Expand Down
4 changes: 2 additions & 2 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ yarn add sharp

## Prerequisites

* Node.js v10.13.0+
* Node.js v10.16.0+

## Prebuilt binaries

Ready-compiled sharp and libvips binaries are provided for use with
Node.js versions 10, 12 and 13 on the most common platforms:
Node.js v10.16.0+ (N-API v4) on the most common platforms:

* macOS x64 (>= 10.13)
* Linux x64 (glibc >= 2.17, musl >= 1.1.24)
Expand Down
7 changes: 6 additions & 1 deletion lib/constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ const Sharp = function (input, options) {
gamma: 0,
gammaOut: 0,
greyscale: false,
normalise: 0,
normalise: false,
brightness: 1,
saturation: 1,
hue: 0,
Expand Down Expand Up @@ -219,6 +219,11 @@ const Sharp = function (input, options) {
heifCompression: 'hevc',
tileSize: 256,
tileOverlap: 0,
tileContainer: 'fs',
tileLayout: 'dz',
tileFormat: 'last',
tileDepth: 'last',
tileAngle: 0,
tileSkipBlanks: -1,
tileBackground: [255, 255, 255, 255],
linearA: 1,
Expand Down
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
"dependencies": {
"color": "^3.1.2",
"detect-libc": "^1.0.3",
"nan": "^2.14.0",
"node-addon-api": "^2.0.0",
"npmlog": "^4.1.2",
"prebuild-install": "^5.3.3",
"semver": "^7.1.3",
Expand Down Expand Up @@ -138,11 +138,16 @@
"libvips": "8.9.0"
},
"engines": {
"node": ">=10.13.0"
"node": ">=10.16.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"binary": {
"napi_versions": [
4
]
},
"semistandard": {
"env": [
"mocha"
Expand Down
85 changes: 46 additions & 39 deletions src/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@
#include <queue>
#include <mutex> // NOLINT(build/c++11)

#include <node.h>
#include <node_buffer.h>
#include <nan.h>
#include <napi.h>
#include <vips/vips8>

#include "common.h"
Expand All @@ -30,66 +28,77 @@ using vips::VImage;

namespace sharp {

// Convenience methods to access the attributes of a v8::Object
bool HasAttr(v8::Local<v8::Object> obj, std::string attr) {
return Nan::Has(obj, Nan::New(attr).ToLocalChecked()).FromJust();
// Convenience methods to access the attributes of a Napi::Object
bool HasAttr(Napi::Object obj, std::string attr) {
return obj.Has(attr);
}
std::string AttrAsStr(v8::Local<v8::Object> obj, std::string attr) {
return *Nan::Utf8String(Nan::Get(obj, Nan::New(attr).ToLocalChecked()).ToLocalChecked());
std::string AttrAsStr(Napi::Object obj, std::string attr) {
return obj.Get(attr).As<Napi::String>();
}
std::vector<double> AttrAsRgba(v8::Local<v8::Object> obj, std::string attr) {
v8::Local<v8::Object> background = AttrAs<v8::Object>(obj, attr);
std::vector<double> rgba(4);
for (unsigned int i = 0; i < 4; i++) {
rgba[i] = AttrTo<double>(background, i);
uint32_t AttrAsUint32(Napi::Object obj, std::string attr) {
return obj.Get(attr).As<Napi::Number>().Uint32Value();
}
int32_t AttrAsInt32(Napi::Object obj, std::string attr) {
return obj.Get(attr).As<Napi::Number>().Int32Value();
}
double AttrAsDouble(Napi::Object obj, std::string attr) {
return obj.Get(attr).As<Napi::Number>().DoubleValue();
}
double AttrAsDouble(Napi::Object obj, unsigned int const attr) {
return obj.Get(attr).As<Napi::Number>().DoubleValue();
}
bool AttrAsBool(Napi::Object obj, std::string attr) {
return obj.Get(attr).As<Napi::Boolean>().Value();
}
std::vector<double> AttrAsRgba(Napi::Object obj, std::string attr) {
Napi::Array background = obj.Get(attr).As<Napi::Array>();
std::vector<double> rgba(background.Length());
for (unsigned int i = 0; i < background.Length(); i++) {
rgba[i] = AttrAsDouble(background, i);
}
return rgba;
}

// Create an InputDescriptor instance from a v8::Object describing an input image
InputDescriptor* CreateInputDescriptor(
v8::Local<v8::Object> input, std::vector<v8::Local<v8::Object>> &buffersToPersist
) {
Nan::HandleScope();
// Create an InputDescriptor instance from a Napi::Object describing an input image
InputDescriptor* CreateInputDescriptor(Napi::Object input) {
InputDescriptor *descriptor = new InputDescriptor;
if (HasAttr(input, "file")) {
descriptor->file = AttrAsStr(input, "file");
} else if (HasAttr(input, "buffer")) {
v8::Local<v8::Object> buffer = AttrAs<v8::Object>(input, "buffer");
descriptor->bufferLength = node::Buffer::Length(buffer);
descriptor->buffer = node::Buffer::Data(buffer);
Napi::Buffer<char> buffer = input.Get("buffer").As<Napi::Buffer<char>>();
descriptor->bufferLength = buffer.Length();
descriptor->buffer = buffer.Data();
descriptor->isBuffer = TRUE;
buffersToPersist.push_back(buffer);
}
descriptor->failOnError = AttrTo<bool>(input, "failOnError");
descriptor->failOnError = AttrAsBool(input, "failOnError");
// Density for vector-based input
if (HasAttr(input, "density")) {
descriptor->density = AttrTo<double>(input, "density");
descriptor->density = AttrAsDouble(input, "density");
}
// Raw pixel input
if (HasAttr(input, "rawChannels")) {
descriptor->rawChannels = AttrTo<uint32_t>(input, "rawChannels");
descriptor->rawWidth = AttrTo<uint32_t>(input, "rawWidth");
descriptor->rawHeight = AttrTo<uint32_t>(input, "rawHeight");
descriptor->rawChannels = AttrAsUint32(input, "rawChannels");
descriptor->rawWidth = AttrAsUint32(input, "rawWidth");
descriptor->rawHeight = AttrAsUint32(input, "rawHeight");
}
// Multi-page input (GIF, TIFF, PDF)
if (HasAttr(input, "pages")) {
descriptor->pages = AttrTo<int32_t>(input, "pages");
descriptor->pages = AttrAsInt32(input, "pages");
}
if (HasAttr(input, "page")) {
descriptor->page = AttrTo<uint32_t>(input, "page");
descriptor->page = AttrAsUint32(input, "page");
}
// Create new image
if (HasAttr(input, "createChannels")) {
descriptor->createChannels = AttrTo<uint32_t>(input, "createChannels");
descriptor->createWidth = AttrTo<uint32_t>(input, "createWidth");
descriptor->createHeight = AttrTo<uint32_t>(input, "createHeight");
descriptor->createChannels = AttrAsUint32(input, "createChannels");
descriptor->createWidth = AttrAsUint32(input, "createWidth");
descriptor->createHeight = AttrAsUint32(input, "createHeight");
descriptor->createBackground = AttrAsRgba(input, "createBackground");
}
// Limit input images to a given number of pixels, where pixels = width * height
descriptor->limitInputPixels = AttrTo<uint32_t>(input, "limitInputPixels");
descriptor->limitInputPixels = AttrAsUint32(input, "limitInputPixels");
// Allow switch from random to sequential access
descriptor->access = AttrTo<bool>(input, "sequentialRead") ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_RANDOM;
descriptor->access = AttrAsBool(input, "sequentialRead") ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_RANDOM;
return descriptor;
}

Expand Down Expand Up @@ -439,11 +448,9 @@ namespace sharp {
/*
Called when a Buffer undergoes GC, required to support mixed runtime libraries in Windows
*/
void FreeCallback(char* data, void* hint) {
if (data != nullptr) {
g_free(data);
}
}
std::function<void(void*, char*)> FreeCallback = [](void*, char* data) {
g_free(data);
};

/*
Temporary buffer of warnings
Expand Down
34 changes: 14 additions & 20 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
#include <tuple>
#include <vector>

#include <node.h>
#include <nan.h>
#include <napi.h>
#include <vips/vips8>

// Verify platform and compiler compatibility
Expand Down Expand Up @@ -82,23 +81,18 @@ namespace sharp {
createBackground{ 0.0, 0.0, 0.0, 255.0 } {}
};

// Convenience methods to access the attributes of a v8::Object
bool HasAttr(v8::Local<v8::Object> obj, std::string attr);
std::string AttrAsStr(v8::Local<v8::Object> obj, std::string attr);
std::vector<double> AttrAsRgba(v8::Local<v8::Object> obj, std::string attr);
template<typename T> v8::Local<T> AttrAs(v8::Local<v8::Object> obj, std::string attr) {
return Nan::Get(obj, Nan::New(attr).ToLocalChecked()).ToLocalChecked().As<T>();
}
template<typename T> T AttrTo(v8::Local<v8::Object> obj, std::string attr) {
return Nan::To<T>(Nan::Get(obj, Nan::New(attr).ToLocalChecked()).ToLocalChecked()).FromJust();
}
template<typename T> T AttrTo(v8::Local<v8::Object> obj, int attr) {
return Nan::To<T>(Nan::Get(obj, attr).ToLocalChecked()).FromJust();
}

// Create an InputDescriptor instance from a v8::Object describing an input image
InputDescriptor* CreateInputDescriptor(
v8::Local<v8::Object> input, std::vector<v8::Local<v8::Object>> &buffersToPersist); // NOLINT(runtime/references)
// Convenience methods to access the attributes of a Napi::Object
bool HasAttr(Napi::Object obj, std::string attr);
std::string AttrAsStr(Napi::Object obj, std::string attr);
uint32_t AttrAsUint32(Napi::Object obj, std::string attr);
int32_t AttrAsInt32(Napi::Object obj, std::string attr);
double AttrAsDouble(Napi::Object obj, std::string attr);
double AttrAsDouble(Napi::Object obj, unsigned int const attr);
bool AttrAsBool(Napi::Object obj, std::string attr);
std::vector<double> AttrAsRgba(Napi::Object obj, std::string attr);

// Create an InputDescriptor instance from a Napi::Object describing an input image
InputDescriptor* CreateInputDescriptor(Napi::Object input);

enum class ImageType {
JPEG,
Expand Down Expand Up @@ -211,7 +205,7 @@ namespace sharp {
/*
Called when a Buffer undergoes GC, required to support mixed runtime libraries in Windows
*/
void FreeCallback(char* data, void* hint);
extern std::function<void(void*, char*)> FreeCallback;

/*
Called with warnings from the glib-registered "VIPS" domain
Expand Down
Loading

0 comments on commit 4abb4ed

Please sign in to comment.