@shqld/canvas 2.11.2-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/Readme.md +600 -0
  2. package/binding.gyp +230 -0
  3. package/browser.js +35 -0
  4. package/index.js +94 -0
  5. package/lib/DOMMatrix.js +620 -0
  6. package/lib/bindings.js +80 -0
  7. package/lib/canvas.js +113 -0
  8. package/lib/context2d.js +14 -0
  9. package/lib/image.js +96 -0
  10. package/lib/jpegstream.js +41 -0
  11. package/lib/parse-font.js +101 -0
  12. package/lib/pattern.js +17 -0
  13. package/lib/pdfstream.js +35 -0
  14. package/lib/pngstream.js +42 -0
  15. package/package.json +71 -0
  16. package/scripts/install.js +24 -0
  17. package/src/Backends.cc +18 -0
  18. package/src/Backends.h +10 -0
  19. package/src/Canvas.cc +965 -0
  20. package/src/Canvas.h +96 -0
  21. package/src/CanvasError.h +23 -0
  22. package/src/CanvasGradient.cc +123 -0
  23. package/src/CanvasGradient.h +22 -0
  24. package/src/CanvasPattern.cc +136 -0
  25. package/src/CanvasPattern.h +37 -0
  26. package/src/CanvasRenderingContext2d.cc +3360 -0
  27. package/src/CanvasRenderingContext2d.h +225 -0
  28. package/src/Image.cc +1434 -0
  29. package/src/Image.h +127 -0
  30. package/src/ImageData.cc +146 -0
  31. package/src/ImageData.h +27 -0
  32. package/src/JPEGStream.h +167 -0
  33. package/src/PNG.h +292 -0
  34. package/src/Point.h +11 -0
  35. package/src/Util.h +9 -0
  36. package/src/backend/Backend.cc +112 -0
  37. package/src/backend/Backend.h +69 -0
  38. package/src/backend/ImageBackend.cc +74 -0
  39. package/src/backend/ImageBackend.h +26 -0
  40. package/src/backend/PdfBackend.cc +53 -0
  41. package/src/backend/PdfBackend.h +24 -0
  42. package/src/backend/SvgBackend.cc +61 -0
  43. package/src/backend/SvgBackend.h +24 -0
  44. package/src/bmp/BMPParser.cc +457 -0
  45. package/src/bmp/BMPParser.h +60 -0
  46. package/src/bmp/LICENSE.md +24 -0
  47. package/src/closure.cc +26 -0
  48. package/src/closure.h +81 -0
  49. package/src/color.cc +779 -0
  50. package/src/color.h +30 -0
  51. package/src/dll_visibility.h +20 -0
  52. package/src/init.cc +94 -0
  53. package/src/register_font.cc +408 -0
  54. package/src/register_font.h +7 -0
  55. package/types/index.d.ts +484 -0
  56. package/util/has_lib.js +119 -0
  57. package/util/win_jpeg_lookup.js +21 -0
package/lib/canvas.js ADDED
@@ -0,0 +1,113 @@
1
+ 'use strict'
2
+
3
+ /*!
4
+ * Canvas
5
+ * Copyright (c) 2010 LearnBoost <tj@learnboost.com>
6
+ * MIT Licensed
7
+ */
8
+
9
+ const bindings = require('./bindings')
10
+ const Canvas = module.exports = bindings.Canvas
11
+ const Context2d = require('./context2d')
12
+ const PNGStream = require('./pngstream')
13
+ const PDFStream = require('./pdfstream')
14
+ const JPEGStream = require('./jpegstream')
15
+ const FORMATS = ['image/png', 'image/jpeg']
16
+ const util = require('util')
17
+
18
+ // TODO || is for Node.js pre-v6.6.0
19
+ Canvas.prototype[util.inspect.custom || 'inspect'] = function () {
20
+ return `[Canvas ${this.width}x${this.height}]`
21
+ }
22
+
23
+ Canvas.prototype.getContext = function (contextType, contextAttributes) {
24
+ if (contextType == '2d') {
25
+ const ctx = this._context2d || (this._context2d = new Context2d(this, contextAttributes))
26
+ this.context = ctx
27
+ ctx.canvas = this
28
+ return ctx
29
+ }
30
+ }
31
+
32
+ Canvas.prototype.pngStream =
33
+ Canvas.prototype.createPNGStream = function (options) {
34
+ return new PNGStream(this, options)
35
+ }
36
+
37
+ Canvas.prototype.pdfStream =
38
+ Canvas.prototype.createPDFStream = function (options) {
39
+ return new PDFStream(this, options)
40
+ }
41
+
42
+ Canvas.prototype.jpegStream =
43
+ Canvas.prototype.createJPEGStream = function (options) {
44
+ return new JPEGStream(this, options)
45
+ }
46
+
47
+ Canvas.prototype.toDataURL = function (a1, a2, a3) {
48
+ // valid arg patterns (args -> [type, opts, fn]):
49
+ // [] -> ['image/png', null, null]
50
+ // [qual] -> ['image/png', null, null]
51
+ // [undefined] -> ['image/png', null, null]
52
+ // ['image/png'] -> ['image/png', null, null]
53
+ // ['image/png', qual] -> ['image/png', null, null]
54
+ // [fn] -> ['image/png', null, fn]
55
+ // [type, fn] -> [type, null, fn]
56
+ // [undefined, fn] -> ['image/png', null, fn]
57
+ // ['image/png', qual, fn] -> ['image/png', null, fn]
58
+ // ['image/jpeg', fn] -> ['image/jpeg', null, fn]
59
+ // ['image/jpeg', opts, fn] -> ['image/jpeg', opts, fn]
60
+ // ['image/jpeg', qual, fn] -> ['image/jpeg', {quality: qual}, fn]
61
+ // ['image/jpeg', undefined, fn] -> ['image/jpeg', null, fn]
62
+ // ['image/jpeg'] -> ['image/jpeg', null, fn]
63
+ // ['image/jpeg', opts] -> ['image/jpeg', opts, fn]
64
+ // ['image/jpeg', qual] -> ['image/jpeg', {quality: qual}, fn]
65
+
66
+ let type = 'image/png'
67
+ let opts = {}
68
+ let fn
69
+
70
+ if (typeof a1 === 'function') {
71
+ fn = a1
72
+ } else {
73
+ if (typeof a1 === 'string' && FORMATS.includes(a1.toLowerCase())) {
74
+ type = a1.toLowerCase()
75
+ }
76
+
77
+ if (typeof a2 === 'function') {
78
+ fn = a2
79
+ } else {
80
+ if (typeof a2 === 'object') {
81
+ opts = a2
82
+ } else if (typeof a2 === 'number') {
83
+ opts = { quality: Math.max(0, Math.min(1, a2)) }
84
+ }
85
+
86
+ if (typeof a3 === 'function') {
87
+ fn = a3
88
+ } else if (undefined !== a3) {
89
+ throw new TypeError(`${typeof a3} is not a function`)
90
+ }
91
+ }
92
+ }
93
+
94
+ if (this.width === 0 || this.height === 0) {
95
+ // Per spec, if the bitmap has no pixels, return this string:
96
+ const str = 'data:,'
97
+ if (fn) {
98
+ setTimeout(() => fn(null, str))
99
+ return
100
+ } else {
101
+ return str
102
+ }
103
+ }
104
+
105
+ if (fn) {
106
+ this.toBuffer((err, buf) => {
107
+ if (err) return fn(err)
108
+ fn(null, `data:${type};base64,${buf.toString('base64')}`)
109
+ }, type, opts)
110
+ } else {
111
+ return `data:${type};base64,${this.toBuffer(type, opts).toString('base64')}`
112
+ }
113
+ }
@@ -0,0 +1,14 @@
1
+ 'use strict'
2
+
3
+ /*!
4
+ * Canvas - Context2d
5
+ * Copyright (c) 2010 LearnBoost <tj@learnboost.com>
6
+ * MIT Licensed
7
+ */
8
+
9
+ const bindings = require('./bindings')
10
+ const parseFont = require('./parse-font')
11
+ const { DOMMatrix } = require('./DOMMatrix')
12
+
13
+ bindings.CanvasRenderingContext2dInit(DOMMatrix, parseFont)
14
+ module.exports = bindings.CanvasRenderingContext2d
package/lib/image.js ADDED
@@ -0,0 +1,96 @@
1
+ 'use strict'
2
+
3
+ /*!
4
+ * Canvas - Image
5
+ * Copyright (c) 2010 LearnBoost <tj@learnboost.com>
6
+ * MIT Licensed
7
+ */
8
+
9
+ /**
10
+ * Module dependencies.
11
+ */
12
+
13
+ const bindings = require('./bindings')
14
+ const Image = module.exports = bindings.Image
15
+ const util = require('util')
16
+
17
+ // Lazily loaded simple-get
18
+ let get
19
+
20
+ const { GetSource, SetSource } = bindings
21
+
22
+ Object.defineProperty(Image.prototype, 'src', {
23
+ /**
24
+ * src setter. Valid values:
25
+ * * `data:` URI
26
+ * * Local file path
27
+ * * HTTP or HTTPS URL
28
+ * * Buffer containing image data (i.e. not a `data:` URI stored in a Buffer)
29
+ *
30
+ * @param {String|Buffer} val filename, buffer, data URI, URL
31
+ * @api public
32
+ */
33
+ set (val) {
34
+ if (typeof val === 'string') {
35
+ if (/^\s*data:/.test(val)) { // data: URI
36
+ const commaI = val.indexOf(',')
37
+ // 'base64' must come before the comma
38
+ const isBase64 = val.lastIndexOf('base64', commaI) !== -1
39
+ const content = val.slice(commaI + 1)
40
+ setSource(this, Buffer.from(content, isBase64 ? 'base64' : 'utf8'), val)
41
+ } else if (/^\s*https?:\/\//.test(val)) { // remote URL
42
+ const onerror = err => {
43
+ if (typeof this.onerror === 'function') {
44
+ this.onerror(err)
45
+ } else {
46
+ throw err
47
+ }
48
+ }
49
+
50
+ if (!get) get = require('simple-get')
51
+
52
+ get.concat({
53
+ url: val,
54
+ headers: { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36' }
55
+ }, (err, res, data) => {
56
+ if (err) return onerror(err)
57
+
58
+ if (res.statusCode < 200 || res.statusCode >= 300) {
59
+ return onerror(new Error(`Server responded with ${res.statusCode}`))
60
+ }
61
+
62
+ setSource(this, data)
63
+ })
64
+ } else { // local file path assumed
65
+ setSource(this, val)
66
+ }
67
+ } else if (Buffer.isBuffer(val)) {
68
+ setSource(this, val)
69
+ }
70
+ },
71
+
72
+ get () {
73
+ // TODO https://github.com/Automattic/node-canvas/issues/118
74
+ return getSource(this)
75
+ },
76
+
77
+ configurable: true
78
+ })
79
+
80
+ // TODO || is for Node.js pre-v6.6.0
81
+ Image.prototype[util.inspect.custom || 'inspect'] = function () {
82
+ return '[Image' +
83
+ (this.complete ? ':' + this.width + 'x' + this.height : '') +
84
+ (this.src ? ' ' + this.src : '') +
85
+ (this.complete ? ' complete' : '') +
86
+ ']'
87
+ }
88
+
89
+ function getSource (img) {
90
+ return img._originalSource || GetSource.call(img)
91
+ }
92
+
93
+ function setSource (img, src, origSrc) {
94
+ SetSource.call(img, src)
95
+ img._originalSource = origSrc
96
+ }
@@ -0,0 +1,41 @@
1
+ 'use strict'
2
+
3
+ /*!
4
+ * Canvas - JPEGStream
5
+ * Copyright (c) 2010 LearnBoost <tj@learnboost.com>
6
+ * MIT Licensed
7
+ */
8
+
9
+ const { Readable } = require('stream')
10
+ function noop () {}
11
+
12
+ class JPEGStream extends Readable {
13
+ constructor (canvas, options) {
14
+ super()
15
+
16
+ if (canvas.streamJPEGSync === undefined) {
17
+ throw new Error('node-canvas was built without JPEG support.')
18
+ }
19
+
20
+ this.options = options
21
+ this.canvas = canvas
22
+ }
23
+
24
+ _read () {
25
+ // For now we're not controlling the c++ code's data emission, so we only
26
+ // call canvas.streamJPEGSync once and let it emit data at will.
27
+ this._read = noop
28
+
29
+ this.canvas.streamJPEGSync(this.options, (err, chunk) => {
30
+ if (err) {
31
+ this.emit('error', err)
32
+ } else if (chunk) {
33
+ this.push(chunk)
34
+ } else {
35
+ this.push(null)
36
+ }
37
+ })
38
+ }
39
+ };
40
+
41
+ module.exports = JPEGStream
@@ -0,0 +1,101 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Font RegExp helpers.
5
+ */
6
+
7
+ const weights = 'bold|bolder|lighter|[1-9]00'
8
+ const styles = 'italic|oblique'
9
+ const variants = 'small-caps'
10
+ const stretches = 'ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded'
11
+ const units = 'px|pt|pc|in|cm|mm|%|em|ex|ch|rem|q'
12
+ const string = '\'([^\']+)\'|"([^"]+)"|[\\w\\s-]+'
13
+
14
+ // [ [ <‘font-style’> || <font-variant-css21> || <‘font-weight’> || <‘font-stretch’> ]?
15
+ // <‘font-size’> [ / <‘line-height’> ]? <‘font-family’> ]
16
+ // https://drafts.csswg.org/css-fonts-3/#font-prop
17
+ const weightRe = new RegExp(`(${weights}) +`, 'i')
18
+ const styleRe = new RegExp(`(${styles}) +`, 'i')
19
+ const variantRe = new RegExp(`(${variants}) +`, 'i')
20
+ const stretchRe = new RegExp(`(${stretches}) +`, 'i')
21
+ const sizeFamilyRe = new RegExp(
22
+ `([\\d\\.]+)(${units}) *((?:${string})( *, *(?:${string}))*)`)
23
+
24
+ /**
25
+ * Cache font parsing.
26
+ */
27
+
28
+ const cache = {}
29
+
30
+ const defaultHeight = 16 // pt, common browser default
31
+
32
+ /**
33
+ * Parse font `str`.
34
+ *
35
+ * @param {String} str
36
+ * @return {Object} Parsed font. `size` is in device units. `unit` is the unit
37
+ * appearing in the input string.
38
+ * @api private
39
+ */
40
+
41
+ module.exports = str => {
42
+ // Cached
43
+ if (cache[str]) return cache[str]
44
+
45
+ // Try for required properties first.
46
+ const sizeFamily = sizeFamilyRe.exec(str)
47
+ if (!sizeFamily) return // invalid
48
+
49
+ // Default values and required properties
50
+ const font = {
51
+ weight: 'normal',
52
+ style: 'normal',
53
+ stretch: 'normal',
54
+ variant: 'normal',
55
+ size: parseFloat(sizeFamily[1]),
56
+ unit: sizeFamily[2],
57
+ family: sizeFamily[3].replace(/["']/g, '').replace(/ *, */g, ',')
58
+ }
59
+
60
+ // Optional, unordered properties.
61
+ let weight, style, variant, stretch
62
+ // Stop search at `sizeFamily.index`
63
+ const substr = str.substring(0, sizeFamily.index)
64
+ if ((weight = weightRe.exec(substr))) font.weight = weight[1]
65
+ if ((style = styleRe.exec(substr))) font.style = style[1]
66
+ if ((variant = variantRe.exec(substr))) font.variant = variant[1]
67
+ if ((stretch = stretchRe.exec(substr))) font.stretch = stretch[1]
68
+
69
+ // Convert to device units. (`font.unit` is the original unit)
70
+ // TODO: ch, ex
71
+ switch (font.unit) {
72
+ case 'pt':
73
+ font.size /= 0.75
74
+ break
75
+ case 'pc':
76
+ font.size *= 16
77
+ break
78
+ case 'in':
79
+ font.size *= 96
80
+ break
81
+ case 'cm':
82
+ font.size *= 96.0 / 2.54
83
+ break
84
+ case 'mm':
85
+ font.size *= 96.0 / 25.4
86
+ break
87
+ case '%':
88
+ // TODO disabled because existing unit tests assume 100
89
+ // font.size *= defaultHeight / 100 / 0.75
90
+ break
91
+ case 'em':
92
+ case 'rem':
93
+ font.size *= defaultHeight / 0.75
94
+ break
95
+ case 'q':
96
+ font.size *= 96 / 25.4 / 4
97
+ break
98
+ }
99
+
100
+ return (cache[str] = font)
101
+ }
package/lib/pattern.js ADDED
@@ -0,0 +1,17 @@
1
+ 'use strict'
2
+
3
+ /*!
4
+ * Canvas - CanvasPattern
5
+ * Copyright (c) 2010 LearnBoost <tj@learnboost.com>
6
+ * MIT Licensed
7
+ */
8
+
9
+ const bindings = require('./bindings')
10
+ const { DOMMatrix } = require('./DOMMatrix')
11
+
12
+ bindings.CanvasPatternInit(DOMMatrix)
13
+ module.exports = bindings.CanvasPattern
14
+
15
+ bindings.CanvasPattern.prototype.toString = function () {
16
+ return '[object CanvasPattern]'
17
+ }
@@ -0,0 +1,35 @@
1
+ 'use strict'
2
+
3
+ /*!
4
+ * Canvas - PDFStream
5
+ */
6
+
7
+ const { Readable } = require('stream')
8
+ function noop () {}
9
+
10
+ class PDFStream extends Readable {
11
+ constructor (canvas, options) {
12
+ super()
13
+
14
+ this.canvas = canvas
15
+ this.options = options
16
+ }
17
+
18
+ _read () {
19
+ // For now we're not controlling the c++ code's data emission, so we only
20
+ // call canvas.streamPDFSync once and let it emit data at will.
21
+ this._read = noop
22
+
23
+ this.canvas.streamPDFSync((err, chunk, len) => {
24
+ if (err) {
25
+ this.emit('error', err)
26
+ } else if (len) {
27
+ this.push(chunk)
28
+ } else {
29
+ this.push(null)
30
+ }
31
+ }, this.options)
32
+ }
33
+ }
34
+
35
+ module.exports = PDFStream
@@ -0,0 +1,42 @@
1
+ 'use strict'
2
+
3
+ /*!
4
+ * Canvas - PNGStream
5
+ * Copyright (c) 2010 LearnBoost <tj@learnboost.com>
6
+ * MIT Licensed
7
+ */
8
+
9
+ const { Readable } = require('stream')
10
+ function noop () {}
11
+
12
+ class PNGStream extends Readable {
13
+ constructor (canvas, options) {
14
+ super()
15
+
16
+ if (options &&
17
+ options.palette instanceof Uint8ClampedArray &&
18
+ options.palette.length % 4 !== 0) {
19
+ throw new Error('Palette length must be a multiple of 4.')
20
+ }
21
+ this.canvas = canvas
22
+ this.options = options || {}
23
+ }
24
+
25
+ _read () {
26
+ // For now we're not controlling the c++ code's data emission, so we only
27
+ // call canvas.streamPNGSync once and let it emit data at will.
28
+ this._read = noop
29
+
30
+ this.canvas.streamPNGSync((err, chunk, len) => {
31
+ if (err) {
32
+ this.emit('error', err)
33
+ } else if (len) {
34
+ this.push(chunk)
35
+ } else {
36
+ this.push(null)
37
+ }
38
+ }, this.options)
39
+ }
40
+ }
41
+
42
+ module.exports = PNGStream
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@shqld/canvas",
3
+ "description": "Canvas graphics API backed by Cairo",
4
+ "version": "2.11.2-rc.1",
5
+ "author": "TJ Holowaychuk <tj@learnboost.com>",
6
+ "main": "index.js",
7
+ "browser": "browser.js",
8
+ "contributors": [
9
+ "Nathan Rajlich <nathan@tootallnate.net>",
10
+ "Rod Vagg <r@va.gg>",
11
+ "Juriy Zaytsev <kangax@gmail.com>"
12
+ ],
13
+ "keywords": [
14
+ "canvas",
15
+ "graphic",
16
+ "graphics",
17
+ "pixman",
18
+ "cairo",
19
+ "image",
20
+ "images",
21
+ "pdf"
22
+ ],
23
+ "homepage": "https://github.com/Automattic/node-canvas",
24
+ "repository": "git://github.com/Automattic/node-canvas.git",
25
+ "scripts": {
26
+ "prebenchmark": "node-gyp build",
27
+ "benchmark": "node benchmarks/run.js",
28
+ "lint": "standard examples/*.js test/server.js test/public/*.js benchmarks/run.js lib/context2d.js util/has_lib.js browser.js index.js",
29
+ "test": "mocha test/*.test.js",
30
+ "pretest-server": "node-gyp build",
31
+ "test-server": "node test/server.js",
32
+ "generate-wpt": "node ./test/wpt/generate.js",
33
+ "test-wpt": "mocha test/wpt/generated/*.js",
34
+ "install": "node scripts/install.js",
35
+ "dtslint": "dtslint types"
36
+ },
37
+ "files": [
38
+ "binding.gyp",
39
+ "lib/",
40
+ "scripts/",
41
+ "src/",
42
+ "util/",
43
+ "types/index.d.ts"
44
+ ],
45
+ "types": "types/index.d.ts",
46
+ "dependencies": {
47
+ "nan": "^2.17.0"
48
+ },
49
+ "optionalDependencies": {
50
+ "@shqld/canvas-darwin-arm64": "2.11.2-rc.1",
51
+ "@shqld/canvas-darwin-x64": "2.11.2-rc.1",
52
+ "@shqld/canvas-linux-arm64-gnu": "2.11.2-rc.1",
53
+ "@shqld/canvas-linux-x64-gnu": "2.11.2-rc.1",
54
+ "@shqld/canvas-win32-x64": "2.11.2-rc.1"
55
+ },
56
+ "devDependencies": {
57
+ "@types/node": "^10.12.18",
58
+ "assert-rejects": "^1.0.0",
59
+ "dtslint": "^4.0.7",
60
+ "express": "^4.16.3",
61
+ "js-yaml": "^4.1.0",
62
+ "mocha": "^5.2.0",
63
+ "pixelmatch": "^4.0.2",
64
+ "standard": "^12.0.1",
65
+ "typescript": "^4.2.2"
66
+ },
67
+ "engines": {
68
+ "node": ">=6"
69
+ },
70
+ "license": "MIT"
71
+ }
@@ -0,0 +1,24 @@
1
+ 'use strict'
2
+
3
+ // If a prebuilt binary is available and functional, skip node-gyp.
4
+ // Otherwise, fall back to building from source.
5
+
6
+ try {
7
+ const bindings = require('../lib/bindings')
8
+ const canvas = new bindings.Canvas(1, 1)
9
+ canvas.getContext('2d')
10
+ process.exit(0)
11
+ } catch (_) {
12
+ const { execSync } = require('child_process')
13
+ try {
14
+ execSync('node-gyp rebuild', {
15
+ stdio: 'inherit',
16
+ cwd: require('path').resolve(__dirname, '..')
17
+ })
18
+ } catch (e) {
19
+ console.error('Failed to build canvas from source.')
20
+ console.error('Please install the required system dependencies:')
21
+ console.error(' https://github.com/Automattic/node-canvas#compiling')
22
+ process.exit(1)
23
+ }
24
+ }
@@ -0,0 +1,18 @@
1
+ #include "Backends.h"
2
+
3
+ #include "backend/ImageBackend.h"
4
+ #include "backend/PdfBackend.h"
5
+ #include "backend/SvgBackend.h"
6
+
7
+ using namespace v8;
8
+
9
+ void Backends::Initialize(Local<Object> target) {
10
+ Nan::HandleScope scope;
11
+
12
+ Local<Object> obj = Nan::New<Object>();
13
+ ImageBackend::Initialize(obj);
14
+ PdfBackend::Initialize(obj);
15
+ SvgBackend::Initialize(obj);
16
+
17
+ Nan::Set(target, Nan::New<String>("Backends").ToLocalChecked(), obj).Check();
18
+ }
package/src/Backends.h ADDED
@@ -0,0 +1,10 @@
1
+ #pragma once
2
+
3
+ #include "backend/Backend.h"
4
+ #include <nan.h>
5
+ #include <v8.h>
6
+
7
+ class Backends : public Nan::ObjectWrap {
8
+ public:
9
+ static void Initialize(v8::Local<v8::Object> target);
10
+ };