From 048bc24e4c505fa556495c3db31afa80b2d78fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Szabo?= Date: Mon, 3 Oct 2022 11:11:32 -0300 Subject: [PATCH 01/13] Removing old API support --- src/bindings/bindings.cc | 2 +- src/bindings/text-buffer-wrapper.cc | 24 ++++-------------------- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src/bindings/bindings.cc b/src/bindings/bindings.cc index fc9b31e1..e00328f5 100644 --- a/src/bindings/bindings.cc +++ b/src/bindings/bindings.cc @@ -21,4 +21,4 @@ void Init(Local exports) { TextBufferSnapshotWrapper::init(); } -NODE_MODULE(superstring, Init) +NAN_MODULE_WORKER_ENABLED(superstring, Init) diff --git a/src/bindings/text-buffer-wrapper.cc b/src/bindings/text-buffer-wrapper.cc index 3c633269..4db3b3d6 100644 --- a/src/bindings/text-buffer-wrapper.cc +++ b/src/bindings/text-buffer-wrapper.cc @@ -387,11 +387,7 @@ static Local encode_ranges(const vector &ranges) { auto length = ranges.size() * 4; auto buffer = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), length * sizeof(uint32_t)); auto result = v8::Uint32Array::New(buffer, 0, length); - #if (V8_MAJOR_VERSION < 8) - auto data = buffer->GetContents().Data(); - #else - auto data = buffer->GetBackingStore()->Data(); - #endif + auto data = buffer->GetBackingStore()->Data(); memcpy(data, ranges.data(), length * sizeof(uint32_t)); return result; } @@ -615,11 +611,7 @@ void TextBufferWrapper::find_words_with_subsequence_in_range(const Nan::Function } auto positions_buffer = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), positions_buffer_size); - #if (V8_MAJOR_VERSION < 8) - uint32_t *positions_data = reinterpret_cast(positions_buffer->GetContents().Data()); - #else - uint32_t *positions_data = reinterpret_cast(positions_buffer->GetBackingStore()->Data()); - #endif + uint32_t *positions_data = reinterpret_cast(positions_buffer->GetBackingStore()->Data()); uint32_t positions_array_index = 0; for (size_t i = 0; i < result.size() && i < max_count; i++) { @@ -943,11 +935,7 @@ void TextBufferWrapper::load(const Nan::FunctionCallbackInfo &info) { if (!force && text_buffer.is_modified()) { Local argv[] = {Nan::Null(), Nan::Null()}; auto callback = info[0].As(); - #if (V8_MAJOR_VERSION > 9 || (V8_MAJOR_VERSION == 9 && V8_MINOR_VERION > 4)) - Nan::Call(callback, callback->GetCreationContext().ToLocalChecked()->Global(), 2, argv); - #else - Nan::Call(callback, callback->CreationContext()->Global(), 2, argv); - #endif + Nan::Call(callback, callback->CreationContext()->Global(), 2, argv); return; } @@ -1052,11 +1040,7 @@ void TextBufferWrapper::base_text_matches_file(const Nan::FunctionCallbackInfo argv[] = {Nan::Null(), Nan::New(result)}; auto callback = info[0].As(); - #if (V8_MAJOR_VERSION > 9 || (V8_MAJOR_VERSION == 9 && V8_MINOR_VERION > 4)) - Nan::Call(callback, callback->GetCreationContext().ToLocalChecked()->Global(), 2, argv); - #else - Nan::Call(callback, callback->CreationContext()->Global(), 2, argv); - #endif + Nan::Call(callback, callback->CreationContext()->Global(), 2, argv); } } From 8705c312f6c34984687ae2dec00092bd8f110189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Szabo?= Date: Wed, 5 Oct 2022 12:10:15 -0300 Subject: [PATCH 02/13] Removed "browser" version We can re-add later, but we're already having too much trouble with the node.js version only, I don't feel it's a good idea to think about supporting YET ANOTHER version of this library... --- index.js | 475 ++++++++++++-------------------- script/build-browser-version.sh | 56 ---- script/install-emscripten.sh | 22 -- 3 files changed, 180 insertions(+), 373 deletions(-) delete mode 100755 script/build-browser-version.sh delete mode 100755 script/install-emscripten.sh diff --git a/index.js b/index.js index f28fa189..2d535b32 100644 --- a/index.js +++ b/index.js @@ -1,344 +1,229 @@ let binding -if (process.env.SUPERSTRING_USE_BROWSER_VERSION) { - binding = require('./browser'); - - const {TextBuffer, Patch} = binding - const {findSync, findAllSync, findAndMarkAllSync, findWordsWithSubsequenceInRange, getCharacterAtPosition} = TextBuffer.prototype - const DEFAULT_RANGE = Object.freeze({start: {row: 0, column: 0}, end: {row: Infinity, column: Infinity}}) - - TextBuffer.prototype.findInRangeSync = function (pattern, range) { - let ignoreCase = false - let unicode = false - if (pattern.source) { - ignoreCase = pattern.flags.includes('i') - unicode = pattern.unicode - pattern = pattern.source - } - const result = findSync.call(this, pattern, ignoreCase, unicode, range) - if (typeof result === 'string') { - throw new Error(result); - } else { - return result - } - } - - TextBuffer.prototype.findSync = function (pattern, range) { - return this.findInRangeSync(pattern, DEFAULT_RANGE) - } - - TextBuffer.prototype.findAllInRangeSync = function (pattern, range) { - let ignoreCase = false - let unicode = false - if (pattern.source) { - ignoreCase = pattern.flags.includes('i') - unicode = pattern.unicode - pattern = pattern.source - } - const result = findAllSync.call(this, pattern, ignoreCase, unicode, range) - if (typeof result === 'string') { - throw new Error(result); - } else { - return result - } - } - TextBuffer.prototype.findAllSync = function (pattern, range) { - return this.findAllInRangeSync(pattern, DEFAULT_RANGE) - } - - TextBuffer.prototype.findAndMarkAllInRangeSync = function (markerIndex, nextId, exclusive, pattern, range) { - let ignoreCase = false - let unicode = false - if (pattern.source) { - ignoreCase = pattern.flags.includes('i') - unicode = pattern.unicode - pattern = pattern.source - } - const result = findAndMarkAllSync.call(this, markerIndex, nextId, exclusive, pattern, ignoreCase, unicode, range) - if (typeof result === 'string') { - throw new Error(result); - } else { - return result - } - } - - TextBuffer.prototype.findAndMarkAllSync = function (markerIndex, nextId, exclusive, pattern) { - return this.findAndMarkAllInRangeSync(markerIndex, nextId, exclusive, pattern, DEFAULT_RANGE) - } - - TextBuffer.prototype.find = function (pattern) { - return new Promise(resolve => resolve(this.findSync(pattern))) - } - - TextBuffer.prototype.findInRange = function (pattern, range) { - return new Promise(resolve => resolve(this.findInRangeSync(pattern, range))) - } - - TextBuffer.prototype.findAll = function (pattern) { - return new Promise(resolve => resolve(this.findAllSync(pattern))) - } - - TextBuffer.prototype.findAllInRange = function (pattern, range) { - return new Promise(resolve => resolve(this.findAllInRangeSync(pattern, range))) - } - - TextBuffer.prototype.findWordsWithSubsequence = function (query, extraWordCharacters, maxCount) { - const range = {start: {row: 0, column: 0}, end: this.getExtent()} - return Promise.resolve( - findWordsWithSubsequenceInRange.call(this, query, extraWordCharacters, range).slice(0, maxCount) - ) - } - - TextBuffer.prototype.findWordsWithSubsequenceInRange = function (query, extraWordCharacters, maxCount, range) { - return Promise.resolve( - findWordsWithSubsequenceInRange.call(this, query, extraWordCharacters, range).slice(0, maxCount) - ) - } - - TextBuffer.prototype.getCharacterAtPosition = function (position) { - return String.fromCharCode(getCharacterAtPosition.call(this, position)) +try { + binding = require('./build/Release/superstring.node') +} catch (e1) { + try { + binding = require('./build/Debug/superstring.node') + } catch (e2) { + throw e1 } +} - const {compose} = Patch - const {splice} = Patch.prototype - - Patch.compose = function (patches) { - const result = compose.call(this, patches) - if (!result) throw new Error('Patch does not apply') - return result - } +const {TextBuffer, TextWriter, TextReader} = binding +const { + load, save, baseTextMatchesFile, + find, findAll, findSync, findAllSync, findWordsWithSubsequenceInRange +} = TextBuffer.prototype - Patch.prototype.splice = Object.assign(function () { - if (!splice.apply(this, arguments)) { - throw new Error('Patch does not apply') - } - }, splice) -} else { - try { - binding = require('./build/Release/superstring.node') - } catch (e1) { - try { - binding = require('./build/Debug/superstring.node') - } catch (e2) { - throw e1 - } +TextBuffer.prototype.load = function (source, options, progressCallback) { + if (typeof options !== 'object') { + progressCallback = options + options = {} } - const {TextBuffer, TextWriter, TextReader} = binding - const { - load, save, baseTextMatchesFile, - find, findAll, findSync, findAllSync, findWordsWithSubsequenceInRange - } = TextBuffer.prototype + const computePatch = options.patch === false ? false : true + const discardChanges = options.force === true ? true : false + const encoding = normalizeEncoding(options.encoding || 'UTF-8') - TextBuffer.prototype.load = function (source, options, progressCallback) { - if (typeof options !== 'object') { - progressCallback = options - options = {} + return new Promise((resolve, reject) => { + const completionCallback = (error, result) => { + error ? reject(error) : resolve(result) } - const computePatch = options.patch === false ? false : true - const discardChanges = options.force === true ? true : false - const encoding = normalizeEncoding(options.encoding || 'UTF-8') - - return new Promise((resolve, reject) => { - const completionCallback = (error, result) => { - error ? reject(error) : resolve(result) - } - - if (typeof source === 'string') { - const filePath = source + if (typeof source === 'string') { + const filePath = source + load.call( + this, + completionCallback, + progressCallback, + discardChanges, + computePatch, + filePath, + encoding + ) + } else { + const stream = source + const writer = new TextWriter(encoding) + stream.on('data', (data) => writer.write(data)) + stream.on('error', reject) + stream.on('end', () => { + writer.end() load.call( this, completionCallback, progressCallback, discardChanges, computePatch, - filePath, - encoding + writer ) - } else { - const stream = source - const writer = new TextWriter(encoding) - stream.on('data', (data) => writer.write(data)) - stream.on('error', reject) - stream.on('end', () => { - writer.end() - load.call( - this, - completionCallback, - progressCallback, - discardChanges, - computePatch, - writer - ) - }) - } - }) - } - - TextBuffer.prototype.save = function (destination, encoding = 'UTF8') { - const CHUNK_SIZE = 10 * 1024 + }) + } + }) +} - encoding = normalizeEncoding(encoding) +TextBuffer.prototype.save = function (destination, encoding = 'UTF8') { + const CHUNK_SIZE = 10 * 1024 - return new Promise((resolve, reject) => { - if (typeof destination === 'string') { - const filePath = destination - save.call(this, filePath, encoding, (error) => { - error ? reject(error) : resolve() - }) - } else { - const stream = destination - const reader = new TextReader(this, encoding) - const buffer = Buffer.allocUnsafe(CHUNK_SIZE) - writeToStream(null) + encoding = normalizeEncoding(encoding) - stream.on('error', (error) => { - reader.destroy() - reject(error) - }) + return new Promise((resolve, reject) => { + if (typeof destination === 'string') { + const filePath = destination + save.call(this, filePath, encoding, (error) => { + error ? reject(error) : resolve() + }) + } else { + const stream = destination + const reader = new TextReader(this, encoding) + const buffer = Buffer.allocUnsafe(CHUNK_SIZE) + writeToStream(null) + + stream.on('error', (error) => { + reader.destroy() + reject(error) + }) - function writeToStream () { - const bytesRead = reader.read(buffer) - if (bytesRead > 0) { - stream.write(buffer.slice(0, bytesRead), (error) => { - if (!error) writeToStream() - }) - } else { - stream.end(() => { - reader.end() - resolve() - }) - } + function writeToStream () { + const bytesRead = reader.read(buffer) + if (bytesRead > 0) { + stream.write(buffer.slice(0, bytesRead), (error) => { + if (!error) writeToStream() + }) + } else { + stream.end(() => { + reader.end() + resolve() + }) } } - }) - } - - TextBuffer.prototype.find = function (pattern) { - return this.findInRange(pattern, null) - } + } + }) +} - TextBuffer.prototype.findInRange = function (pattern, range) { - return new Promise((resolve, reject) => { - find.call(this, pattern, (error, result) => { - error ? reject(error) : resolve(result.length > 0 ? interpretRange(result) : null) - }, range) - }) - } +TextBuffer.prototype.find = function (pattern) { + return this.findInRange(pattern, null) +} - TextBuffer.prototype.findAll = function (pattern) { - return this.findAllInRange(pattern, null) - } +TextBuffer.prototype.findInRange = function (pattern, range) { + return new Promise((resolve, reject) => { + find.call(this, pattern, (error, result) => { + error ? reject(error) : resolve(result.length > 0 ? interpretRange(result) : null) + }, range) + }) +} - TextBuffer.prototype.findAllInRange = function (pattern, range) { - return new Promise((resolve, reject) => { - findAll.call(this, pattern, (error, result) => { - error ? reject(error) : resolve(interpretRangeArray(result)) - }, range) - }) - } +TextBuffer.prototype.findAll = function (pattern) { + return this.findAllInRange(pattern, null) +} - TextBuffer.prototype.findSync = function (pattern) { - return this.findInRangeSync(pattern, null) - } +TextBuffer.prototype.findAllInRange = function (pattern, range) { + return new Promise((resolve, reject) => { + findAll.call(this, pattern, (error, result) => { + error ? reject(error) : resolve(interpretRangeArray(result)) + }, range) + }) +} - TextBuffer.prototype.findInRangeSync = function (pattern, range) { - const result = findSync.call(this, pattern, range) - return result.length > 0 ? interpretRange(result) : null - } +TextBuffer.prototype.findSync = function (pattern) { + return this.findInRangeSync(pattern, null) +} - TextBuffer.prototype.findAllSync = function (pattern) { - return interpretRangeArray(findAllSync.call(this, pattern, null)) - } +TextBuffer.prototype.findInRangeSync = function (pattern, range) { + const result = findSync.call(this, pattern, range) + return result.length > 0 ? interpretRange(result) : null +} - TextBuffer.prototype.findAllInRangeSync = function (pattern, range) { - return interpretRangeArray(findAllSync.call(this, pattern, range)) - } +TextBuffer.prototype.findAllSync = function (pattern) { + return interpretRangeArray(findAllSync.call(this, pattern, null)) +} - TextBuffer.prototype.findWordsWithSubsequence = function (query, extraWordCharacters, maxCount) { - return this.findWordsWithSubsequenceInRange(query, extraWordCharacters, maxCount, { - start: {row: 0, column: 0}, - end: this.getExtent() - }) - } +TextBuffer.prototype.findAllInRangeSync = function (pattern, range) { + return interpretRangeArray(findAllSync.call(this, pattern, range)) +} - TextBuffer.prototype.findWordsWithSubsequenceInRange = function (query, extraWordCharacters, maxCount, range) { - return new Promise(resolve => - findWordsWithSubsequenceInRange.call(this, query, extraWordCharacters, maxCount, range, (matches, positions) => { - if (!matches) { - resolve(null) - return - } +TextBuffer.prototype.findWordsWithSubsequence = function (query, extraWordCharacters, maxCount) { + return this.findWordsWithSubsequenceInRange(query, extraWordCharacters, maxCount, { + start: {row: 0, column: 0}, + end: this.getExtent() + }) +} - let positionArrayIndex = 0 - for (let i = 0, n = matches.length; i < n; i++) { - let positionCount = positions[positionArrayIndex++] - matches[i].positions = interpretPointArray(positions, positionArrayIndex, positionCount) - positionArrayIndex += 2 * positionCount - } - resolve(matches) - }) - ) - } +TextBuffer.prototype.findWordsWithSubsequenceInRange = function (query, extraWordCharacters, maxCount, range) { + return new Promise(resolve => + findWordsWithSubsequenceInRange.call(this, query, extraWordCharacters, maxCount, range, (matches, positions) => { + if (!matches) { + resolve(null) + return + } - TextBuffer.prototype.baseTextMatchesFile = function (source, encoding = 'UTF8') { - return new Promise((resolve, reject) => { - const callback = (error, result) => { - if (error) { - reject(error) - } else { - resolve(result) - } + let positionArrayIndex = 0 + for (let i = 0, n = matches.length; i < n; i++) { + let positionCount = positions[positionArrayIndex++] + matches[i].positions = interpretPointArray(positions, positionArrayIndex, positionCount) + positionArrayIndex += 2 * positionCount } + resolve(matches) + }) + ) +} - if (typeof source === 'string') { - baseTextMatchesFile.call(this, callback, source, encoding) +TextBuffer.prototype.baseTextMatchesFile = function (source, encoding = 'UTF8') { + return new Promise((resolve, reject) => { + const callback = (error, result) => { + if (error) { + reject(error) } else { - const stream = source - const writer = new TextWriter(encoding) - stream.on('data', (data) => writer.write(data)) - stream.on('error', reject) - stream.on('end', () => { - writer.end() - baseTextMatchesFile.call(this, callback, writer) - }) + resolve(result) } - }) - } + } - function interpretPointArray (rawData, startIndex, pointCount) { - const points = [] - for (let i = 0; i < pointCount; i++) { - points.push({row: rawData[startIndex++], column: rawData[startIndex++]}) + if (typeof source === 'string') { + baseTextMatchesFile.call(this, callback, source, encoding) + } else { + const stream = source + const writer = new TextWriter(encoding) + stream.on('data', (data) => writer.write(data)) + stream.on('error', reject) + stream.on('end', () => { + writer.end() + baseTextMatchesFile.call(this, callback, writer) + }) } - return points + }) +} + +function interpretPointArray (rawData, startIndex, pointCount) { + const points = [] + for (let i = 0; i < pointCount; i++) { + points.push({row: rawData[startIndex++], column: rawData[startIndex++]}) } + return points +} - function interpretRangeArray (rawData) { - const rangeCount = rawData.length / 4 - const ranges = new Array(rangeCount) - let rawIndex = 0 - for (let rangeIndex = 0; rangeIndex < rangeCount; rangeIndex++) { - ranges[rangeIndex] = interpretRange(rawData, rawIndex) - rawIndex += 4 - } - return ranges +function interpretRangeArray (rawData) { + const rangeCount = rawData.length / 4 + const ranges = new Array(rangeCount) + let rawIndex = 0 + for (let rangeIndex = 0; rangeIndex < rangeCount; rangeIndex++) { + ranges[rangeIndex] = interpretRange(rawData, rawIndex) + rawIndex += 4 } + return ranges +} - function interpretRange (rawData, index = 0) { - return { - start: { - row: rawData[index], - column: rawData[index + 1] - }, - end: { - row: rawData[index + 2], - column: rawData[index + 3] - } +function interpretRange (rawData, index = 0) { + return { + start: { + row: rawData[index], + column: rawData[index + 1] + }, + end: { + row: rawData[index + 2], + column: rawData[index + 3] } } -} + } function normalizeEncoding(encoding) { return encoding.toUpperCase() diff --git a/script/build-browser-version.sh b/script/build-browser-version.sh deleted file mode 100755 index bb370e11..00000000 --- a/script/build-browser-version.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bash - -source emsdk-portable/emsdk_env.sh - -mkdir -p build - -emcc \ - -o build/pcre.o \ - -O3 \ - -I vendor/pcre/10.23/src \ - -I vendor/pcre/include \ - -D HAVE_CONFIG_H \ - -D PCRE2_CODE_UNIT_WIDTH=16 \ - vendor/pcre/pcre2_chartables.c \ - vendor/pcre/10.23/src/pcre2_auto_possess.c \ - vendor/pcre/10.23/src/pcre2_compile.c \ - vendor/pcre/10.23/src/pcre2_config.c \ - vendor/pcre/10.23/src/pcre2_context.c \ - vendor/pcre/10.23/src/pcre2_dfa_match.c \ - vendor/pcre/10.23/src/pcre2_error.c \ - vendor/pcre/10.23/src/pcre2_find_bracket.c \ - vendor/pcre/10.23/src/pcre2_jit_compile.c \ - vendor/pcre/10.23/src/pcre2_maketables.c \ - vendor/pcre/10.23/src/pcre2_match.c \ - vendor/pcre/10.23/src/pcre2_match_data.c \ - vendor/pcre/10.23/src/pcre2_newline.c \ - vendor/pcre/10.23/src/pcre2_ord2utf.c \ - vendor/pcre/10.23/src/pcre2_pattern_info.c \ - vendor/pcre/10.23/src/pcre2_serialize.c \ - vendor/pcre/10.23/src/pcre2_string_utils.c \ - vendor/pcre/10.23/src/pcre2_study.c \ - vendor/pcre/10.23/src/pcre2_substitute.c \ - vendor/pcre/10.23/src/pcre2_substring.c \ - vendor/pcre/10.23/src/pcre2_tables.c \ - vendor/pcre/10.23/src/pcre2_ucd.c \ - vendor/pcre/10.23/src/pcre2_valid_utf.c \ - vendor/pcre/10.23/src/pcre2_xclass.c - -em++ \ - --bind \ - -o browser.js \ - -O3 \ - -I src/bindings/em \ - -I src/core \ - -I vendor/libcxx \ - -I vendor/pcre/include \ - -D PCRE2_CODE_UNIT_WIDTH=16 \ - -xc++ \ - --pre-js src/bindings/em/prologue.js \ - --post-js src/bindings/em/epilogue.js \ - src/core/*.cc \ - src/bindings/em/*.cc \ - build/pcre.o \ - -s TOTAL_MEMORY=134217728 \ - --memory-init-file 0 \ - "$@" diff --git a/script/install-emscripten.sh b/script/install-emscripten.sh deleted file mode 100755 index 952cbcd4..00000000 --- a/script/install-emscripten.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -set -e - -EMSCRIPTEN_DOWNLOAD_URL='https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz' -EMSDK_PATH="./emsdk-portable/emsdk" - -if [ ! -f $EMSDK_PATH ]; then - echo 'Downloading emscripten SDK installer...' - curl $EMSCRIPTEN_DOWNLOAD_URL | tar xz -fi - -echo 'Installing emscripten SDK...' - -# Workaround https://github.com/juj/emsdk/pull/74 -sed -i{} "s_/kripken/emscripten/'_/kripken/emscripten'_" $EMSDK_PATH -sed -i{} "s_/WebAssembly/binaryen/'_/WebAssembly/binaryen'_" $EMSDK_PATH - -$EMSDK_PATH update -$EMSDK_PATH list -$EMSDK_PATH install sdk-1.37.9-64bit -$EMSDK_PATH activate sdk-1.37.9-64bit From c37a3757980dcf97d8ca20f5ae7c593a704747d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Szabo?= Date: Wed, 5 Oct 2022 12:24:46 -0300 Subject: [PATCH 03/13] Fixed self-bindings of prototypes --- index.js | 28 +++++++++++----------------- src/bindings/text-buffer-wrapper.cc | 16 ++++++++-------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/index.js b/index.js index 2d535b32..b2a39eea 100644 --- a/index.js +++ b/index.js @@ -11,10 +11,6 @@ try { } const {TextBuffer, TextWriter, TextReader} = binding -const { - load, save, baseTextMatchesFile, - find, findAll, findSync, findAllSync, findWordsWithSubsequenceInRange -} = TextBuffer.prototype TextBuffer.prototype.load = function (source, options, progressCallback) { if (typeof options !== 'object') { @@ -33,8 +29,7 @@ TextBuffer.prototype.load = function (source, options, progressCallback) { if (typeof source === 'string') { const filePath = source - load.call( - this, + this._load( completionCallback, progressCallback, discardChanges, @@ -49,8 +44,7 @@ TextBuffer.prototype.load = function (source, options, progressCallback) { stream.on('error', reject) stream.on('end', () => { writer.end() - load.call( - this, + this._load( completionCallback, progressCallback, discardChanges, @@ -70,7 +64,7 @@ TextBuffer.prototype.save = function (destination, encoding = 'UTF8') { return new Promise((resolve, reject) => { if (typeof destination === 'string') { const filePath = destination - save.call(this, filePath, encoding, (error) => { + this._save(filePath, encoding, (error) => { error ? reject(error) : resolve() }) } else { @@ -107,7 +101,7 @@ TextBuffer.prototype.find = function (pattern) { TextBuffer.prototype.findInRange = function (pattern, range) { return new Promise((resolve, reject) => { - find.call(this, pattern, (error, result) => { + this._find(pattern, (error, result) => { error ? reject(error) : resolve(result.length > 0 ? interpretRange(result) : null) }, range) }) @@ -119,7 +113,7 @@ TextBuffer.prototype.findAll = function (pattern) { TextBuffer.prototype.findAllInRange = function (pattern, range) { return new Promise((resolve, reject) => { - findAll.call(this, pattern, (error, result) => { + this._findAll(pattern, (error, result) => { error ? reject(error) : resolve(interpretRangeArray(result)) }, range) }) @@ -130,16 +124,16 @@ TextBuffer.prototype.findSync = function (pattern) { } TextBuffer.prototype.findInRangeSync = function (pattern, range) { - const result = findSync.call(this, pattern, range) + const result = this._findSync(pattern, range) return result.length > 0 ? interpretRange(result) : null } TextBuffer.prototype.findAllSync = function (pattern) { - return interpretRangeArray(findAllSync.call(this, pattern, null)) + return interpretRangeArray(this._findAllSync(pattern, null)) } TextBuffer.prototype.findAllInRangeSync = function (pattern, range) { - return interpretRangeArray(findAllSync.call(this, pattern, range)) + return interpretRangeArray(this._findAllSync(pattern, range)) } TextBuffer.prototype.findWordsWithSubsequence = function (query, extraWordCharacters, maxCount) { @@ -151,7 +145,7 @@ TextBuffer.prototype.findWordsWithSubsequence = function (query, extraWordCharac TextBuffer.prototype.findWordsWithSubsequenceInRange = function (query, extraWordCharacters, maxCount, range) { return new Promise(resolve => - findWordsWithSubsequenceInRange.call(this, query, extraWordCharacters, maxCount, range, (matches, positions) => { + this._findWordsWithSubsequenceInRange(query, extraWordCharacters, maxCount, range, (matches, positions) => { if (!matches) { resolve(null) return @@ -179,7 +173,7 @@ TextBuffer.prototype.baseTextMatchesFile = function (source, encoding = 'UTF8') } if (typeof source === 'string') { - baseTextMatchesFile.call(this, callback, source, encoding) + this._baseTextMatchesFile(callback, source, encoding) } else { const stream = source const writer = new TextWriter(encoding) @@ -187,7 +181,7 @@ TextBuffer.prototype.baseTextMatchesFile = function (source, encoding = 'UTF8') stream.on('error', reject) stream.on('end', () => { writer.end() - baseTextMatchesFile.call(this, callback, writer) + this._baseTextMatchesFile(callback, writer) }) } }) diff --git a/src/bindings/text-buffer-wrapper.cc b/src/bindings/text-buffer-wrapper.cc index 4db3b3d6..b5a79d8f 100644 --- a/src/bindings/text-buffer-wrapper.cc +++ b/src/bindings/text-buffer-wrapper.cc @@ -210,20 +210,20 @@ void TextBufferWrapper::init(Local exports) { Nan::SetTemplate(prototype_template, Nan::New("characterIndexForPosition").ToLocalChecked(), Nan::New(character_index_for_position), None); Nan::SetTemplate(prototype_template, Nan::New("positionForCharacterIndex").ToLocalChecked(), Nan::New(position_for_character_index), None); Nan::SetTemplate(prototype_template, Nan::New("isModified").ToLocalChecked(), Nan::New(is_modified), None); - Nan::SetTemplate(prototype_template, Nan::New("load").ToLocalChecked(), Nan::New(load), None); - Nan::SetTemplate(prototype_template, Nan::New("baseTextMatchesFile").ToLocalChecked(), Nan::New(base_text_matches_file), None); - Nan::SetTemplate(prototype_template, Nan::New("save").ToLocalChecked(), Nan::New(save), None); + Nan::SetTemplate(prototype_template, Nan::New("_load").ToLocalChecked(), Nan::New(load), None); + Nan::SetTemplate(prototype_template, Nan::New("_baseTextMatchesFile").ToLocalChecked(), Nan::New(base_text_matches_file), None); + Nan::SetTemplate(prototype_template, Nan::New("_save").ToLocalChecked(), Nan::New(save), None); Nan::SetTemplate(prototype_template, Nan::New("loadSync").ToLocalChecked(), Nan::New(load_sync), None); Nan::SetTemplate(prototype_template, Nan::New("serializeChanges").ToLocalChecked(), Nan::New(serialize_changes), None); Nan::SetTemplate(prototype_template, Nan::New("deserializeChanges").ToLocalChecked(), Nan::New(deserialize_changes), None); Nan::SetTemplate(prototype_template, Nan::New("reset").ToLocalChecked(), Nan::New(reset), None); Nan::SetTemplate(prototype_template, Nan::New("baseTextDigest").ToLocalChecked(), Nan::New(base_text_digest), None); - Nan::SetTemplate(prototype_template, Nan::New("find").ToLocalChecked(), Nan::New(find), None); - Nan::SetTemplate(prototype_template, Nan::New("findSync").ToLocalChecked(), Nan::New(find_sync), None); - Nan::SetTemplate(prototype_template, Nan::New("findAll").ToLocalChecked(), Nan::New(find_all), None); - Nan::SetTemplate(prototype_template, Nan::New("findAllSync").ToLocalChecked(), Nan::New(find_all_sync), None); + Nan::SetTemplate(prototype_template, Nan::New("_find").ToLocalChecked(), Nan::New(find), None); + Nan::SetTemplate(prototype_template, Nan::New("_findSync").ToLocalChecked(), Nan::New(find_sync), None); + Nan::SetTemplate(prototype_template, Nan::New("_findAll").ToLocalChecked(), Nan::New(find_all), None); + Nan::SetTemplate(prototype_template, Nan::New("_findAllSync").ToLocalChecked(), Nan::New(find_all_sync), None); Nan::SetTemplate(prototype_template, Nan::New("findAndMarkAllSync").ToLocalChecked(), Nan::New(find_and_mark_all_sync), None); - Nan::SetTemplate(prototype_template, Nan::New("findWordsWithSubsequenceInRange").ToLocalChecked(), Nan::New(find_words_with_subsequence_in_range), None); + Nan::SetTemplate(prototype_template, Nan::New("_findWordsWithSubsequenceInRange").ToLocalChecked(), Nan::New(find_words_with_subsequence_in_range), None); Nan::SetTemplate(prototype_template, Nan::New("getDotGraph").ToLocalChecked(), Nan::New(dot_graph), None); Nan::SetTemplate(prototype_template, Nan::New("getSnapshot").ToLocalChecked(), Nan::New(get_snapshot), None); RegexWrapper::init(); From cbb692edfbee56fb0cc95d15bba095796c89783a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Szabo?= Date: Thu, 6 Oct 2022 22:19:26 -0300 Subject: [PATCH 04/13] Added napi to package and binding --- binding.gyp | 9 +++++++-- package.json | 11 ++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/binding.gyp b/binding.gyp index 249e9e82..c78ed0a2 100644 --- a/binding.gyp +++ b/binding.gyp @@ -3,7 +3,11 @@ { "target_name": "superstring", "dependencies": [ - "superstring_core" + "superstring_core", + " Date: Fri, 7 Oct 2022 00:50:45 -0300 Subject: [PATCH 05/13] Point and Range converted --- binding.gyp | 14 ++-- src/bindings/bindings.cc | 52 +++++++++----- src/bindings/point-wrapper.cc | 124 +++++++++++++++++----------------- src/bindings/point-wrapper.h | 26 +++---- src/bindings/range-wrapper.cc | 87 +++++++++++------------- src/bindings/range-wrapper.h | 20 +++--- 6 files changed, 162 insertions(+), 161 deletions(-) diff --git a/binding.gyp b/binding.gyp index c78ed0a2..c3cc0510 100644 --- a/binding.gyp +++ b/binding.gyp @@ -11,15 +11,15 @@ ], "sources": [ "src/bindings/bindings.cc", - "src/bindings/marker-index-wrapper.cc", - "src/bindings/patch-wrapper.cc", + # "src/bindings/marker-index-wrapper.cc", + # "src/bindings/patch-wrapper.cc", "src/bindings/point-wrapper.cc", "src/bindings/range-wrapper.cc", - "src/bindings/text-buffer-wrapper.cc", - "src/bindings/text-buffer-snapshot-wrapper.cc", - "src/bindings/text-reader.cc", - "src/bindings/string-conversion.cc", - "src/bindings/text-writer.cc", + # "src/bindings/text-buffer-wrapper.cc", + # "src/bindings/text-buffer-snapshot-wrapper.cc", + # "src/bindings/text-reader.cc", + # "src/bindings/string-conversion.cc", + # "src/bindings/text-writer.cc", ], "include_dirs": [ "src/core", diff --git a/src/bindings/bindings.cc b/src/bindings/bindings.cc index e00328f5..cd238d70 100644 --- a/src/bindings/bindings.cc +++ b/src/bindings/bindings.cc @@ -1,24 +1,40 @@ -#include "marker-index-wrapper.h" -#include "nan.h" -#include "patch-wrapper.h" +#include +// #include "marker-index-wrapper.h" +// #include "patch-wrapper.h" #include "range-wrapper.h" #include "point-wrapper.h" -#include "text-writer.h" -#include "text-reader.h" -#include "text-buffer-wrapper.h" -#include "text-buffer-snapshot-wrapper.h" +// #include "text-writer.h" +// #include "text-reader.h" +// #include "text-buffer-wrapper.h" +// #include "text-buffer-snapshot-wrapper.h" -using namespace v8; +// FIXME: Remove NAN +// using namespace v8; -void Init(Local exports) { - PointWrapper::init(); - RangeWrapper::init(); - PatchWrapper::init(exports); - MarkerIndexWrapper::init(exports); - TextBufferWrapper::init(exports); - TextWriter::init(exports); - TextReader::init(exports); - TextBufferSnapshotWrapper::init(); +// void Init(Local exports) { +// PointWrapper::init(); +// RangeWrapper::init(); +// PatchWrapper::init(exports); +// MarkerIndexWrapper::init(exports); +// TextBufferWrapper::init(exports); +// TextWriter::init(exports); +// TextReader::init(exports); +// TextBufferSnapshotWrapper::init(); +// } +// +// NAN_MODULE_WORKER_ENABLED(superstring, Init) + +// using namespace Napi; +// static Object NAPI_Init(Env env, Object exports) { +// return exports; +// } + +// NODE_MODULE_INITIALIZER(NODE_GYP_MODULE_NAME, exports); + +Napi::Object InitNapi(Napi::Env env, Napi::Object exports) { + PointWrapper::init(env, exports); + RangeWrapper::init(env, exports); + return exports; } -NAN_MODULE_WORKER_ENABLED(superstring, Init) +NODE_API_MODULE(NODE_GYP_MODULE_NAME, InitNapi); diff --git a/src/bindings/point-wrapper.cc b/src/bindings/point-wrapper.cc index 7bd159f7..eef432a6 100644 --- a/src/bindings/point-wrapper.cc +++ b/src/bindings/point-wrapper.cc @@ -1,81 +1,81 @@ #include "point-wrapper.h" #include -#include "nan.h" +#include "napi.h" -using namespace v8; +// using namespace v8; -static Nan::Persistent row_string; -static Nan::Persistent column_string; -static Nan::Persistent constructor; +// static Nan::Persistent row_string; +// static Nan::Persistent column_string; +// static Nan::Persistent constructor; +// +// static uint32_t number_from_js(Napi::Value js_number) { +// double number; +// if(js_number.IsNumber()) { +// number = js_number.ToNumber().DoubleValue(); +// } else { +// number = 0; +// } +// if (number > 0 && !std::isfinite(number)) { +// return UINT32_MAX; +// } else { +// return std::max(0.0, number); +// } +// } -static uint32_t number_from_js(Local js_number) { - double number = Nan::To(js_number).FromMaybe(0); - if (number > 0 && !std::isfinite(number)) { - return UINT32_MAX; - } else { - return std::max(0.0, number); - } -} - -optional PointWrapper::point_from_js(Local value) { - Nan::MaybeLocal maybe_object = Nan::To(value); - Local object; - if (!maybe_object.ToLocal(&object)) { - Nan::ThrowTypeError("Expected an object with 'row' and 'column' properties."); - return optional{}; - } - - Nan::MaybeLocal maybe_row = Nan::To(Nan::Get(object, Nan::New(row_string)).ToLocalChecked()); - Local js_row; - if (!maybe_row.ToLocal(&js_row)) { - Nan::ThrowTypeError("Expected an object with 'row' and 'column' properties."); - return optional{}; +std::optional PointWrapper::point_from_js(Napi::Value value) { + Napi::Env env = value.Env(); + if (!value.IsObject()) { + Napi::TypeError::New(env, "Expected an object with 'row' and 'column' properties.").ThrowAsJavaScriptException(); + return std::optional(); } + Napi::Object object = value.ToObject(); - Nan::MaybeLocal maybe_column = Nan::To(Nan::Get(object, Nan::New(column_string)).ToLocalChecked()); - Local js_column; - if (!maybe_column.ToLocal(&js_column)) { - Nan::ThrowTypeError("Expected an object with 'row' and 'column' properties."); - return optional{}; + auto js_row = object.Get("row"); + auto js_column = object.Get("column");; + if (!js_row.IsNumber() || !js_column.IsNumber()) { + Napi::TypeError::New(env, "Expected an object with 'row' and 'column' properties.").ThrowAsJavaScriptException(); + return std::optional(); } - return Point(number_from_js(js_row), number_from_js(js_column)); + return Point(js_row.ToNumber().DoubleValue(), js_column.ToNumber().DoubleValue()); } -void PointWrapper::init() { - row_string.Reset(Nan::Persistent(Nan::New("row").ToLocalChecked())); - column_string.Reset(Nan::Persistent(Nan::New("column").ToLocalChecked())); +void PointWrapper::init(Napi::Env env, Napi::Object exports) { + Napi::Function func = DefineClass(env, "Point", { + InstanceAccessor<&PointWrapper::get_row>("row"), + InstanceAccessor<&PointWrapper::get_column>("column") + }); + + Napi::FunctionReference* constructor = new Napi::FunctionReference(); + *constructor = Napi::Persistent(func); + exports.Set("Point", func); - Local constructor_template = Nan::New(construct); - constructor_template->SetClassName(Nan::New("Point").ToLocalChecked()); - constructor_template->InstanceTemplate()->SetInternalFieldCount(1); - Nan::SetAccessor(constructor_template->InstanceTemplate(), Nan::New(row_string), get_row); - Nan::SetAccessor(constructor_template->InstanceTemplate(), Nan::New(column_string), get_column); - constructor.Reset(Nan::GetFunction(constructor_template).ToLocalChecked()); } -Local PointWrapper::from_point(Point point) { - Local result; - if (Nan::New(constructor)->NewInstance(Nan::GetCurrentContext()).ToLocal(&result)) { - (new PointWrapper(point))->Wrap(result); - return result; - } else { - return Nan::Null(); +// Local PointWrapper::from_point(Point point) { +// Local result; +// if (Nan::New(constructor)->NewInstance(Nan::GetCurrentContext()).ToLocal(&result)) { +// (new PointWrapper(point))->Wrap(result); +// return result; +// } else { +// return Nan::Null(); +// } +// } +// +PointWrapper::PointWrapper(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { + auto maybe_point = PointWrapper::point_from_js(info[0]); + if(maybe_point.has_value()) { + this->point = maybe_point.value(); } } -PointWrapper::PointWrapper(Point point) : point(point) {} - -void PointWrapper::construct(const Nan::FunctionCallbackInfo &info) {} - -void PointWrapper::get_row(v8::Local property, const Nan::PropertyCallbackInfo &info) { - PointWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - Point &point = wrapper->point; - info.GetReturnValue().Set(Nan::New(point.row)); +// PointWrapper::PointWrapper(Point point) : point(point) {} +// +// void PointWrapper::construct(const Nan::FunctionCallbackInfo &info) {} +// +Napi::Value PointWrapper::get_row(const Napi::CallbackInfo &info) { + return Napi::Value::From(info.Env(), point.row); } - -void PointWrapper::get_column(v8::Local property, const Nan::PropertyCallbackInfo &info) { - PointWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - Point &point = wrapper->point; - info.GetReturnValue().Set(Nan::New(point.column)); +Napi::Value PointWrapper::get_column(const Napi::CallbackInfo &info) { + return Napi::Value::From(info.Env(), point.column); } diff --git a/src/bindings/point-wrapper.h b/src/bindings/point-wrapper.h index fc06b263..83df2ab5 100644 --- a/src/bindings/point-wrapper.h +++ b/src/bindings/point-wrapper.h @@ -1,27 +1,21 @@ #ifndef SUPERSTRING_POINT_WRAPPER_H #define SUPERSTRING_POINT_WRAPPER_H -#include "nan.h" -#include "optional.h" +#include "napi.h" #include "point.h" -class PointWrapper : public Nan::ObjectWrap { +class PointWrapper : public Napi::ObjectWrap { public: - static void init(); - static v8::Local from_point(Point point); - static optional point_from_js(v8::Local); + static void init(Napi::Env env, Napi::Object exports); -private: - PointWrapper(Point point); - - static void construct(const Nan::FunctionCallbackInfo &info); - - static void get_row(v8::Local property, - const Nan::PropertyCallbackInfo &info); - - static void get_column(v8::Local property, - const Nan::PropertyCallbackInfo &info); + static Napi::Value from_point(Point point); + static std::optional point_from_js(Napi::Value); + PointWrapper(const Napi::CallbackInfo& info); +private: + // static void construct(const Napi::Value &info); + Napi::Value get_row(const Napi::CallbackInfo &info); + Napi::Value get_column(const Napi::CallbackInfo &info); Point point; }; diff --git a/src/bindings/range-wrapper.cc b/src/bindings/range-wrapper.cc index b0aaf5ab..2b245a41 100644 --- a/src/bindings/range-wrapper.cc +++ b/src/bindings/range-wrapper.cc @@ -1,64 +1,57 @@ #include "range-wrapper.h" #include "point-wrapper.h" -#include "nan.h" +#include "napi.h" -using namespace v8; +std::optional RangeWrapper::range_from_js(Napi::Value value) { + auto env = value.Env(); -static Nan::Persistent start_string; -static Nan::Persistent end_string; -static Nan::Persistent constructor; - -optional RangeWrapper::range_from_js(Local value) { - Local object; - if (!Nan::To(value).ToLocal(&object)) { - Nan::ThrowTypeError("Expected an object with 'start' and 'end' properties."); - return optional{}; + if (!value.IsObject()) { + Napi::TypeError::New(env, "Expected an object with 'start' and 'end' properties.").ThrowAsJavaScriptException(); + return std::optional(); } + Napi::Object object = value.ToObject(); - auto start = PointWrapper::point_from_js(Nan::Get(object, Nan::New(start_string)).ToLocalChecked()); - auto end = PointWrapper::point_from_js(Nan::Get(object, Nan::New(end_string)).ToLocalChecked()); - if (start && end) { - return Range{*start, *end}; + auto start = PointWrapper::point_from_js(object.Get("start")); + auto end = PointWrapper::point_from_js(object.Get("end")); + if (start.has_value() && end.has_value()) { + return Range{start.value(), end.value()}; } else { - Nan::ThrowTypeError("Expected an object with 'start' and 'end' properties."); - return optional{}; + Napi::TypeError::New(env, "Expected an object with 'start' and 'end' properties.").ThrowAsJavaScriptException(); + return std::optional(); } } -void RangeWrapper::init() { - start_string.Reset(Nan::Persistent(Nan::New("start").ToLocalChecked())); - end_string.Reset(Nan::Persistent(Nan::New("end").ToLocalChecked())); - - Local constructor_template = Nan::New(construct); - constructor_template->SetClassName(Nan::New("Range").ToLocalChecked()); - constructor_template->InstanceTemplate()->SetInternalFieldCount(1); - Nan::SetAccessor(constructor_template->InstanceTemplate(), Nan::New(start_string), get_start); - Nan::SetAccessor(constructor_template->InstanceTemplate(), Nan::New(end_string), get_end); - constructor.Reset(Nan::GetFunction(constructor_template).ToLocalChecked()); +void RangeWrapper::init(Napi::Env env, Napi::Object exports) { + Napi::Function func = DefineClass(env, "Range", { + InstanceAccessor<&RangeWrapper::get_start>("start"), + InstanceAccessor<&RangeWrapper::get_end>("end") + }); + Napi::FunctionReference* constructor = new Napi::FunctionReference(); + *constructor = Napi::Persistent(func); + exports.Set("Range", func); } -Local RangeWrapper::from_range(Range range) { - Local result; - if (Nan::New(constructor)->NewInstance(Nan::GetCurrentContext()).ToLocal(&result)) { - (new RangeWrapper(range))->Wrap(result); - return result; - } else { - return Nan::Null(); +// Local RangeWrapper::from_range(Range range) { +// Local result; +// if (Nan::New(constructor)->NewInstance(Nan::GetCurrentContext()).ToLocal(&result)) { +// (new RangeWrapper(range))->Wrap(result); +// return result; +// } else { +// return Nan::Null(); +// } +// } +// +RangeWrapper::RangeWrapper(const Napi::CallbackInfo& info) + : Napi::ObjectWrap(info) { + auto maybe_range = RangeWrapper::range_from_js(info[0]); + if(maybe_range.has_value()) { + this->range = maybe_range.value(); } } -RangeWrapper::RangeWrapper(Range range) : range(range) {} - -void RangeWrapper::construct(const Nan::FunctionCallbackInfo &info) {} - -void RangeWrapper::get_start(v8::Local property, const Nan::PropertyCallbackInfo &info) { - RangeWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - Range &range = wrapper->range; - info.GetReturnValue().Set(PointWrapper::from_point(range.start)); +Napi::Value RangeWrapper::get_start(const Napi::CallbackInfo &info) { + return Napi::Value::From(info.Env(), PointWrapper::from_point(range.start)); } - -void RangeWrapper::get_end(v8::Local property, const Nan::PropertyCallbackInfo &info) { - RangeWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - Range &range = wrapper->range; - info.GetReturnValue().Set(PointWrapper::from_point(range.end)); +Napi::Value RangeWrapper::get_end(const Napi::CallbackInfo &info) { + return Napi::Value::From(info.Env(), PointWrapper::from_point(range.end)); } diff --git a/src/bindings/range-wrapper.h b/src/bindings/range-wrapper.h index de08dd59..bba5663f 100644 --- a/src/bindings/range-wrapper.h +++ b/src/bindings/range-wrapper.h @@ -1,24 +1,22 @@ #ifndef SUPERSTRING_RANGE_WRAPPER_H #define SUPERSTRING_RANGE_WRAPPER_H -#include "nan.h" -#include "optional.h" +#include "napi.h" #include "point.h" #include "range.h" -class RangeWrapper : public Nan::ObjectWrap { +class RangeWrapper : public Napi::ObjectWrap { public: - static void init(); - static v8::Local from_range(Range); - static optional range_from_js(v8::Local); + static void init(Napi::Env env, Napi::Object exports); + static Napi::Value from_range(Range); + static std::optional range_from_js(Napi::Value); + RangeWrapper(const Napi::CallbackInfo& info); private: - RangeWrapper(Range); - - static void construct(const Nan::FunctionCallbackInfo &); - static void get_start(v8::Local, const Nan::PropertyCallbackInfo &); - static void get_end(v8::Local, const Nan::PropertyCallbackInfo &); + // RangeWrapper(Range); + Napi::Value get_start(const Napi::CallbackInfo &info); + Napi::Value get_end(const Napi::CallbackInfo &info); Range range; }; From 6bbabeac2b39ea40303dce78363b7b2b4ea76dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Szabo?= Date: Sat, 8 Oct 2022 18:04:18 -0300 Subject: [PATCH 06/13] Finally wrapped Patch --- src/bindings/patch-wrapper.cc | 782 ++++++++++++++++++---------------- src/bindings/patch-wrapper.h | 46 +- src/bindings/point-wrapper.cc | 42 +- src/bindings/point-wrapper.h | 5 +- src/bindings/range-wrapper.cc | 4 +- src/core/patch.cc | 6 +- 6 files changed, 462 insertions(+), 423 deletions(-) diff --git a/src/bindings/patch-wrapper.cc b/src/bindings/patch-wrapper.cc index fc610aaf..6d669cb6 100644 --- a/src/bindings/patch-wrapper.cc +++ b/src/bindings/patch-wrapper.cc @@ -1,410 +1,442 @@ -#include "noop.h" +// #include "noop.h" #include "patch-wrapper.h" -#include -#include -#include +// #include +// #include +// #include #include "point-wrapper.h" -#include "string-conversion.h" - -using namespace v8; -using std::move; -using std::vector; -using std::u16string; - -static Nan::Persistent new_text_string; -static Nan::Persistent old_text_string; -static Nan::Persistent change_wrapper_constructor; -static Nan::Persistent patch_wrapper_constructor_template; -static Nan::Persistent patch_wrapper_constructor; - -static const char *InvalidSpliceMessage = "Patch does not apply"; - -class ChangeWrapper : public Nan::ObjectWrap { +// #include "string-conversion.h" +// +// using namespace v8; +// using std::vector; +// using std::u16string; +// +// static Nan::Persistent new_text_string; +// static Nan::Persistent old_text_string; +// static Nan::Persistent change_wrapper_constructor; +// static Nan::Persistent patch_wrapper_constructor_template; +// static Nan::Persistent patch_wrapper_constructor; +// +// static const char *InvalidSpliceMessage = "Patch does not apply"; + +class ChangeWrapper : public Napi::ObjectWrap { public: - static void init() { - new_text_string.Reset(Nan::New("newText").ToLocalChecked()); - old_text_string.Reset(Nan::New("oldText").ToLocalChecked()); - static Nan::Persistent old_text_string; - - Local constructor_template = Nan::New(construct); - constructor_template->SetClassName(Nan::New("Change").ToLocalChecked()); - constructor_template->InstanceTemplate()->SetInternalFieldCount(1); - const auto &instance_template = constructor_template->InstanceTemplate(); - Nan::SetAccessor(instance_template, Nan::New("oldStart").ToLocalChecked(), get_old_start); - Nan::SetAccessor(instance_template, Nan::New("newStart").ToLocalChecked(), get_new_start); - Nan::SetAccessor(instance_template, Nan::New("oldEnd").ToLocalChecked(), get_old_end); - Nan::SetAccessor(instance_template, Nan::New("newEnd").ToLocalChecked(), get_new_end); - - const auto &prototype_template = constructor_template->PrototypeTemplate(); - Nan::SetTemplate(prototype_template, Nan::New("toString").ToLocalChecked(), Nan::New(to_string), None); - change_wrapper_constructor.Reset(Nan::GetFunction(constructor_template).ToLocalChecked()); + static void init(Napi::Env env) { + // new_text_string.Reset(Nan::New("newText").ToLocalChecked()); + // old_text_string.Reset(Nan::New("oldText").ToLocalChecked()); + // static Nan::Persistent old_text_string; + // + // Local constructor_template = Nan::New(construct); + // constructor_template->SetClassName(Nan::New("Change").ToLocalChecked()); + // constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + // const auto &instance_template = constructor_template->InstanceTemplate(); + // Nan::SetAccessor(instance_template, Nan::New("oldStart").ToLocalChecked(), get_old_start); + // Nan::SetAccessor(instance_template, Nan::New("newStart").ToLocalChecked(), get_new_start); + // Nan::SetAccessor(instance_template, Nan::New("oldEnd").ToLocalChecked(), get_old_end); + // Nan::SetAccessor(instance_template, Nan::New("newEnd").ToLocalChecked(), get_new_end); + // + // const auto &prototype_template = constructor_template->PrototypeTemplate(); + // Nan::SetTemplate(prototype_template, Nan::New("toString").ToLocalChecked(), Nan::New(to_string), None); + // change_wrapper_constructor.Reset(Nan::GetFunction(constructor_template).ToLocalChecked()); } - - static Local FromChange(Patch::Change change) { - Local result; - if (Nan::NewInstance(Nan::New(change_wrapper_constructor)).ToLocal(&result)) { - (new ChangeWrapper(change))->Wrap(result); - if (change.new_text) { - Nan::Set( - result, - Nan::New(new_text_string), - string_conversion::string_to_js(change.new_text->content) - ); - } - if (change.old_text) { - Nan::Set( - result, - Nan::New(old_text_string), - string_conversion::string_to_js(change.old_text->content) - ); - } - return result; - } else { - return Nan::Null(); +// + static Napi::Value FromChange(Napi::Env env, Patch::Change change) { + Napi::Object result = Napi::Object::New(env); + result.Set("oldStart", PointWrapper::from_point(env, change.old_start)); + result.Set("oldEnd", PointWrapper::from_point(env, change.old_end)); + result.Set("newStart", PointWrapper::from_point(env, change.new_start)); + result.Set("newEnd", PointWrapper::from_point(env, change.new_end)); + + if(change.new_text) { + result.Set("newText", Napi::String::From(env, change.new_text->content)); } + if(change.old_text) { + result.Set("oldText", Napi::String::From(env, change.old_text->content)); + } + return result; + // result.Set + // Local result; + // if (Nan::NewInstance(Nan::New(change_wrapper_constructor)).ToLocal(&result)) { + // (new ChangeWrapper(change))->Wrap(result); + // if (change.new_text) { + // Nan::Set( + // result, + // Nan::New(new_text_string), + // string_conversion::string_to_js(change.new_text->content) + // ); + // } + // if (change.old_text) { + // Nan::Set( + // result, + // Nan::New(old_text_string), + // string_conversion::string_to_js(change.old_text->content) + // ); + // } + // return result; + // } else { + // return Nan::Null(); + // } } - - private: - ChangeWrapper(Patch::Change change) : change(change) {} - - static void construct(const Nan::FunctionCallbackInfo &info) {} - - static void get_old_start(v8::Local property, const Nan::PropertyCallbackInfo &info) { - Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; - info.GetReturnValue().Set(PointWrapper::from_point(change.old_start)); - } - - static void get_new_start(v8::Local property, const Nan::PropertyCallbackInfo &info) { - Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; - info.GetReturnValue().Set(PointWrapper::from_point(change.new_start)); - } - - static void get_old_end(v8::Local property, const Nan::PropertyCallbackInfo &info) { - Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; - info.GetReturnValue().Set(PointWrapper::from_point(change.old_end)); - } - - static void get_new_end(v8::Local property, const Nan::PropertyCallbackInfo &info) { - Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; - info.GetReturnValue().Set(PointWrapper::from_point(change.new_end)); - } - - static void get_preceding_old_text_length(v8::Local property, const Nan::PropertyCallbackInfo &info) { - Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; - info.GetReturnValue().Set(Nan::New(change.preceding_old_text_size)); - } - - static void get_preceding_new_text_length(v8::Local property, const Nan::PropertyCallbackInfo &info) { - Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; - info.GetReturnValue().Set(Nan::New(change.preceding_new_text_size)); - } - - static void to_string(const Nan::FunctionCallbackInfo &info) { - Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; - std::stringstream result; - result << change; - info.GetReturnValue().Set(Nan::New(result.str()).ToLocalChecked()); - } - +// +// private: +// ChangeWrapper(Patch::Change change) : change(change) {} +// +// static void construct(const Nan::FunctionCallbackInfo &info) {} +// +// static void get_old_start(v8::Local property, const Nan::PropertyCallbackInfo &info) { +// Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; +// info.GetReturnValue().Set(PointWrapper::from_point(change.old_start)); +// } +// +// static void get_new_start(v8::Local property, const Nan::PropertyCallbackInfo &info) { +// Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; +// info.GetReturnValue().Set(PointWrapper::from_point(change.new_start)); +// } +// +// static void get_old_end(v8::Local property, const Nan::PropertyCallbackInfo &info) { +// Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; +// info.GetReturnValue().Set(PointWrapper::from_point(change.old_end)); +// } +// +// static void get_new_end(v8::Local property, const Nan::PropertyCallbackInfo &info) { +// Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; +// info.GetReturnValue().Set(PointWrapper::from_point(change.new_end)); +// } +// +// static void get_preceding_old_text_length(v8::Local property, const Nan::PropertyCallbackInfo &info) { +// Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; +// info.GetReturnValue().Set(Nan::New(change.preceding_old_text_size)); +// } +// +// static void get_preceding_new_text_length(v8::Local property, const Nan::PropertyCallbackInfo &info) { +// Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; +// info.GetReturnValue().Set(Nan::New(change.preceding_new_text_size)); +// } +// +// static void to_string(const Nan::FunctionCallbackInfo &info) { +// Patch::Change &change = Nan::ObjectWrap::Unwrap(info.This())->change; +// std::stringstream result; +// result << change; +// info.GetReturnValue().Set(Nan::New(result.str()).ToLocalChecked()); +// } +// Patch::Change change; }; - -void PatchWrapper::init(Local exports) { - ChangeWrapper::init(); - - Local constructor_template_local = Nan::New(construct); - constructor_template_local->SetClassName(Nan::New("Patch").ToLocalChecked()); - Nan::SetTemplate(constructor_template_local, Nan::New("deserialize").ToLocalChecked(), Nan::New(deserialize), None); - Nan::SetTemplate(constructor_template_local, Nan::New("compose").ToLocalChecked(), Nan::New(compose), None); - constructor_template_local->InstanceTemplate()->SetInternalFieldCount(1); - const auto &prototype_template = constructor_template_local->PrototypeTemplate(); - Nan::SetTemplate(prototype_template, Nan::New("delete").ToLocalChecked(), Nan::New(noop), None); - Nan::SetTemplate(prototype_template, Nan::New("splice").ToLocalChecked(), Nan::New(splice), None); - Nan::SetTemplate(prototype_template, Nan::New("spliceOld").ToLocalChecked(), Nan::New(splice_old), None); - Nan::SetTemplate(prototype_template, Nan::New("copy").ToLocalChecked(), Nan::New(copy), None); - Nan::SetTemplate(prototype_template, Nan::New("invert").ToLocalChecked(), Nan::New(invert), None); - Nan::SetTemplate(prototype_template, Nan::New("getChanges").ToLocalChecked(), Nan::New(get_changes), None); - Nan::SetTemplate(prototype_template, Nan::New("getChangesInOldRange").ToLocalChecked(), - Nan::New(get_changes_in_old_range), None); - Nan::SetTemplate(prototype_template, Nan::New("getChangesInNewRange").ToLocalChecked(), - Nan::New(get_changes_in_new_range), None); - Nan::SetTemplate(prototype_template, Nan::New("changeForOldPosition").ToLocalChecked(), - Nan::New(change_for_old_position), None); - Nan::SetTemplate(prototype_template, Nan::New("changeForNewPosition").ToLocalChecked(), - Nan::New(change_for_new_position), None); - Nan::SetTemplate(prototype_template, Nan::New("serialize").ToLocalChecked(), Nan::New(serialize), None); - Nan::SetTemplate(prototype_template, Nan::New("getDotGraph").ToLocalChecked(), Nan::New(get_dot_graph), None); - Nan::SetTemplate(prototype_template, Nan::New("getJSON").ToLocalChecked(), Nan::New(get_json), None); - Nan::SetTemplate(prototype_template, Nan::New("rebalance").ToLocalChecked(), Nan::New(rebalance), None); - Nan::SetTemplate(prototype_template, Nan::New("getChangeCount").ToLocalChecked(), Nan::New(get_change_count), None); - Nan::SetTemplate(prototype_template, Nan::New("getBounds").ToLocalChecked(), Nan::New(get_bounds), None); - patch_wrapper_constructor_template.Reset(constructor_template_local); - patch_wrapper_constructor.Reset(Nan::GetFunction(constructor_template_local).ToLocalChecked()); - Nan::Set(exports, Nan::New("Patch").ToLocalChecked(), Nan::New(patch_wrapper_constructor)); +// +void PatchWrapper::init(Napi::Env env, Napi::Object exports) { + ChangeWrapper::init(env); + + auto func = DefineClass(env, "Patch", { + InstanceMethod<&PatchWrapper::splice>("splice"), + InstanceMethod<&PatchWrapper::get_changes>("getChanges") + // StaticMethod<&PatchWrapper::deserialize>("deserialize") + // InstanceAccessor<&RangeWrapper::get_start>("start"), + // InstanceAccessor<&RangeWrapper::get_end>("end") + }); + Napi::FunctionReference* constructor = new Napi::FunctionReference(); + *constructor = Napi::Persistent(func); + exports.Set("Patch", func); + + // Nan::SetTemplate(constructor_template_local, Nan::New("deserialize").ToLocalChecked(), Nan::New(deserialize), None); + // Nan::SetTemplate(constructor_template_local, Nan::New("compose").ToLocalChecked(), Nan::New(compose), None); + // constructor_template_local->InstanceTemplate()->SetInternalFieldCount(1); + // const auto &prototype_template = constructor_template_local->PrototypeTemplate(); + // Nan::SetTemplate(prototype_template, Nan::New("delete").ToLocalChecked(), Nan::New(noop), None); + // Nan::SetTemplate(prototype_template, Nan::New("splice").ToLocalChecked(), Nan::New(splice), None); + // Nan::SetTemplate(prototype_template, Nan::New("spliceOld").ToLocalChecked(), Nan::New(splice_old), None); + // Nan::SetTemplate(prototype_template, Nan::New("copy").ToLocalChecked(), Nan::New(copy), None); + // Nan::SetTemplate(prototype_template, Nan::New("invert").ToLocalChecked(), Nan::New(invert), None); + // Nan::SetTemplate(prototype_template, Nan::New("getChanges").ToLocalChecked(), Nan::New(get_changes), None); + // Nan::SetTemplate(prototype_template, Nan::New("getChangesInOldRange").ToLocalChecked(), + // Nan::New(get_changes_in_old_range), None); + // Nan::SetTemplate(prototype_template, Nan::New("getChangesInNewRange").ToLocalChecked(), + // Nan::New(get_changes_in_new_range), None); + // Nan::SetTemplate(prototype_template, Nan::New("changeForOldPosition").ToLocalChecked(), + // Nan::New(change_for_old_position), None); + // Nan::SetTemplate(prototype_template, Nan::New("changeForNewPosition").ToLocalChecked(), + // Nan::New(change_for_new_position), None); + // Nan::SetTemplate(prototype_template, Nan::New("serialize").ToLocalChecked(), Nan::New(serialize), None); + // Nan::SetTemplate(prototype_template, Nan::New("getDotGraph").ToLocalChecked(), Nan::New(get_dot_graph), None); + // Nan::SetTemplate(prototype_template, Nan::New("getJSON").ToLocalChecked(), Nan::New(get_json), None); + // Nan::SetTemplate(prototype_template, Nan::New("rebalance").ToLocalChecked(), Nan::New(rebalance), None); + // Nan::SetTemplate(prototype_template, Nan::New("getChangeCount").ToLocalChecked(), Nan::New(get_change_count), None); + // Nan::SetTemplate(prototype_template, Nan::New("getBounds").ToLocalChecked(), Nan::New(get_bounds), None); + // patch_wrapper_constructor_template.Reset(constructor_template_local); + // patch_wrapper_constructor.Reset(Nan::GetFunction(constructor_template_local).ToLocalChecked()); + // Nan::Set(exports, Nan::New("Patch").ToLocalChecked(), Nan::New(patch_wrapper_constructor)); } - -PatchWrapper::PatchWrapper(Patch &&patch) : patch{std::move(patch)} {} - -Local PatchWrapper::from_patch(Patch &&patch) { - Local result; - if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { - (new PatchWrapper(move(patch)))->Wrap(result); - return result; - } else { - return Nan::Null(); - } -} - -void PatchWrapper::construct(const Nan::FunctionCallbackInfo &info) { - bool merges_adjacent_changes = true; - Local options; - - if (info.Length() > 0 && Nan::To(info[0]).ToLocal(&options)) { - Local js_merge_adjacent_changes; - if (Nan::Get(options, Nan::New("mergeAdjacentChanges").ToLocalChecked()).ToLocal(&js_merge_adjacent_changes)) { - merges_adjacent_changes = Nan::To(js_merge_adjacent_changes).FromMaybe(false); - } - } - PatchWrapper *patch = new PatchWrapper(Patch{merges_adjacent_changes}); - patch->Wrap(info.This()); +// +PatchWrapper::PatchWrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) { } -void PatchWrapper::splice(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - - optional start = PointWrapper::point_from_js(info[0]); - optional deletion_extent = PointWrapper::point_from_js(info[1]); - optional insertion_extent = PointWrapper::point_from_js(info[2]); +// +// Local PatchWrapper::from_patch(Patch &&patch) { +// Local result; +// if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { +// (new PatchWrapper(move(patch)))->Wrap(result); +// return result; +// } else { +// return Nan::Null(); +// } +// } +// +// void PatchWrapper::construct(const Nan::FunctionCallbackInfo &info) { +// bool merges_adjacent_changes = true; +// Local options; +// +// if (info.Length() > 0 && Nan::To(info[0]).ToLocal(&options)) { +// Local js_merge_adjacent_changes; +// if (Nan::Get(options, Nan::New("mergeAdjacentChanges").ToLocalChecked()).ToLocal(&js_merge_adjacent_changes)) { +// merges_adjacent_changes = Nan::To(js_merge_adjacent_changes).FromMaybe(false); +// } +// } +// PatchWrapper *patch = new PatchWrapper(Patch{merges_adjacent_changes}); +// patch->Wrap(info.This()); +// } +// +// Patch from_js( +Napi::Value PatchWrapper::splice(const Napi::CallbackInfo &info) { + auto start = PointWrapper::point_from_js(info[0]); + auto deletion_extent = PointWrapper::point_from_js(info[1]); + auto insertion_extent = PointWrapper::point_from_js(info[2]); + auto env = info.Env(); if (start && deletion_extent && insertion_extent) { optional deleted_text; optional inserted_text; - if (info.Length() >= 4) { - auto deleted_string = string_conversion::string_from_js(info[3]); - if (!deleted_string) return; - deleted_text = Text{move(*deleted_string)}; + if(info[3].IsString()) { + deleted_text = optional(Text{info[3].ToString().Utf16Value()}); + } else { + return env.Undefined(); + } } if (info.Length() >= 5) { - auto inserted_string = string_conversion::string_from_js(info[4]); - if (!inserted_string) return; - inserted_text = Text{move(*inserted_string)}; + if(info[4].IsString()) { + inserted_text = optional(Text{info[4].ToString().Utf16Value()}); + } else { + return env.Undefined(); + } } if (!patch.splice( *start, *deletion_extent, *insertion_extent, - move(deleted_text), - move(inserted_text) + std::move(deleted_text), + std::move(inserted_text) )) { - Nan::ThrowError(InvalidSpliceMessage); + Napi::Error::New(env, "Patch does not apply").ThrowAsJavaScriptException(); } } + return info.Env().Undefined(); } - -void PatchWrapper::splice_old(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - - optional start = PointWrapper::point_from_js(info[0]); - optional deletion_extent = PointWrapper::point_from_js(info[1]); - optional insertion_extent = PointWrapper::point_from_js(info[2]); - - if (start && deletion_extent && insertion_extent) { - patch.splice_old(*start, *deletion_extent, *insertion_extent); - } -} - -void PatchWrapper::copy(const Nan::FunctionCallbackInfo &info) { - Local result; - if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - auto wrapper = new PatchWrapper{patch.copy()}; - wrapper->Wrap(result); - info.GetReturnValue().Set(result); - } -} - -void PatchWrapper::invert(const Nan::FunctionCallbackInfo &info) { - Local result; - if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - auto wrapper = new PatchWrapper{patch.invert()}; - wrapper->Wrap(result); - info.GetReturnValue().Set(result); - } -} - -void PatchWrapper::get_changes(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - - Local js_result = Nan::New(); +// +// void PatchWrapper::splice_old(const Nan::FunctionCallbackInfo &info) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// +// optional start = PointWrapper::point_from_js(info[0]); +// optional deletion_extent = PointWrapper::point_from_js(info[1]); +// optional insertion_extent = PointWrapper::point_from_js(info[2]); +// +// if (start && deletion_extent && insertion_extent) { +// patch.splice_old(*start, *deletion_extent, *insertion_extent); +// } +// } +// +// void PatchWrapper::copy(const Nan::FunctionCallbackInfo &info) { +// Local result; +// if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// auto wrapper = new PatchWrapper{patch.copy()}; +// wrapper->Wrap(result); +// info.GetReturnValue().Set(result); +// } +// } +// +// void PatchWrapper::invert(const Nan::FunctionCallbackInfo &info) { +// Local result; +// if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// auto wrapper = new PatchWrapper{patch.invert()}; +// wrapper->Wrap(result); +// info.GetReturnValue().Set(result); +// } +// } +// +Napi::Value PatchWrapper::get_changes(const Napi::CallbackInfo &info) { + auto env = info.Env(); + auto t = Napi::ObjectWrap::Unwrap(info.This().ToObject()); + auto &patch = t->patch; + auto js_result = Napi::Array::New(env); size_t i = 0; for (auto change : patch.get_changes()) { - Nan::Set(js_result, i++, ChangeWrapper::FromChange(change)); + js_result.Set(i++, ChangeWrapper::FromChange(env, change)); } - - info.GetReturnValue().Set(js_result); -} - -void PatchWrapper::get_changes_in_old_range(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - - optional start = PointWrapper::point_from_js(info[0]); - optional end = PointWrapper::point_from_js(info[1]); - - if (start && end) { - Local js_result = Nan::New(); - - size_t i = 0; - for (auto change : patch.grab_changes_in_old_range(*start, *end)) { - Nan::Set(js_result, i++, ChangeWrapper::FromChange(change)); - } - - info.GetReturnValue().Set(js_result); - } -} - -void PatchWrapper::get_changes_in_new_range(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - - optional start = PointWrapper::point_from_js(info[0]); - optional end = PointWrapper::point_from_js(info[1]); - - if (start && end) { - Local js_result = Nan::New(); - - size_t i = 0; - for (auto change : patch.grab_changes_in_new_range(*start, *end)) { - Nan::Set(js_result, i++, ChangeWrapper::FromChange(change)); - } - - info.GetReturnValue().Set(js_result); - } -} - -void PatchWrapper::change_for_old_position(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - optional start = PointWrapper::point_from_js(info[0]); - if (start) { - auto change = patch.grab_change_starting_before_old_position(*start); - if (change) { - info.GetReturnValue().Set(ChangeWrapper::FromChange(*change)); - } else { - info.GetReturnValue().Set(Nan::Undefined()); - } - } -} - -void PatchWrapper::change_for_new_position(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - optional start = PointWrapper::point_from_js(info[0]); - if (start) { - auto change = patch.grab_change_starting_before_new_position(*start); - if (change) { - info.GetReturnValue().Set(ChangeWrapper::FromChange(*change)); - } else { - info.GetReturnValue().Set(Nan::Undefined()); - } - } -} - -void PatchWrapper::serialize(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - - static vector output; - output.clear(); - Serializer serializer(output); - patch.serialize(serializer); - Local result; - auto maybe_result = - Nan::CopyBuffer(reinterpret_cast(output.data()), output.size()); - if (maybe_result.ToLocal(&result)) { - info.GetReturnValue().Set(result); - } -} - -void PatchWrapper::deserialize(const Nan::FunctionCallbackInfo &info) { - Local result; - if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { - if (info[0]->IsUint8Array()) { - auto *data = node::Buffer::Data(info[0]); - - static vector input; - input.assign(data, data + node::Buffer::Length(info[0])); - Deserializer deserializer(input); - PatchWrapper *wrapper = new PatchWrapper(Patch{deserializer}); - wrapper->Wrap(result); - info.GetReturnValue().Set(result); - } - } -} - -void PatchWrapper::compose(const Nan::FunctionCallbackInfo &info) { - Local result; - if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { - Local js_patches = Local::Cast(info[0]); - if (!js_patches->IsArray()) { - Nan::ThrowTypeError("Compose requires an array of patches"); - return; - } - - Patch combination; - bool left_to_right = true; - for (uint32_t i = 0, n = js_patches->Length(); i < n; i++) { - if (!Nan::Get(js_patches, i).ToLocalChecked()->IsObject()) { - Nan::ThrowTypeError("Patch.compose must be called with an array of patches"); - return; - } - - Local js_patch = Local::Cast(Nan::Get(js_patches, i).ToLocalChecked()); - if (!Nan::New(patch_wrapper_constructor_template)->HasInstance(js_patch)) { - Nan::ThrowTypeError("Patch.compose must be called with an array of patches"); - return; - } - - Patch &patch = Nan::ObjectWrap::Unwrap(js_patch)->patch; - if (!combination.combine(patch, left_to_right)) { - Nan::ThrowTypeError(InvalidSpliceMessage); - return; - } - left_to_right = !left_to_right; - } - - (new PatchWrapper{move(combination)})->Wrap(result); - info.GetReturnValue().Set(result); - } -} - -void PatchWrapper::get_dot_graph(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - std::string graph = patch.get_dot_graph(); - info.GetReturnValue().Set(Nan::New(graph).ToLocalChecked()); -} - -void PatchWrapper::get_json(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - std::string graph = patch.get_json(); - info.GetReturnValue().Set(Nan::New(graph).ToLocalChecked()); -} - -void PatchWrapper::get_change_count(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - uint32_t change_count = patch.get_change_count(); - info.GetReturnValue().Set(Nan::New(change_count)); + return js_result; } - -void PatchWrapper::get_bounds(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - auto bounds = patch.get_bounds(); - if (bounds) { - info.GetReturnValue().Set(ChangeWrapper::FromChange(*bounds)); - } -} - -void PatchWrapper::rebalance(const Nan::FunctionCallbackInfo &info) { - Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; - patch.rebalance(); +// +// void PatchWrapper::get_changes_in_old_range(const Nan::FunctionCallbackInfo &info) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// +// optional start = PointWrapper::point_from_js(info[0]); +// optional end = PointWrapper::point_from_js(info[1]); +// +// if (start && end) { +// Local js_result = Nan::New(); +// +// size_t i = 0; +// for (auto change : patch.grab_changes_in_old_range(*start, *end)) { +// Nan::Set(js_result, i++, ChangeWrapper::FromChange(change)); +// } +// +// info.GetReturnValue().Set(js_result); +// } +// } +// +// void PatchWrapper::get_changes_in_new_range(const Nan::FunctionCallbackInfo &info) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// +// optional start = PointWrapper::point_from_js(info[0]); +// optional end = PointWrapper::point_from_js(info[1]); +// +// if (start && end) { +// Local js_result = Nan::New(); +// +// size_t i = 0; +// for (auto change : patch.grab_changes_in_new_range(*start, *end)) { +// Nan::Set(js_result, i++, ChangeWrapper::FromChange(change)); +// } +// +// info.GetReturnValue().Set(js_result); +// } +// } +// +// void PatchWrapper::change_for_old_position(const Nan::FunctionCallbackInfo &info) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// optional start = PointWrapper::point_from_js(info[0]); +// if (start) { +// auto change = patch.grab_change_starting_before_old_position(*start); +// if (change) { +// info.GetReturnValue().Set(ChangeWrapper::FromChange(*change)); +// } else { +// info.GetReturnValue().Set(Nan::Undefined()); +// } +// } +// } +// +// void PatchWrapper::change_for_new_position(const Nan::FunctionCallbackInfo &info) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// optional start = PointWrapper::point_from_js(info[0]); +// if (start) { +// auto change = patch.grab_change_starting_before_new_position(*start); +// if (change) { +// info.GetReturnValue().Set(ChangeWrapper::FromChange(*change)); +// } else { +// info.GetReturnValue().Set(Nan::Undefined()); +// } +// } +// } +// +// void PatchWrapper::serialize(const Nan::FunctionCallbackInfo &info) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// +// static vector output; +// output.clear(); +// Serializer serializer(output); +// patch.serialize(serializer); +// Local result; +// auto maybe_result = +// Nan::CopyBuffer(reinterpret_cast(output.data()), output.size()); +// if (maybe_result.ToLocal(&result)) { +// info.GetReturnValue().Set(result); +// } +// } +// + +Napi::Value PatchWrapper::deserialize(const Napi::CallbackInfo &info) { + Napi::Object result; + // result.S + // // Local result; + // if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { + // if (info[0]->IsUint8Array()) { + // auto *data = node::Buffer::Data(info[0]); + // + // static vector input; + // input.assign(data, data + node::Buffer::Length(info[0])); + // Deserializer deserializer(input); + // PatchWrapper *wrapper = new PatchWrapper(Patch{deserializer}); + // wrapper->Wrap(result); + // info.GetReturnValue().Set(result); + // } + // } + return info.Env().Undefined(); } +// +// void PatchWrapper::compose(const Nan::FunctionCallbackInfo &info) { +// Local result; +// if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { +// Local js_patches = Local::Cast(info[0]); +// if (!js_patches->IsArray()) { +// Nan::ThrowTypeError("Compose requires an array of patches"); +// return; +// } +// +// Patch combination; +// bool left_to_right = true; +// for (uint32_t i = 0, n = js_patches->Length(); i < n; i++) { +// if (!Nan::Get(js_patches, i).ToLocalChecked()->IsObject()) { +// Nan::ThrowTypeError("Patch.compose must be called with an array of patches"); +// return; +// } +// +// Local js_patch = Local::Cast(Nan::Get(js_patches, i).ToLocalChecked()); +// if (!Nan::New(patch_wrapper_constructor_template)->HasInstance(js_patch)) { +// Nan::ThrowTypeError("Patch.compose must be called with an array of patches"); +// return; +// } +// +// Patch &patch = Nan::ObjectWrap::Unwrap(js_patch)->patch; +// if (!combination.combine(patch, left_to_right)) { +// Nan::ThrowTypeError(InvalidSpliceMessage); +// return; +// } +// left_to_right = !left_to_right; +// } +// +// (new PatchWrapper{move(combination)})->Wrap(result); +// info.GetReturnValue().Set(result); +// } +// } +// +// void PatchWrapper::get_dot_graph(const Nan::FunctionCallbackInfo &info) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// std::string graph = patch.get_dot_graph(); +// info.GetReturnValue().Set(Nan::New(graph).ToLocalChecked()); +// } +// +// void PatchWrapper::get_json(const Nan::FunctionCallbackInfo &info) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// std::string graph = patch.get_json(); +// info.GetReturnValue().Set(Nan::New(graph).ToLocalChecked()); +// } +// +// void PatchWrapper::get_change_count(const Nan::FunctionCallbackInfo &info) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// uint32_t change_count = patch.get_change_count(); +// info.GetReturnValue().Set(Nan::New(change_count)); +// } +// +// void PatchWrapper::get_bounds(const Nan::FunctionCallbackInfo &info) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// auto bounds = patch.get_bounds(); +// if (bounds) { +// info.GetReturnValue().Set(ChangeWrapper::FromChange(*bounds)); +// } +// } +// +// void PatchWrapper::rebalance(const Nan::FunctionCallbackInfo &info) { +// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; +// patch.rebalance(); +// } diff --git a/src/bindings/patch-wrapper.h b/src/bindings/patch-wrapper.h index 97fc6133..bd73b353 100644 --- a/src/bindings/patch-wrapper.h +++ b/src/bindings/patch-wrapper.h @@ -1,31 +1,31 @@ -#include +#include #include "patch.h" -class PatchWrapper : public Nan::ObjectWrap { +class PatchWrapper : public Napi::ObjectWrap { public: - static void init(v8::Local exports); - static v8::Local from_patch(Patch &&); + static void init(Napi::Env env, Napi::Object exports); + // static v8::Local from_patch(Patch &&); + PatchWrapper(const Napi::CallbackInfo &info); private: - PatchWrapper(Patch &&patch); - static void construct(const Nan::FunctionCallbackInfo &info); - static void splice(const Nan::FunctionCallbackInfo &info); - static void splice_old(const Nan::FunctionCallbackInfo &info); - static void copy(const Nan::FunctionCallbackInfo &info); - static void invert(const Nan::FunctionCallbackInfo &info); - static void get_changes(const Nan::FunctionCallbackInfo &info); - static void get_changes_in_old_range(const Nan::FunctionCallbackInfo &info); - static void get_changes_in_new_range(const Nan::FunctionCallbackInfo &info); - static void change_for_old_position(const Nan::FunctionCallbackInfo &info); - static void change_for_new_position(const Nan::FunctionCallbackInfo &info); - static void serialize(const Nan::FunctionCallbackInfo &info); - static void deserialize(const Nan::FunctionCallbackInfo &info); - static void compose(const Nan::FunctionCallbackInfo &info); - static void get_dot_graph(const Nan::FunctionCallbackInfo &info); - static void get_json(const Nan::FunctionCallbackInfo &info); - static void get_change_count(const Nan::FunctionCallbackInfo &info); - static void get_bounds(const Nan::FunctionCallbackInfo &info); - static void rebalance(const Nan::FunctionCallbackInfo &info); + // static void construct(const Nan::FunctionCallbackInfo &info); + Napi::Value splice(const Napi::CallbackInfo &info); + // static void splice_old(const Nan::FunctionCallbackInfo &info); + // static void copy(const Nan::FunctionCallbackInfo &info); + // static void invert(const Nan::FunctionCallbackInfo &info); + Napi::Value get_changes(const Napi::CallbackInfo &info); + // static void get_changes_in_old_range(const Nan::FunctionCallbackInfo &info); + // static void get_changes_in_new_range(const Nan::FunctionCallbackInfo &info); + // static void change_for_old_position(const Nan::FunctionCallbackInfo &info); + // static void change_for_new_position(const Nan::FunctionCallbackInfo &info); + // static void serialize(const Nan::FunctionCallbackInfo &info); + static Napi::Value deserialize(const Napi::CallbackInfo &info); + // static void compose(const Nan::FunctionCallbackInfo &info); + // static void get_dot_graph(const Nan::FunctionCallbackInfo &info); + // static void get_json(const Nan::FunctionCallbackInfo &info); + // static void get_change_count(const Nan::FunctionCallbackInfo &info); + // static void get_bounds(const Nan::FunctionCallbackInfo &info); + // static void rebalance(const Nan::FunctionCallbackInfo &info); Patch patch; }; diff --git a/src/bindings/point-wrapper.cc b/src/bindings/point-wrapper.cc index eef432a6..c1f253bf 100644 --- a/src/bindings/point-wrapper.cc +++ b/src/bindings/point-wrapper.cc @@ -1,3 +1,4 @@ +#include #include "point-wrapper.h" #include #include "napi.h" @@ -40,42 +41,45 @@ std::optional PointWrapper::point_from_js(Napi::Value value) { return Point(js_row.ToNumber().DoubleValue(), js_column.ToNumber().DoubleValue()); } +Napi::FunctionReference *PointWrapper::constructor; void PointWrapper::init(Napi::Env env, Napi::Object exports) { Napi::Function func = DefineClass(env, "Point", { InstanceAccessor<&PointWrapper::get_row>("row"), - InstanceAccessor<&PointWrapper::get_column>("column") + InstanceAccessor<&PointWrapper::get_column>("column"), + InstanceMethod<&PointWrapper::get_column>("toJSON"), }); - Napi::FunctionReference* constructor = new Napi::FunctionReference(); + constructor = new Napi::FunctionReference(); *constructor = Napi::Persistent(func); exports.Set("Point", func); +} +Napi::Value PointWrapper::from_point(Napi::Env env, Point point) { + auto wrapped = Napi::External::New(env, &point); + auto values = std::initializer_list { wrapped }; + return PointWrapper::constructor->New(values); } -// Local PointWrapper::from_point(Point point) { -// Local result; -// if (Nan::New(constructor)->NewInstance(Nan::GetCurrentContext()).ToLocal(&result)) { -// (new PointWrapper(point))->Wrap(result); -// return result; -// } else { -// return Nan::Null(); -// } -// } -// PointWrapper::PointWrapper(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { - auto maybe_point = PointWrapper::point_from_js(info[0]); - if(maybe_point.has_value()) { - this->point = maybe_point.value(); + if(info[0].IsExternal()) { + auto point = info[0].As>(); + this->point = *point.Data(); + } else { + auto maybe_point = PointWrapper::point_from_js(info[0]); + if(maybe_point.has_value()) { + this->point = maybe_point.value(); + } } } -// PointWrapper::PointWrapper(Point point) : point(point) {} -// -// void PointWrapper::construct(const Nan::FunctionCallbackInfo &info) {} -// Napi::Value PointWrapper::get_row(const Napi::CallbackInfo &info) { return Napi::Value::From(info.Env(), point.row); } Napi::Value PointWrapper::get_column(const Napi::CallbackInfo &info) { return Napi::Value::From(info.Env(), point.column); } +Napi::Value PointWrapper::to_json(const Napi::CallbackInfo &info) { + std::ostringstream json; + json << "{\"row\":" << this->point.row << ", \"column\":" << this->point.column << "}"; + return Napi::Value::From(info.Env(), json.str()); +} diff --git a/src/bindings/point-wrapper.h b/src/bindings/point-wrapper.h index 83df2ab5..371499e9 100644 --- a/src/bindings/point-wrapper.h +++ b/src/bindings/point-wrapper.h @@ -8,14 +8,15 @@ class PointWrapper : public Napi::ObjectWrap { public: static void init(Napi::Env env, Napi::Object exports); - static Napi::Value from_point(Point point); + static Napi::Value from_point(Napi::Env env, Point point); static std::optional point_from_js(Napi::Value); PointWrapper(const Napi::CallbackInfo& info); private: - // static void construct(const Napi::Value &info); + static Napi::FunctionReference *constructor; Napi::Value get_row(const Napi::CallbackInfo &info); Napi::Value get_column(const Napi::CallbackInfo &info); + Napi::Value to_json(const Napi::CallbackInfo &info); Point point; }; diff --git a/src/bindings/range-wrapper.cc b/src/bindings/range-wrapper.cc index 2b245a41..d787b818 100644 --- a/src/bindings/range-wrapper.cc +++ b/src/bindings/range-wrapper.cc @@ -50,8 +50,8 @@ RangeWrapper::RangeWrapper(const Napi::CallbackInfo& info) } Napi::Value RangeWrapper::get_start(const Napi::CallbackInfo &info) { - return Napi::Value::From(info.Env(), PointWrapper::from_point(range.start)); + return PointWrapper::from_point(info.Env(), range.start); } Napi::Value RangeWrapper::get_end(const Napi::CallbackInfo &info) { - return Napi::Value::From(info.Env(), PointWrapper::from_point(range.end)); + return PointWrapper::from_point(info.Env(), range.end); } diff --git a/src/core/patch.cc b/src/core/patch.cc index 8702f9b3..db5e8886 100644 --- a/src/core/patch.cc +++ b/src/core/patch.cc @@ -477,8 +477,10 @@ Patch Patch::invert() { // Mutations bool Patch::splice(Point new_splice_start, - Point new_deletion_extent, Point new_insertion_extent, - optional &&deleted_text, optional &&inserted_text, + Point new_deletion_extent, + Point new_insertion_extent, + optional &&deleted_text, + optional &&inserted_text, uint32_t deleted_text_size) { if (new_deletion_extent.is_zero() && new_insertion_extent.is_zero()) return true; From bf104b8a84aee8656741d668a6955d9e1162f23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Szabo?= Date: Sat, 8 Oct 2022 18:45:06 -0300 Subject: [PATCH 07/13] Patch#splice is done --- src/bindings/patch-wrapper.cc | 34 +++++++++++++++++++++------------- src/bindings/patch-wrapper.h | 2 +- src/bindings/point-wrapper.cc | 9 +++++---- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/bindings/patch-wrapper.cc b/src/bindings/patch-wrapper.cc index 6d669cb6..c0dc21fc 100644 --- a/src/bindings/patch-wrapper.cc +++ b/src/bindings/patch-wrapper.cc @@ -127,6 +127,7 @@ void PatchWrapper::init(Napi::Env env, Napi::Object exports) { auto func = DefineClass(env, "Patch", { InstanceMethod<&PatchWrapper::splice>("splice"), + InstanceMethod<&PatchWrapper::splice_old>("spliceOld"), InstanceMethod<&PatchWrapper::get_changes>("getChanges") // StaticMethod<&PatchWrapper::deserialize>("deserialize") // InstanceAccessor<&RangeWrapper::get_start>("start"), @@ -166,6 +167,13 @@ void PatchWrapper::init(Napi::Env env, Napi::Object exports) { } // PatchWrapper::PatchWrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) { + if(info[0].IsObject()) { + auto param = info[0].ToObject(); + if(param.Has("mergeAdjacentChanges")) { + bool merge_adjacent = param.Get("mergeAdjacentChanges").ToBoolean(); + this->patch = Patch{ merge_adjacent }; + } + } } // @@ -219,7 +227,7 @@ Napi::Value PatchWrapper::splice(const Napi::CallbackInfo &info) { } } - if (!patch.splice( + if (!this->patch.splice( *start, *deletion_extent, *insertion_extent, @@ -231,18 +239,18 @@ Napi::Value PatchWrapper::splice(const Napi::CallbackInfo &info) { } return info.Env().Undefined(); } -// -// void PatchWrapper::splice_old(const Nan::FunctionCallbackInfo &info) { -// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; -// -// optional start = PointWrapper::point_from_js(info[0]); -// optional deletion_extent = PointWrapper::point_from_js(info[1]); -// optional insertion_extent = PointWrapper::point_from_js(info[2]); -// -// if (start && deletion_extent && insertion_extent) { -// patch.splice_old(*start, *deletion_extent, *insertion_extent); -// } -// } + +Napi::Value PatchWrapper::splice_old(const Napi::CallbackInfo &info) { + auto start = PointWrapper::point_from_js(info[0]); + auto deletion_extent = PointWrapper::point_from_js(info[1]); + auto insertion_extent = PointWrapper::point_from_js(info[2]); + auto env = info.Env(); + + if (start && deletion_extent && insertion_extent) { + patch.splice_old(*start, *deletion_extent, *insertion_extent); + } + return env.Undefined(); +} // // void PatchWrapper::copy(const Nan::FunctionCallbackInfo &info) { // Local result; diff --git a/src/bindings/patch-wrapper.h b/src/bindings/patch-wrapper.h index bd73b353..2f3baf18 100644 --- a/src/bindings/patch-wrapper.h +++ b/src/bindings/patch-wrapper.h @@ -10,7 +10,7 @@ class PatchWrapper : public Napi::ObjectWrap { private: // static void construct(const Nan::FunctionCallbackInfo &info); Napi::Value splice(const Napi::CallbackInfo &info); - // static void splice_old(const Nan::FunctionCallbackInfo &info); + Napi::Value splice_old(const Napi::CallbackInfo &info); // static void copy(const Nan::FunctionCallbackInfo &info); // static void invert(const Nan::FunctionCallbackInfo &info); Napi::Value get_changes(const Napi::CallbackInfo &info); diff --git a/src/bindings/point-wrapper.cc b/src/bindings/point-wrapper.cc index c1f253bf..dd3cc992 100644 --- a/src/bindings/point-wrapper.cc +++ b/src/bindings/point-wrapper.cc @@ -46,7 +46,7 @@ void PointWrapper::init(Napi::Env env, Napi::Object exports) { Napi::Function func = DefineClass(env, "Point", { InstanceAccessor<&PointWrapper::get_row>("row"), InstanceAccessor<&PointWrapper::get_column>("column"), - InstanceMethod<&PointWrapper::get_column>("toJSON"), + InstanceMethod<&PointWrapper::to_json>("toJSON"), }); constructor = new Napi::FunctionReference(); @@ -79,7 +79,8 @@ Napi::Value PointWrapper::get_column(const Napi::CallbackInfo &info) { return Napi::Value::From(info.Env(), point.column); } Napi::Value PointWrapper::to_json(const Napi::CallbackInfo &info) { - std::ostringstream json; - json << "{\"row\":" << this->point.row << ", \"column\":" << this->point.column << "}"; - return Napi::Value::From(info.Env(), json.str()); + auto json = Napi::Object::New(info.Env()); + json.Set("row", this->point.row); + json.Set("column", this->point.column); + return json; } From 4fdfa3d88de12e0c08bd31efc3173cc1cc545883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Szabo?= Date: Sun, 9 Oct 2022 01:51:49 -0300 Subject: [PATCH 08/13] Reimplemented `combine` --- src/bindings/patch-wrapper.cc | 140 +++++++++++++++++++--------------- src/bindings/patch-wrapper.h | 6 +- 2 files changed, 81 insertions(+), 65 deletions(-) diff --git a/src/bindings/patch-wrapper.cc b/src/bindings/patch-wrapper.cc index c0dc21fc..4cea7d6f 100644 --- a/src/bindings/patch-wrapper.cc +++ b/src/bindings/patch-wrapper.cc @@ -1,3 +1,4 @@ +#include // #include "noop.h" #include "patch-wrapper.h" // #include @@ -121,19 +122,22 @@ class ChangeWrapper : public Napi::ObjectWrap { // Patch::Change change; }; -// + +Napi::FunctionReference *PatchWrapper::constructor; void PatchWrapper::init(Napi::Env env, Napi::Object exports) { ChangeWrapper::init(env); auto func = DefineClass(env, "Patch", { InstanceMethod<&PatchWrapper::splice>("splice"), InstanceMethod<&PatchWrapper::splice_old>("spliceOld"), - InstanceMethod<&PatchWrapper::get_changes>("getChanges") + InstanceMethod<&PatchWrapper::get_changes>("getChanges"), + InstanceMethod<&PatchWrapper::get_change_count>("getChangeCount"), + StaticMethod<&PatchWrapper::compose>("compose") // StaticMethod<&PatchWrapper::deserialize>("deserialize") // InstanceAccessor<&RangeWrapper::get_start>("start"), // InstanceAccessor<&RangeWrapper::get_end>("end") }); - Napi::FunctionReference* constructor = new Napi::FunctionReference(); + constructor = new Napi::FunctionReference(); *constructor = Napi::Persistent(func); exports.Set("Patch", func); @@ -167,7 +171,8 @@ void PatchWrapper::init(Napi::Env env, Napi::Object exports) { } // PatchWrapper::PatchWrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) { - if(info[0].IsObject()) { + if(info[0].IsExternal()) { + } else if(info[0].IsObject()) { auto param = info[0].ToObject(); if(param.Has("mergeAdjacentChanges")) { bool merge_adjacent = param.Get("mergeAdjacentChanges").ToBoolean(); @@ -363,61 +368,72 @@ Napi::Value PatchWrapper::get_changes(const Napi::CallbackInfo &info) { // } // -Napi::Value PatchWrapper::deserialize(const Napi::CallbackInfo &info) { - Napi::Object result; - // result.S - // // Local result; - // if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { - // if (info[0]->IsUint8Array()) { - // auto *data = node::Buffer::Data(info[0]); - // - // static vector input; - // input.assign(data, data + node::Buffer::Length(info[0])); - // Deserializer deserializer(input); - // PatchWrapper *wrapper = new PatchWrapper(Patch{deserializer}); - // wrapper->Wrap(result); - // info.GetReturnValue().Set(result); - // } - // } - return info.Env().Undefined(); -} -// -// void PatchWrapper::compose(const Nan::FunctionCallbackInfo &info) { -// Local result; -// if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { -// Local js_patches = Local::Cast(info[0]); -// if (!js_patches->IsArray()) { -// Nan::ThrowTypeError("Compose requires an array of patches"); -// return; -// } -// -// Patch combination; -// bool left_to_right = true; -// for (uint32_t i = 0, n = js_patches->Length(); i < n; i++) { -// if (!Nan::Get(js_patches, i).ToLocalChecked()->IsObject()) { -// Nan::ThrowTypeError("Patch.compose must be called with an array of patches"); -// return; -// } -// -// Local js_patch = Local::Cast(Nan::Get(js_patches, i).ToLocalChecked()); -// if (!Nan::New(patch_wrapper_constructor_template)->HasInstance(js_patch)) { -// Nan::ThrowTypeError("Patch.compose must be called with an array of patches"); -// return; -// } -// -// Patch &patch = Nan::ObjectWrap::Unwrap(js_patch)->patch; -// if (!combination.combine(patch, left_to_right)) { -// Nan::ThrowTypeError(InvalidSpliceMessage); -// return; -// } -// left_to_right = !left_to_right; -// } -// -// (new PatchWrapper{move(combination)})->Wrap(result); -// info.GetReturnValue().Set(result); -// } +// Napi::Value PatchWrapper::deserialize(const Napi::CallbackInfo &info) { +// Napi::Object result; +// // result.S +// // // Local result; +// // if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { +// // if (info[0]->IsUint8Array()) { +// // auto *data = node::Buffer::Data(info[0]); +// // +// // static vector input; +// // input.assign(data, data + node::Buffer::Length(info[0])); +// // Deserializer deserializer(input); +// // PatchWrapper *wrapper = new PatchWrapper(Patch{deserializer}); +// // wrapper->Wrap(result); +// // info.GetReturnValue().Set(result); +// // } +// // } +// return info.Env().Undefined(); // } // + +Napi::Value PatchWrapper::compose(const Napi::CallbackInfo &info) { + auto env = info.Env(); + if(!info[0].IsArray()) { + Napi::Error::New(env, "Compose requires an array of patches").ThrowAsJavaScriptException(); + return env.Undefined(); + } + Napi::Array js_patches = info[0].As(); + + + auto values = std::initializer_list { }; + auto return_value = PatchWrapper::constructor->New(values); + auto combination = &PatchWrapper::Unwrap(return_value)->patch; + bool left_to_right = true; + for (uint32_t i = 0, n = js_patches.Length(); i < n; i++) { + Patch patch; + auto obj = js_patches.Get(i).ToObject(); + if(!obj.Has("getChangeCount")) { + // } catch (Napi::Error _) { + Napi::Error::New(env, "Patch.compose must be called with an array of patches").ThrowAsJavaScriptException(); + return env.Undefined(); + } + patch = std::move(PatchWrapper::Unwrap(obj)->patch); + + if (!combination->combine(patch, left_to_right)) { + Napi::Error::New(env, "Patch does not apply").ThrowAsJavaScriptException(); + return env.Undefined(); + } + left_to_right = !left_to_right; + } + + return return_value; + // auto wrapped = Napi::External::New(env, &combination); + // auto values = std::initializer_list { wrapped }; + // return PatchWrapper::constructor->New(values); + + // std::cout << "SAT " << combination.get_change_count() << "\n"; + // PatchWrapper::Unwrap(w)->patch = std::move(combination); + // std::cout << "SAT " << PatchWrapper::Unwrap(w)->patch.get_change_count() << "\n"; + // auto w = Napi::External::New(env, &combination); + // return new PatchWrapper { std::move(combination) }; + // return Napi::External::New(env, &combination); + + // (new PatchWrapper{move(combination)})->Wrap(result); + // info.GetReturnValue().Set(result); +} +// // void PatchWrapper::get_dot_graph(const Nan::FunctionCallbackInfo &info) { // Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; // std::string graph = patch.get_dot_graph(); @@ -430,11 +446,11 @@ Napi::Value PatchWrapper::deserialize(const Napi::CallbackInfo &info) { // info.GetReturnValue().Set(Nan::New(graph).ToLocalChecked()); // } // -// void PatchWrapper::get_change_count(const Nan::FunctionCallbackInfo &info) { -// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; -// uint32_t change_count = patch.get_change_count(); -// info.GetReturnValue().Set(Nan::New(change_count)); -// } +Napi::Value PatchWrapper::get_change_count(const Napi::CallbackInfo &info) { + // std::cout << "PTR? " << (this->patch == nullptr) << "\n"; + std::cout << "ChangeCount " << this->patch.get_change_count() << "\n"; + return Napi::Value::From(info.Env(), this->patch.get_change_count()); +} // // void PatchWrapper::get_bounds(const Nan::FunctionCallbackInfo &info) { // Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; diff --git a/src/bindings/patch-wrapper.h b/src/bindings/patch-wrapper.h index 2f3baf18..c3ba33db 100644 --- a/src/bindings/patch-wrapper.h +++ b/src/bindings/patch-wrapper.h @@ -8,6 +8,7 @@ class PatchWrapper : public Napi::ObjectWrap { PatchWrapper(const Napi::CallbackInfo &info); private: + static Napi::FunctionReference *constructor; // static void construct(const Nan::FunctionCallbackInfo &info); Napi::Value splice(const Napi::CallbackInfo &info); Napi::Value splice_old(const Napi::CallbackInfo &info); @@ -19,11 +20,10 @@ class PatchWrapper : public Napi::ObjectWrap { // static void change_for_old_position(const Nan::FunctionCallbackInfo &info); // static void change_for_new_position(const Nan::FunctionCallbackInfo &info); // static void serialize(const Nan::FunctionCallbackInfo &info); - static Napi::Value deserialize(const Napi::CallbackInfo &info); - // static void compose(const Nan::FunctionCallbackInfo &info); + static Napi::Value compose(const Napi::CallbackInfo &info); // static void get_dot_graph(const Nan::FunctionCallbackInfo &info); // static void get_json(const Nan::FunctionCallbackInfo &info); - // static void get_change_count(const Nan::FunctionCallbackInfo &info); + Napi::Value get_change_count(const Napi::CallbackInfo &info); // static void get_bounds(const Nan::FunctionCallbackInfo &info); // static void rebalance(const Nan::FunctionCallbackInfo &info); From e61dea0b88027252af57962f55d46cf2ada2316a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Szabo?= Date: Sun, 9 Oct 2022 16:21:10 -0300 Subject: [PATCH 09/13] Removed outdated code --- test/js/patch.test.js | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/test/js/patch.test.js b/test/js/patch.test.js index 30862d84..3f4c722f 100644 --- a/test/js/patch.test.js +++ b/test/js/patch.test.js @@ -29,8 +29,6 @@ describe('Patch', function () { newEnd: {row: 1, column: 13} } ]) - - patch.delete(); }) it('honors the mergeAdjacentChanges option set to true', function () { @@ -56,8 +54,6 @@ describe('Patch', function () { newStart: {row: 0, column: 5}, newEnd: {row: 0, column: 11} } ]) - - patch.delete(); }) describe('.compose', () => { @@ -95,11 +91,6 @@ describe('Patch', function () { assert.throws(() => Patch.compose([{}, {}])) assert.throws(() => Patch.compose([1, 'a'])) - - for (let patch of patches) - patch.delete(); - - composedPatch.delete(); }) it('throws an Error if the patches do not apply', () => { @@ -169,10 +160,6 @@ describe('Patch', function () { newStart: {row: 0, column: 9}, newEnd: {row: 0, column: 14} } ]) - - patch.delete(); - invertedPatch.delete(); - patch2.delete(); }) it('can copy patches', function () { @@ -186,8 +173,6 @@ describe('Patch', function () { patch2.splice({row: 0, column: 10}, {row: 0, column: 5}, {row: 0, column: 5}) assert.deepEqual(patch2.copy().getChanges(), patch2.getChanges()) - patch.delete(); - patch2.delete(); }) it('can serialize/deserialize patches', () => { @@ -207,9 +192,6 @@ describe('Patch', function () { oldText: 'hello', newText: 'world' }]) - - patch1.delete(); - patch2.delete(); }) it('removes a change when it becomes empty', () => { @@ -368,8 +350,6 @@ describe('Patch', function () { assert.deepEqual(patchCopy2.getChanges(), patch.getChanges(), seedMessage) assert.deepEqual(patchCopy2.changeForOldPosition(oldPoint), patch.changeForOldPosition(oldPoint), seedMessage) } - - patch.delete(); } }) From 4d9e92aacf082b529f8a01f6661173c2e6804c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Szabo?= Date: Sun, 9 Oct 2022 16:21:17 -0300 Subject: [PATCH 10/13] PatchWrapper working --- src/bindings/patch-wrapper.cc | 321 +++++++++++++--------------------- src/bindings/patch-wrapper.h | 17 +- src/bindings/range-wrapper.cc | 10 -- 3 files changed, 130 insertions(+), 218 deletions(-) diff --git a/src/bindings/patch-wrapper.cc b/src/bindings/patch-wrapper.cc index 4cea7d6f..f43d7d57 100644 --- a/src/bindings/patch-wrapper.cc +++ b/src/bindings/patch-wrapper.cc @@ -128,50 +128,33 @@ void PatchWrapper::init(Napi::Env env, Napi::Object exports) { ChangeWrapper::init(env); auto func = DefineClass(env, "Patch", { + StaticMethod<&PatchWrapper::deserialize>("deserialize"), + InstanceMethod<&PatchWrapper::serialize>("serialize"), InstanceMethod<&PatchWrapper::splice>("splice"), InstanceMethod<&PatchWrapper::splice_old>("spliceOld"), + InstanceMethod<&PatchWrapper::change_for_old_position>("changeForOldPosition"), + InstanceMethod<&PatchWrapper::change_for_new_position>("changeForNewPosition"), InstanceMethod<&PatchWrapper::get_changes>("getChanges"), InstanceMethod<&PatchWrapper::get_change_count>("getChangeCount"), + InstanceMethod<&PatchWrapper::get_changes_in_old_range>("getChangesInOldRange"), + InstanceMethod<&PatchWrapper::get_changes_in_new_range>("getChangesInNewRange"), + InstanceMethod<&PatchWrapper::invert>("invert"), + InstanceMethod<&PatchWrapper::copy>("copy"), + InstanceMethod<&PatchWrapper::rebalance>("rebalance"), + InstanceMethod<&PatchWrapper::get_bounds>("getBounds"), StaticMethod<&PatchWrapper::compose>("compose") - // StaticMethod<&PatchWrapper::deserialize>("deserialize") // InstanceAccessor<&RangeWrapper::get_start>("start"), // InstanceAccessor<&RangeWrapper::get_end>("end") }); constructor = new Napi::FunctionReference(); *constructor = Napi::Persistent(func); exports.Set("Patch", func); - - // Nan::SetTemplate(constructor_template_local, Nan::New("deserialize").ToLocalChecked(), Nan::New(deserialize), None); - // Nan::SetTemplate(constructor_template_local, Nan::New("compose").ToLocalChecked(), Nan::New(compose), None); - // constructor_template_local->InstanceTemplate()->SetInternalFieldCount(1); - // const auto &prototype_template = constructor_template_local->PrototypeTemplate(); - // Nan::SetTemplate(prototype_template, Nan::New("delete").ToLocalChecked(), Nan::New(noop), None); - // Nan::SetTemplate(prototype_template, Nan::New("splice").ToLocalChecked(), Nan::New(splice), None); - // Nan::SetTemplate(prototype_template, Nan::New("spliceOld").ToLocalChecked(), Nan::New(splice_old), None); - // Nan::SetTemplate(prototype_template, Nan::New("copy").ToLocalChecked(), Nan::New(copy), None); - // Nan::SetTemplate(prototype_template, Nan::New("invert").ToLocalChecked(), Nan::New(invert), None); - // Nan::SetTemplate(prototype_template, Nan::New("getChanges").ToLocalChecked(), Nan::New(get_changes), None); - // Nan::SetTemplate(prototype_template, Nan::New("getChangesInOldRange").ToLocalChecked(), - // Nan::New(get_changes_in_old_range), None); - // Nan::SetTemplate(prototype_template, Nan::New("getChangesInNewRange").ToLocalChecked(), - // Nan::New(get_changes_in_new_range), None); - // Nan::SetTemplate(prototype_template, Nan::New("changeForOldPosition").ToLocalChecked(), - // Nan::New(change_for_old_position), None); - // Nan::SetTemplate(prototype_template, Nan::New("changeForNewPosition").ToLocalChecked(), - // Nan::New(change_for_new_position), None); - // Nan::SetTemplate(prototype_template, Nan::New("serialize").ToLocalChecked(), Nan::New(serialize), None); - // Nan::SetTemplate(prototype_template, Nan::New("getDotGraph").ToLocalChecked(), Nan::New(get_dot_graph), None); - // Nan::SetTemplate(prototype_template, Nan::New("getJSON").ToLocalChecked(), Nan::New(get_json), None); - // Nan::SetTemplate(prototype_template, Nan::New("rebalance").ToLocalChecked(), Nan::New(rebalance), None); - // Nan::SetTemplate(prototype_template, Nan::New("getChangeCount").ToLocalChecked(), Nan::New(get_change_count), None); - // Nan::SetTemplate(prototype_template, Nan::New("getBounds").ToLocalChecked(), Nan::New(get_bounds), None); - // patch_wrapper_constructor_template.Reset(constructor_template_local); - // patch_wrapper_constructor.Reset(Nan::GetFunction(constructor_template_local).ToLocalChecked()); - // Nan::Set(exports, Nan::New("Patch").ToLocalChecked(), Nan::New(patch_wrapper_constructor)); } -// + PatchWrapper::PatchWrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) { if(info[0].IsExternal()) { + auto patch = info[0].As>(); + this->patch = std::move(*patch.Data()); } else if(info[0].IsObject()) { auto param = info[0].ToObject(); if(param.Has("mergeAdjacentChanges")) { @@ -181,32 +164,6 @@ PatchWrapper::PatchWrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap PatchWrapper::from_patch(Patch &&patch) { -// Local result; -// if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { -// (new PatchWrapper(move(patch)))->Wrap(result); -// return result; -// } else { -// return Nan::Null(); -// } -// } -// -// void PatchWrapper::construct(const Nan::FunctionCallbackInfo &info) { -// bool merges_adjacent_changes = true; -// Local options; -// -// if (info.Length() > 0 && Nan::To(info[0]).ToLocal(&options)) { -// Local js_merge_adjacent_changes; -// if (Nan::Get(options, Nan::New("mergeAdjacentChanges").ToLocalChecked()).ToLocal(&js_merge_adjacent_changes)) { -// merges_adjacent_changes = Nan::To(js_merge_adjacent_changes).FromMaybe(false); -// } -// } -// PatchWrapper *patch = new PatchWrapper(Patch{merges_adjacent_changes}); -// patch->Wrap(info.This()); -// } -// -// Patch from_js( Napi::Value PatchWrapper::splice(const Napi::CallbackInfo &info) { auto start = PointWrapper::point_from_js(info[0]); auto deletion_extent = PointWrapper::point_from_js(info[1]); @@ -256,27 +213,21 @@ Napi::Value PatchWrapper::splice_old(const Napi::CallbackInfo &info) { } return env.Undefined(); } -// -// void PatchWrapper::copy(const Nan::FunctionCallbackInfo &info) { -// Local result; -// if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { -// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; -// auto wrapper = new PatchWrapper{patch.copy()}; -// wrapper->Wrap(result); -// info.GetReturnValue().Set(result); -// } -// } -// -// void PatchWrapper::invert(const Nan::FunctionCallbackInfo &info) { -// Local result; -// if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { -// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; -// auto wrapper = new PatchWrapper{patch.invert()}; -// wrapper->Wrap(result); -// info.GetReturnValue().Set(result); -// } -// } -// + +Napi::Value PatchWrapper::copy(const Napi::CallbackInfo &info) { + auto copied = patch.copy(); + auto wrapped = Napi::External::New(info.Env(), &copied); + auto result = PatchWrapper::constructor->New({ wrapped }); + return result; +} + +Napi::Value PatchWrapper::invert(const Napi::CallbackInfo &info) { + auto inverted = patch.invert(); + auto wrapped = Napi::External::New(info.Env(), &inverted); + auto result = PatchWrapper::constructor->New({ wrapped }); + return result; +} + Napi::Value PatchWrapper::get_changes(const Napi::CallbackInfo &info) { auto env = info.Env(); auto t = Napi::ObjectWrap::Unwrap(info.This().ToObject()); @@ -289,104 +240,87 @@ Napi::Value PatchWrapper::get_changes(const Napi::CallbackInfo &info) { } return js_result; } -// -// void PatchWrapper::get_changes_in_old_range(const Nan::FunctionCallbackInfo &info) { -// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; -// -// optional start = PointWrapper::point_from_js(info[0]); -// optional end = PointWrapper::point_from_js(info[1]); -// -// if (start && end) { -// Local js_result = Nan::New(); -// -// size_t i = 0; -// for (auto change : patch.grab_changes_in_old_range(*start, *end)) { -// Nan::Set(js_result, i++, ChangeWrapper::FromChange(change)); -// } -// -// info.GetReturnValue().Set(js_result); -// } -// } -// -// void PatchWrapper::get_changes_in_new_range(const Nan::FunctionCallbackInfo &info) { -// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; -// -// optional start = PointWrapper::point_from_js(info[0]); -// optional end = PointWrapper::point_from_js(info[1]); -// -// if (start && end) { -// Local js_result = Nan::New(); -// -// size_t i = 0; -// for (auto change : patch.grab_changes_in_new_range(*start, *end)) { -// Nan::Set(js_result, i++, ChangeWrapper::FromChange(change)); -// } -// -// info.GetReturnValue().Set(js_result); -// } -// } -// -// void PatchWrapper::change_for_old_position(const Nan::FunctionCallbackInfo &info) { -// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; -// optional start = PointWrapper::point_from_js(info[0]); -// if (start) { -// auto change = patch.grab_change_starting_before_old_position(*start); -// if (change) { -// info.GetReturnValue().Set(ChangeWrapper::FromChange(*change)); -// } else { -// info.GetReturnValue().Set(Nan::Undefined()); -// } -// } -// } -// -// void PatchWrapper::change_for_new_position(const Nan::FunctionCallbackInfo &info) { -// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; -// optional start = PointWrapper::point_from_js(info[0]); -// if (start) { -// auto change = patch.grab_change_starting_before_new_position(*start); -// if (change) { -// info.GetReturnValue().Set(ChangeWrapper::FromChange(*change)); -// } else { -// info.GetReturnValue().Set(Nan::Undefined()); -// } -// } -// } -// -// void PatchWrapper::serialize(const Nan::FunctionCallbackInfo &info) { -// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; -// -// static vector output; -// output.clear(); -// Serializer serializer(output); -// patch.serialize(serializer); -// Local result; -// auto maybe_result = -// Nan::CopyBuffer(reinterpret_cast(output.data()), output.size()); -// if (maybe_result.ToLocal(&result)) { -// info.GetReturnValue().Set(result); -// } -// } -// -// Napi::Value PatchWrapper::deserialize(const Napi::CallbackInfo &info) { -// Napi::Object result; -// // result.S -// // // Local result; -// // if (Nan::NewInstance(Nan::New(patch_wrapper_constructor)).ToLocal(&result)) { -// // if (info[0]->IsUint8Array()) { -// // auto *data = node::Buffer::Data(info[0]); -// // -// // static vector input; -// // input.assign(data, data + node::Buffer::Length(info[0])); -// // Deserializer deserializer(input); -// // PatchWrapper *wrapper = new PatchWrapper(Patch{deserializer}); -// // wrapper->Wrap(result); -// // info.GetReturnValue().Set(result); -// // } -// // } -// return info.Env().Undefined(); -// } -// +Napi::Value PatchWrapper::get_changes_in_old_range(const Napi::CallbackInfo &info) { + auto env = info.Env(); + auto start = PointWrapper::point_from_js(info[0]); + auto end = PointWrapper::point_from_js(info[1]); + if (start.has_value() && end.has_value()) { + auto changes = patch.grab_changes_in_old_range(start.value(), end.value()); + auto js_result = Napi::Array::New(env, changes.size()); + size_t i = 0; + for (auto change : changes) { + js_result.Set(i++, ChangeWrapper::FromChange(env, change)); + } + return js_result; + } else { + return env.Undefined(); + } +} + +Napi::Value PatchWrapper::get_changes_in_new_range(const Napi::CallbackInfo &info) { + auto env = info.Env(); + auto start = PointWrapper::point_from_js(info[0]); + auto end = PointWrapper::point_from_js(info[1]); + if (start.has_value() && end.has_value()) { + auto changes = patch.grab_changes_in_new_range(start.value(), end.value()); + auto js_result = Napi::Array::New(env, changes.size()); + size_t i = 0; + for (auto change : changes) { + js_result.Set(i++, ChangeWrapper::FromChange(env, change)); + } + return js_result; + } else { + return env.Undefined(); + } +} + +Napi::Value PatchWrapper::change_for_old_position(const Napi::CallbackInfo &info) { + auto start = PointWrapper::point_from_js(info[0]); + if (start.has_value()) { + auto change = patch.grab_change_starting_before_old_position(start.value()); + if (change) { + return ChangeWrapper::FromChange(info.Env(), *change); + } + } + return info.Env().Undefined(); +} + +Napi::Value PatchWrapper::change_for_new_position(const Napi::CallbackInfo &info) { + auto start = PointWrapper::point_from_js(info[0]); + if (start.has_value()) { + auto change = patch.grab_change_starting_before_new_position(start.value()); + if (change) { + return ChangeWrapper::FromChange(info.Env(), *change); + } + } + return info.Env().Undefined(); +} + +Napi::Value PatchWrapper::serialize(const Napi::CallbackInfo &info) { + static std::vector output; + output.clear(); + Serializer serializer(output); + patch.serialize(serializer); + auto result = Napi::Buffer::Copy(info.Env(), output.data(), output.size()); + return result; +} + + +Napi::Value PatchWrapper::deserialize(const Napi::CallbackInfo &info) { + if(info[0].IsBuffer()) { + auto buffer = info[0].As>(); + auto *data = buffer.Data(); + static std::vector input; + input.assign(data, data + buffer.Length()); + Deserializer deserializer(input); + auto new_patch = Patch{deserializer}; + auto wrapped = Napi::External::New(info.Env(), &new_patch); + return PatchWrapper::constructor->New({ wrapped }); + } else { + return info.Env().Undefined(); + } +} Napi::Value PatchWrapper::compose(const Napi::CallbackInfo &info) { auto env = info.Env(); @@ -419,19 +353,6 @@ Napi::Value PatchWrapper::compose(const Napi::CallbackInfo &info) { } return return_value; - // auto wrapped = Napi::External::New(env, &combination); - // auto values = std::initializer_list { wrapped }; - // return PatchWrapper::constructor->New(values); - - // std::cout << "SAT " << combination.get_change_count() << "\n"; - // PatchWrapper::Unwrap(w)->patch = std::move(combination); - // std::cout << "SAT " << PatchWrapper::Unwrap(w)->patch.get_change_count() << "\n"; - // auto w = Napi::External::New(env, &combination); - // return new PatchWrapper { std::move(combination) }; - // return Napi::External::New(env, &combination); - - // (new PatchWrapper{move(combination)})->Wrap(result); - // info.GetReturnValue().Set(result); } // // void PatchWrapper::get_dot_graph(const Nan::FunctionCallbackInfo &info) { @@ -447,20 +368,18 @@ Napi::Value PatchWrapper::compose(const Napi::CallbackInfo &info) { // } // Napi::Value PatchWrapper::get_change_count(const Napi::CallbackInfo &info) { - // std::cout << "PTR? " << (this->patch == nullptr) << "\n"; - std::cout << "ChangeCount " << this->patch.get_change_count() << "\n"; return Napi::Value::From(info.Env(), this->patch.get_change_count()); } // -// void PatchWrapper::get_bounds(const Nan::FunctionCallbackInfo &info) { -// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; -// auto bounds = patch.get_bounds(); -// if (bounds) { -// info.GetReturnValue().Set(ChangeWrapper::FromChange(*bounds)); -// } -// } -// -// void PatchWrapper::rebalance(const Nan::FunctionCallbackInfo &info) { -// Patch &patch = Nan::ObjectWrap::Unwrap(info.This())->patch; -// patch.rebalance(); -// } +Napi::Value PatchWrapper::get_bounds(const Napi::CallbackInfo &info) { + auto bounds = patch.get_bounds(); + if (bounds) { + return ChangeWrapper::FromChange(info.Env(), *bounds); + } + return info.Env().Undefined(); +} + +Napi::Value PatchWrapper::rebalance(const Napi::CallbackInfo &info) { + patch.rebalance(); + return info.Env().Undefined(); +} diff --git a/src/bindings/patch-wrapper.h b/src/bindings/patch-wrapper.h index c3ba33db..1c82da0b 100644 --- a/src/bindings/patch-wrapper.h +++ b/src/bindings/patch-wrapper.h @@ -13,19 +13,22 @@ class PatchWrapper : public Napi::ObjectWrap { Napi::Value splice(const Napi::CallbackInfo &info); Napi::Value splice_old(const Napi::CallbackInfo &info); // static void copy(const Nan::FunctionCallbackInfo &info); - // static void invert(const Nan::FunctionCallbackInfo &info); + Napi::Value copy(const Napi::CallbackInfo &info); + Napi::Value invert(const Napi::CallbackInfo &info); Napi::Value get_changes(const Napi::CallbackInfo &info); - // static void get_changes_in_old_range(const Nan::FunctionCallbackInfo &info); - // static void get_changes_in_new_range(const Nan::FunctionCallbackInfo &info); - // static void change_for_old_position(const Nan::FunctionCallbackInfo &info); + Napi::Value get_changes_in_old_range(const Napi::CallbackInfo &info); + Napi::Value get_changes_in_new_range(const Napi::CallbackInfo &info); + Napi::Value change_for_old_position(const Napi::CallbackInfo &info); + Napi::Value change_for_new_position(const Napi::CallbackInfo &info); // static void change_for_new_position(const Nan::FunctionCallbackInfo &info); - // static void serialize(const Nan::FunctionCallbackInfo &info); + static Napi::Value deserialize(const Napi::CallbackInfo &info); + Napi::Value serialize(const Napi::CallbackInfo &info); static Napi::Value compose(const Napi::CallbackInfo &info); // static void get_dot_graph(const Nan::FunctionCallbackInfo &info); // static void get_json(const Nan::FunctionCallbackInfo &info); Napi::Value get_change_count(const Napi::CallbackInfo &info); - // static void get_bounds(const Nan::FunctionCallbackInfo &info); - // static void rebalance(const Nan::FunctionCallbackInfo &info); + Napi::Value get_bounds(const Napi::CallbackInfo &info); + Napi::Value rebalance(const Napi::CallbackInfo &info); Patch patch; }; diff --git a/src/bindings/range-wrapper.cc b/src/bindings/range-wrapper.cc index d787b818..8b968893 100644 --- a/src/bindings/range-wrapper.cc +++ b/src/bindings/range-wrapper.cc @@ -31,16 +31,6 @@ void RangeWrapper::init(Napi::Env env, Napi::Object exports) { exports.Set("Range", func); } -// Local RangeWrapper::from_range(Range range) { -// Local result; -// if (Nan::New(constructor)->NewInstance(Nan::GetCurrentContext()).ToLocal(&result)) { -// (new RangeWrapper(range))->Wrap(result); -// return result; -// } else { -// return Nan::Null(); -// } -// } -// RangeWrapper::RangeWrapper(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { auto maybe_range = RangeWrapper::range_from_js(info[0]); From bb23f3797ba58a121f64e8408adddd62f6e9d9f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Szabo?= Date: Tue, 11 Oct 2022 02:07:49 -0300 Subject: [PATCH 11/13] Migrating part of MarkerIndexWrapper to NAPI --- src/bindings/bindings.cc | 6 +- src/bindings/marker-index-wrapper.cc | 583 ++++++++++++++------------- src/bindings/marker-index-wrapper.h | 66 +-- src/bindings/patch-wrapper.cc | 16 +- src/bindings/point-wrapper.cc | 55 ++- src/bindings/point-wrapper.h | 4 +- src/bindings/range-wrapper.cc | 8 +- 7 files changed, 377 insertions(+), 361 deletions(-) diff --git a/src/bindings/bindings.cc b/src/bindings/bindings.cc index cd238d70..29308002 100644 --- a/src/bindings/bindings.cc +++ b/src/bindings/bindings.cc @@ -1,6 +1,6 @@ #include -// #include "marker-index-wrapper.h" -// #include "patch-wrapper.h" +#include "marker-index-wrapper.h" +#include "patch-wrapper.h" #include "range-wrapper.h" #include "point-wrapper.h" // #include "text-writer.h" @@ -34,6 +34,8 @@ Napi::Object InitNapi(Napi::Env env, Napi::Object exports) { PointWrapper::init(env, exports); RangeWrapper::init(env, exports); + PatchWrapper::init(env, exports); + MarkerIndexWrapper::init(env, exports); return exports; } diff --git a/src/bindings/marker-index-wrapper.cc b/src/bindings/marker-index-wrapper.cc index f53853e3..58ae81a2 100644 --- a/src/bindings/marker-index-wrapper.cc +++ b/src/bindings/marker-index-wrapper.cc @@ -1,384 +1,401 @@ #include "marker-index-wrapper.h" #include #include "marker-index.h" -#include "nan.h" -#include "noop.h" #include "optional.h" #include "point-wrapper.h" #include "range.h" -using namespace v8; -using std::unordered_map; - -static Nan::Persistent marker_index_constructor_template; -static Nan::Persistent start_string; -static Nan::Persistent end_string; -static Nan::Persistent touch_string; -static Nan::Persistent inside_string; -static Nan::Persistent overlap_string; -static Nan::Persistent surround_string; -static Nan::Persistent containing_start_string; -static Nan::Persistent boundaries_string; -static Nan::Persistent position_string; -static Nan::Persistent starting_string; -static Nan::Persistent ending_string; - -void MarkerIndexWrapper::init(Local exports) { - Local constructor_template = Nan::New(construct); - constructor_template->SetClassName(Nan::New("MarkerIndex").ToLocalChecked()); - constructor_template->InstanceTemplate()->SetInternalFieldCount(1); - - const auto &prototype_template = constructor_template->PrototypeTemplate(); - - Nan::SetTemplate(prototype_template, Nan::New("delete").ToLocalChecked(), Nan::New(noop), None); - Nan::SetTemplate(prototype_template, Nan::New("generateRandomNumber").ToLocalChecked(), - Nan::New(generate_random_number), None); - Nan::SetTemplate(prototype_template, Nan::New("insert").ToLocalChecked(), Nan::New(insert), None); - Nan::SetTemplate(prototype_template, Nan::New("setExclusive").ToLocalChecked(), Nan::New(set_exclusive), None); - Nan::SetTemplate(prototype_template, Nan::New("remove").ToLocalChecked(), Nan::New(remove), None); - Nan::SetTemplate(prototype_template, Nan::New("has").ToLocalChecked(), Nan::New(has), None); - Nan::SetTemplate(prototype_template, Nan::New("splice").ToLocalChecked(), Nan::New(splice), None); - Nan::SetTemplate(prototype_template, Nan::New("getStart").ToLocalChecked(), Nan::New(get_start), None); - Nan::SetTemplate(prototype_template, Nan::New("getEnd").ToLocalChecked(), Nan::New(get_end), None); - Nan::SetTemplate(prototype_template, Nan::New("getRange").ToLocalChecked(), Nan::New(get_range), None); - Nan::SetTemplate(prototype_template, Nan::New("compare").ToLocalChecked(), Nan::New(compare), None); - Nan::SetTemplate(prototype_template, Nan::New("findIntersecting").ToLocalChecked(), - Nan::New(find_intersecting), None); - Nan::SetTemplate(prototype_template, Nan::New("findContaining").ToLocalChecked(), - Nan::New(find_containing), None); - Nan::SetTemplate(prototype_template, Nan::New("findContainedIn").ToLocalChecked(), - Nan::New(find_contained_in), None); - Nan::SetTemplate(prototype_template, Nan::New("findStartingIn").ToLocalChecked(), - Nan::New(find_starting_in), None); - Nan::SetTemplate(prototype_template, Nan::New("findStartingAt").ToLocalChecked(), - Nan::New(find_starting_at), None); - Nan::SetTemplate(prototype_template, Nan::New("findEndingIn").ToLocalChecked(), Nan::New(find_ending_in), None); - Nan::SetTemplate(prototype_template, Nan::New("findEndingAt").ToLocalChecked(), Nan::New(find_ending_at), None); - Nan::SetTemplate(prototype_template, Nan::New("findBoundariesAfter").ToLocalChecked(), Nan::New(find_boundaries_after), None); - Nan::SetTemplate(prototype_template, Nan::New("dump").ToLocalChecked(), Nan::New(dump), None); - - start_string.Reset(Nan::Persistent(Nan::New("start").ToLocalChecked())); - end_string.Reset(Nan::Persistent(Nan::New("end").ToLocalChecked())); - touch_string.Reset(Nan::Persistent(Nan::New("touch").ToLocalChecked())); - inside_string.Reset(Nan::Persistent(Nan::New("inside").ToLocalChecked())); - overlap_string.Reset(Nan::Persistent(Nan::New("overlap").ToLocalChecked())); - surround_string.Reset(Nan::Persistent(Nan::New("surround").ToLocalChecked())); - containing_start_string.Reset(Nan::Persistent(Nan::New("containingStart").ToLocalChecked())); - boundaries_string.Reset(Nan::Persistent(Nan::New("boundaries").ToLocalChecked())); - position_string.Reset(Nan::Persistent(Nan::New("position").ToLocalChecked())); - starting_string.Reset(Nan::Persistent(Nan::New("starting").ToLocalChecked())); - ending_string.Reset(Nan::Persistent(Nan::New("ending").ToLocalChecked())); - - marker_index_constructor_template.Reset(constructor_template); - Nan::Set(exports, Nan::New("MarkerIndex").ToLocalChecked(), Nan::GetFunction(constructor_template).ToLocalChecked()); +// using namespace v8; +// using std::unordered_map; +// +// static Nan::Persistent marker_index_constructor_template; +// static Nan::Persistent start_string; +// static Nan::Persistent end_string; +// static Nan::Persistent touch_string; +// static Nan::Persistent inside_string; +// static Nan::Persistent overlap_string; +// static Nan::Persistent surround_string; +// static Nan::Persistent containing_start_string; +// static Nan::Persistent boundaries_string; +// static Nan::Persistent position_string; +// static Nan::Persistent starting_string; +// static Nan::Persistent ending_string; +// +Napi::FunctionReference *MarkerIndexWrapper::constructor; + +void MarkerIndexWrapper::init(Napi::Env env, Napi::Object exports) { + Napi::Function func = DefineClass(env, "MarkerIndex", { + InstanceMethod<&MarkerIndexWrapper::splice>("splice"), + InstanceMethod<&MarkerIndexWrapper::has>("has"), + InstanceMethod<&MarkerIndexWrapper::insert>("insert"), + InstanceMethod<&MarkerIndexWrapper::compare>("compare"), + InstanceMethod<&MarkerIndexWrapper::get_start>("getStart"), + InstanceMethod<&MarkerIndexWrapper::get_end>("getEnd"), + InstanceMethod<&MarkerIndexWrapper::get_range>("getRange"), + InstanceMethod<&MarkerIndexWrapper::set_exclusive>("setExclusive"), + InstanceMethod<&MarkerIndexWrapper::find_starting_at>("findStartingAt"), + InstanceMethod<&MarkerIndexWrapper::find_starting_in>("findStartingIn"), + InstanceMethod<&MarkerIndexWrapper::find_ending_at>("findEndingAt"), + InstanceMethod<&MarkerIndexWrapper::find_ending_in>("findEndingIn"), + InstanceMethod<&MarkerIndexWrapper::remove>("remove"), + InstanceMethod<&MarkerIndexWrapper::dump>("dump"), + InstanceMethod<&MarkerIndexWrapper::find_intersecting>("findIntersecting"), + InstanceMethod<&MarkerIndexWrapper::find_containing>("findContaining"), + }); + + constructor = new Napi::FunctionReference(); + *constructor = Napi::Persistent(func); + exports.Set("MarkerIndex", func); } -MarkerIndex *MarkerIndexWrapper::from_js(Local value) { - auto js_marker_index = Local::Cast(value); - if (!Nan::New(marker_index_constructor_template)->HasInstance(js_marker_index)) { - return nullptr; - } - return &Nan::ObjectWrap::Unwrap(js_marker_index)->marker_index; -} - -void MarkerIndexWrapper::construct(const Nan::FunctionCallbackInfo &info) { - auto seed = Nan::To(info[0]); - MarkerIndexWrapper *marker_index = new MarkerIndexWrapper(seed.IsJust() ? seed.FromJust() : 0u); - marker_index->Wrap(info.This()); +#include +MarkerIndexWrapper::MarkerIndexWrapper(const Napi::CallbackInfo& info) + : Napi::ObjectWrap(info) { + // if(info[0].IsNumber()) { + // auto seed = info[0].ToNumber(); + // auto index = new MarkerIndex { seed.Uint32Value() }; + // this->marker_index = *index; + // } } -void MarkerIndexWrapper::generate_random_number(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - int random = wrapper->marker_index.generate_random_number(); - info.GetReturnValue().Set(Nan::New(random)); +Napi::Value MarkerIndexWrapper::splice(const Napi::CallbackInfo &info) { + auto env = info.Env(); + optional start = PointWrapper::point_from_js(info[0]); + optional old_extent = PointWrapper::point_from_js(info[1]); + optional new_extent = PointWrapper::point_from_js(info[2]); + if (start && old_extent && new_extent) { + MarkerIndex::SpliceResult result = marker_index.splice( + *start, *old_extent, *new_extent + ); + + auto invalidated = Napi::Object::New(env); + invalidated.Set("touch", marker_ids_set_to_js(env, result.touch)); + invalidated.Set("inside", marker_ids_set_to_js(env, result.inside)); + invalidated.Set("overlap", marker_ids_set_to_js(env, result.overlap)); + invalidated.Set("surround", marker_ids_set_to_js(env, result.surround)); + return invalidated; + } else { + return env.Undefined(); + } } -Local MarkerIndexWrapper::marker_ids_set_to_js(const MarkerIndex::MarkerIdSet &marker_ids) { - Isolate *isolate = v8::Isolate::GetCurrent(); - Local context = isolate->GetCurrentContext(); - Local js_set = v8::Set::New(isolate); - +// MarkerIndex *MarkerIndexWrapper::from_js(Local value) { +// auto js_marker_index = Local::Cast(value); +// if (!Nan::New(marker_index_constructor_template)->HasInstance(js_marker_index)) { +// return nullptr; +// } +// return &Nan::ObjectWrap::Unwrap(js_marker_index)->marker_index; +// } +// +// void MarkerIndexWrapper::construct(const Nan::FunctionCallbackInfo &info) { +// auto seed = Nan::To(info[0]); +// MarkerIndexWrapper *marker_index = new MarkerIndexWrapper(seed.IsJust() ? seed.FromJust() : 0u); +// marker_index->Wrap(info.This()); +// } +// +// void MarkerIndexWrapper::generate_random_number(const Nan::FunctionCallbackInfo &info) { +// MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); +// int random = wrapper->marker_index.generate_random_number(); +// info.GetReturnValue().Set(Nan::New(random)); +// } +// +Napi::Object MarkerIndexWrapper::marker_ids_set_to_js(Napi::Env env, const MarkerIndex::MarkerIdSet &marker_ids) { + auto js_set = env.RunScript("new Set()").ToObject(); + auto add_to_set = js_set.Get("add").As(); for (MarkerIndex::MarkerId id : marker_ids) { - // Not sure why Set::Add warns if we don't use its return value, but - // just doing it to avoid the warning. - js_set = js_set->Add(context, Nan::New(id)).ToLocalChecked(); + auto params = std::initializer_list { Napi::Number::New(env, id) }; + add_to_set.Call(js_set, params); } - return js_set; } - -Local MarkerIndexWrapper::marker_ids_vector_to_js(const std::vector &marker_ids) { - Local js_array = Nan::New(marker_ids.size()); - - Isolate *isolate = v8::Isolate::GetCurrent(); - Local context = isolate->GetCurrentContext(); - for (size_t i = 0; i < marker_ids.size(); i++) { - js_array->Set(context, i, Nan::New(marker_ids[i])); - } - return js_array; -} - -Local MarkerIndexWrapper::snapshot_to_js(const unordered_map &snapshot) { - Local result_object = Nan::New(); - Isolate *isolate = v8::Isolate::GetCurrent(); - Local context = isolate->GetCurrentContext(); - for (auto &pair : snapshot) { - Local range = Nan::New(); - range->Set(context, Nan::New(start_string), PointWrapper::from_point(pair.second.start)); - range->Set(context, Nan::New(end_string), PointWrapper::from_point(pair.second.end)); - result_object->Set(context, Nan::New(pair.first), range); - } - return result_object; -} - -optional MarkerIndexWrapper::marker_id_from_js(Local value) { - auto result = unsigned_from_js(value); - if (result) { - return *result; +// +// Local MarkerIndexWrapper::marker_ids_vector_to_js(const std::vector &marker_ids) { +// Local js_array = Nan::New(marker_ids.size()); +// +// Isolate *isolate = v8::Isolate::GetCurrent(); +// Local context = isolate->GetCurrentContext(); +// for (size_t i = 0; i < marker_ids.size(); i++) { +// js_array->Set(context, i, Nan::New(marker_ids[i])); +// } +// return js_array; +// } +// + +optional MarkerIndexWrapper::marker_id_from_js(Napi::Value value) { + if(!value.IsNumber() || value.ToNumber().DoubleValue() < 0) { + Napi::TypeError::New(value.Env(), "Expected an non-negative integer value").ThrowAsJavaScriptException(); + return optional(); } else { - return optional{}; - } -} - -optional MarkerIndexWrapper::unsigned_from_js(Local value) { - Nan::Maybe result = Nan::To(value); - if (!result.IsJust()) { - Nan::ThrowTypeError("Expected an non-negative integer value."); - return optional{}; + auto result = value.ToNumber(); + return optional(result.Uint32Value()); } - return result.FromJust(); } -optional MarkerIndexWrapper::bool_from_js(Local value) { - Nan::MaybeLocal maybe_boolean = Nan::To(value); - Local boolean; - if (!maybe_boolean.ToLocal(&boolean)) { - Nan::ThrowTypeError("Expected an boolean."); - return optional{}; - } - - return boolean->Value(); -} - -void MarkerIndexWrapper::insert(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - +Napi::Value MarkerIndexWrapper::insert(const Napi::CallbackInfo &info) { + auto env = info.Env(); optional id = marker_id_from_js(info[0]); optional start = PointWrapper::point_from_js(info[1]); optional end = PointWrapper::point_from_js(info[2]); if (id && start && end) { - wrapper->marker_index.insert(*id, *start, *end); + marker_index.insert(*id, *start, *end); } + return env.Undefined(); } -void MarkerIndexWrapper::set_exclusive(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - +Napi::Value MarkerIndexWrapper::set_exclusive(const Napi::CallbackInfo &info) { + auto env = info.Env(); optional id = marker_id_from_js(info[0]); - optional exclusive = bool_from_js(info[1]); - if (id && exclusive) { - wrapper->marker_index.set_exclusive(*id, *exclusive); + if (id && info[1].IsBoolean()) { + marker_index.set_exclusive(*id, info[1].ToBoolean().Value()); } + return env.Undefined(); } -void MarkerIndexWrapper::remove(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - +Napi::Value MarkerIndexWrapper::remove(const Napi::CallbackInfo &info) { + auto env = info.Env(); optional id = marker_id_from_js(info[0]); if (id) { - wrapper->marker_index.remove(*id); + marker_index.remove(*id); } + return env.Undefined(); } - -void MarkerIndexWrapper::has(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - - optional id = marker_id_from_js(info[0]); +// +Napi::Value MarkerIndexWrapper::has(const Napi::CallbackInfo &info) { + auto env = info.Env(); + auto id = marker_id_from_js(info[0]); if (id) { - bool result = wrapper->marker_index.has(*id); - info.GetReturnValue().Set(Nan::New(result)); - } -} - -void MarkerIndexWrapper::splice(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - - optional start = PointWrapper::point_from_js(info[0]); - optional old_extent = PointWrapper::point_from_js(info[1]); - optional new_extent = PointWrapper::point_from_js(info[2]); - if (start && old_extent && new_extent) { - MarkerIndex::SpliceResult result = wrapper->marker_index.splice(*start, *old_extent, *new_extent); - - Local invalidated = Nan::New(); - Nan::Set(invalidated, Nan::New(touch_string), marker_ids_set_to_js(result.touch)); - Nan::Set(invalidated, Nan::New(inside_string), marker_ids_set_to_js(result.inside)); - Nan::Set(invalidated, Nan::New(inside_string), marker_ids_set_to_js(result.inside)); - Nan::Set(invalidated, Nan::New(overlap_string), marker_ids_set_to_js(result.overlap)); - Nan::Set(invalidated, Nan::New(surround_string), marker_ids_set_to_js(result.surround)); - info.GetReturnValue().Set(invalidated); + bool result = marker_index.has(*id); + return Napi::Boolean::New(env, result); + } else { + return env.Undefined(); } } -void MarkerIndexWrapper::get_start(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - +Napi::Value MarkerIndexWrapper::get_start(const Napi::CallbackInfo &info) { + auto env = info.Env(); optional id = marker_id_from_js(info[0]); if (id) { - Point result = wrapper->marker_index.get_start(*id); - info.GetReturnValue().Set(PointWrapper::from_point(result)); + Range range = marker_index.get_range(*id); + return PointWrapper::from_point(env, range.start); + } else { + return env.Undefined(); } } -void MarkerIndexWrapper::get_end(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - +Napi::Value MarkerIndexWrapper::get_end(const Napi::CallbackInfo &info) { + auto env = info.Env(); optional id = marker_id_from_js(info[0]); if (id) { - Point result = wrapper->marker_index.get_end(*id); - info.GetReturnValue().Set(PointWrapper::from_point(result)); + Range range = marker_index.get_range(*id); + return PointWrapper::from_point(env, range.end); + } else { + return env.Undefined(); } } -void MarkerIndexWrapper::get_range(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - +Napi::Value MarkerIndexWrapper::get_range(const Napi::CallbackInfo &info) { + auto env = info.Env(); optional id = marker_id_from_js(info[0]); if (id) { - Range range = wrapper->marker_index.get_range(*id); - auto result = Nan::New(); - Nan::Set(result, Nan::New(start_string), PointWrapper::from_point(range.start)); - Nan::Set(result, Nan::New(end_string), PointWrapper::from_point(range.end)); - info.GetReturnValue().Set(result); + Range range = marker_index.get_range(*id); + auto result = Napi::Object::New(env); + result.Set("start", PointWrapper::from_point(env, range.start)); + result.Set("end", PointWrapper::from_point(env, range.end)); + return result; + } else { + return env.Undefined(); } } - -void MarkerIndexWrapper::compare(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); +// +Napi::Value MarkerIndexWrapper::compare(const Napi::CallbackInfo &info) { + auto env = info.Env(); optional id1 = marker_id_from_js(info[0]); optional id2 = marker_id_from_js(info[1]); if (id1 && id2) { - info.GetReturnValue().Set(wrapper->marker_index.compare(*id1, *id2)); + auto r = marker_index.compare(*id1, *id2); + return Napi::Number::New(env, r); + } else { + return env.Undefined(); } } -void MarkerIndexWrapper::find_intersecting(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - +Napi::Value MarkerIndexWrapper::find_intersecting(const Napi::CallbackInfo &info) { + auto env = info.Env(); optional start = PointWrapper::point_from_js(info[0]); optional end = PointWrapper::point_from_js(info[1]); if (start && end) { - MarkerIndex::MarkerIdSet result = wrapper->marker_index.find_intersecting(*start, *end); - info.GetReturnValue().Set(marker_ids_set_to_js(result)); + MarkerIndex::MarkerIdSet result = marker_index.find_intersecting(*start, *end); + return marker_ids_set_to_js(env, result); + } else { + return env.Undefined(); } } -void MarkerIndexWrapper::find_containing(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - +Napi::Value MarkerIndexWrapper::find_containing(const Napi::CallbackInfo &info) { + auto env = info.Env(); optional start = PointWrapper::point_from_js(info[0]); optional end = PointWrapper::point_from_js(info[1]); if (start && end) { - MarkerIndex::MarkerIdSet result = wrapper->marker_index.find_containing(*start, *end); - info.GetReturnValue().Set(marker_ids_set_to_js(result)); + MarkerIndex::MarkerIdSet result = marker_index.find_containing(*start, *end); + return marker_ids_set_to_js(env, result); + } else { + return env.Undefined(); } } +// +// void MarkerIndexWrapper::find_containing(const Nan::FunctionCallbackInfo &info) { +// MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); +// +// optional start = PointWrapper::point_from_js(info[0]); +// optional end = PointWrapper::point_from_js(info[1]); +// +// if (start && end) { +// MarkerIndex::MarkerIdSet result = wrapper->marker_index.find_containing(*start, *end); +// info.GetReturnValue().Set(marker_ids_set_to_js(result)); +// } +// } +// +// void MarkerIndexWrapper::find_contained_in(const Nan::FunctionCallbackInfo &info) { +// MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); +// +// optional start = PointWrapper::point_from_js(info[0]); +// optional end = PointWrapper::point_from_js(info[1]); +// +// if (start && end) { +// MarkerIndex::MarkerIdSet result = wrapper->marker_index.find_contained_in(*start, *end); +// info.GetReturnValue().Set(marker_ids_set_to_js(result)); +// } +// } +// +// void MarkerIndexWrapper::find_starting_in(const Nan::FunctionCallbackInfo &info) { +// MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); +// +// optional start = PointWrapper::point_from_js(info[0]); +// optional end = PointWrapper::point_from_js(info[1]); +// +// if (start && end) { +// MarkerIndex::MarkerIdSet result = wrapper->marker_index.find_starting_in(*start, *end); +// info.GetReturnValue().Set(marker_ids_set_to_js(result)); +// } +// } +// +// void MarkerIndexWrapper::find_starting_at(const Nan::FunctionCallbackInfo &info) { +// MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); +// +// optional position = PointWrapper::point_from_js(info[0]); +// +// if (position) { +// MarkerIndex::MarkerIdSet result = wrapper->marker_index.find_starting_at(*position); +// info.GetReturnValue().Set(marker_ids_set_to_js(result)); +// } +// } +// +// void MarkerIndexWrapper::find_ending_in(const Nan::FunctionCallbackInfo &info) { +// MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); +// +// optional start = PointWrapper::point_from_js(info[0]); +// optional end = PointWrapper::point_from_js(info[1]); +// +// if (start && end) { +// MarkerIndex::MarkerIdSet result = wrapper->marker_index.find_ending_in(*start, *end); +// info.GetReturnValue().Set(marker_ids_set_to_js(result)); +// } +// } +// + +Napi::Value MarkerIndexWrapper::find_ending_at(const Napi::CallbackInfo &info) { + auto env = info.Env(); + optional position = PointWrapper::point_from_js(info[0]); -void MarkerIndexWrapper::find_contained_in(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - - optional start = PointWrapper::point_from_js(info[0]); - optional end = PointWrapper::point_from_js(info[1]); - - if (start && end) { - MarkerIndex::MarkerIdSet result = wrapper->marker_index.find_contained_in(*start, *end); - info.GetReturnValue().Set(marker_ids_set_to_js(result)); + if (position) { + MarkerIndex::MarkerIdSet result = marker_index.find_ending_at(*position); + return marker_ids_set_to_js(env, result); + } else { + return env.Undefined(); } } -void MarkerIndexWrapper::find_starting_in(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - +Napi::Value MarkerIndexWrapper::find_ending_in(const Napi::CallbackInfo &info) { + auto env = info.Env(); optional start = PointWrapper::point_from_js(info[0]); optional end = PointWrapper::point_from_js(info[1]); if (start && end) { - MarkerIndex::MarkerIdSet result = wrapper->marker_index.find_starting_in(*start, *end); - info.GetReturnValue().Set(marker_ids_set_to_js(result)); + MarkerIndex::MarkerIdSet result = marker_index.find_ending_in(*start, *end); + return marker_ids_set_to_js(env, result); + } else { + return env.Undefined(); } } -void MarkerIndexWrapper::find_starting_at(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - +Napi::Value MarkerIndexWrapper::find_starting_at(const Napi::CallbackInfo &info) { + auto env = info.Env(); optional position = PointWrapper::point_from_js(info[0]); if (position) { - MarkerIndex::MarkerIdSet result = wrapper->marker_index.find_starting_at(*position); - info.GetReturnValue().Set(marker_ids_set_to_js(result)); + MarkerIndex::MarkerIdSet result = marker_index.find_starting_at(*position); + return marker_ids_set_to_js(env, result); + } else { + return env.Undefined(); } } -void MarkerIndexWrapper::find_ending_in(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - +Napi::Value MarkerIndexWrapper::find_starting_in(const Napi::CallbackInfo &info) { + auto env = info.Env(); optional start = PointWrapper::point_from_js(info[0]); optional end = PointWrapper::point_from_js(info[1]); if (start && end) { - MarkerIndex::MarkerIdSet result = wrapper->marker_index.find_ending_in(*start, *end); - info.GetReturnValue().Set(marker_ids_set_to_js(result)); - } -} - -void MarkerIndexWrapper::find_ending_at(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - - optional position = PointWrapper::point_from_js(info[0]); - - if (position) { - MarkerIndex::MarkerIdSet result = wrapper->marker_index.find_ending_at(*position); - info.GetReturnValue().Set(marker_ids_set_to_js(result)); + MarkerIndex::MarkerIdSet result = marker_index.find_starting_in(*start, *end); + return marker_ids_set_to_js(env, result); + } else { + return env.Undefined(); } } -void MarkerIndexWrapper::find_boundaries_after(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - - optional start = PointWrapper::point_from_js(info[0]); - optional max_count; - Local js_max_count; - if (Nan::To(info[1]).ToLocal(&js_max_count)) { - max_count = Nan::To(js_max_count).FromMaybe(0); +// void MarkerIndexWrapper::find_boundaries_after(const Nan::FunctionCallbackInfo &info) { +// MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); +// +// optional start = PointWrapper::point_from_js(info[0]); +// optional max_count; +// Local js_max_count; +// if (Nan::To(info[1]).ToLocal(&js_max_count)) { +// max_count = Nan::To(js_max_count).FromMaybe(0); +// } +// +// if (start && max_count) { +// MarkerIndex::BoundaryQueryResult result = wrapper->marker_index.find_boundaries_after(*start, *max_count); +// Local js_result = Nan::New(); +// Nan::Set(js_result, Nan::New(containing_start_string), marker_ids_vector_to_js(result.containing_start)); +// +// Local js_boundaries = Nan::New(result.boundaries.size()); +// for (size_t i = 0; i < result.boundaries.size(); i++) { +// MarkerIndex::Boundary boundary = result.boundaries[i]; +// Local js_boundary = Nan::New(); +// Nan::Set(js_boundary, Nan::New(position_string), PointWrapper::from_point(boundary.position)); +// Nan::Set(js_boundary, Nan::New(starting_string), marker_ids_set_to_js(boundary.starting)); +// Nan::Set(js_boundary, Nan::New(ending_string), marker_ids_set_to_js(boundary.ending)); +// Nan::Set(js_boundaries, i, js_boundary); +// } +// Nan::Set(js_result, Nan::New(boundaries_string), js_boundaries); +// +// info.GetReturnValue().Set(js_result); +// } +// } +// +Napi::Value MarkerIndexWrapper::dump(const Napi::CallbackInfo &info) { + auto env = info.Env(); + auto snapshot = marker_index.dump(); + auto result_object = Napi::Object::New(env); + for (auto pair : snapshot) { + auto range = Napi::Object::New(env); + range.Set("start", PointWrapper::from_point(env, pair.second.start)); + range.Set("end", PointWrapper::from_point(env, pair.second.end)); + result_object.Set(pair.first, range); } - - if (start && max_count) { - MarkerIndex::BoundaryQueryResult result = wrapper->marker_index.find_boundaries_after(*start, *max_count); - Local js_result = Nan::New(); - Nan::Set(js_result, Nan::New(containing_start_string), marker_ids_vector_to_js(result.containing_start)); - - Local js_boundaries = Nan::New(result.boundaries.size()); - for (size_t i = 0; i < result.boundaries.size(); i++) { - MarkerIndex::Boundary boundary = result.boundaries[i]; - Local js_boundary = Nan::New(); - Nan::Set(js_boundary, Nan::New(position_string), PointWrapper::from_point(boundary.position)); - Nan::Set(js_boundary, Nan::New(starting_string), marker_ids_set_to_js(boundary.starting)); - Nan::Set(js_boundary, Nan::New(ending_string), marker_ids_set_to_js(boundary.ending)); - Nan::Set(js_boundaries, i, js_boundary); - } - Nan::Set(js_result, Nan::New(boundaries_string), js_boundaries); - - info.GetReturnValue().Set(js_result); - } -} - -void MarkerIndexWrapper::dump(const Nan::FunctionCallbackInfo &info) { - MarkerIndexWrapper *wrapper = Nan::ObjectWrap::Unwrap(info.This()); - unordered_map snapshot = wrapper->marker_index.dump(); - info.GetReturnValue().Set(snapshot_to_js(snapshot)); + return result_object; } - -MarkerIndexWrapper::MarkerIndexWrapper(unsigned seed) : marker_index{seed} {} diff --git a/src/bindings/marker-index-wrapper.h b/src/bindings/marker-index-wrapper.h index 2f64cc54..bccd21a5 100644 --- a/src/bindings/marker-index-wrapper.h +++ b/src/bindings/marker-index-wrapper.h @@ -1,41 +1,41 @@ -#include "nan.h" +#include "napi.h" #include "marker-index.h" #include "optional.h" #include "range.h" -class MarkerIndexWrapper : public Nan::ObjectWrap { +class MarkerIndexWrapper : public Napi::ObjectWrap { public: - static void init(v8::Local exports); - static MarkerIndex *from_js(v8::Local); - + static void init(Napi::Env env, Napi::Object exports); + MarkerIndexWrapper(const Napi::CallbackInfo& info); +// static void init(v8::Local exports); + // static MarkerIndex *from_js(v8::Local); +// private: - static void construct(const Nan::FunctionCallbackInfo &info); - static void generate_random_number(const Nan::FunctionCallbackInfo &info); - static bool is_finite(v8::Local number); - static v8::Local marker_ids_set_to_js(const MarkerIndex::MarkerIdSet &marker_ids); - static v8::Local marker_ids_vector_to_js(const std::vector &marker_ids); - static v8::Local snapshot_to_js(const std::unordered_map &snapshot); - static optional marker_id_from_js(v8::Local value); - static optional unsigned_from_js(v8::Local value); - static optional bool_from_js(v8::Local value); - static void insert(const Nan::FunctionCallbackInfo &info); - static void set_exclusive(const Nan::FunctionCallbackInfo &info); - static void remove(const Nan::FunctionCallbackInfo &info); - static void has(const Nan::FunctionCallbackInfo &info); - static void splice(const Nan::FunctionCallbackInfo &info); - static void get_start(const Nan::FunctionCallbackInfo &info); - static void get_end(const Nan::FunctionCallbackInfo &info); - static void get_range(const Nan::FunctionCallbackInfo &info); - static void compare(const Nan::FunctionCallbackInfo &info); - static void find_intersecting(const Nan::FunctionCallbackInfo &info); - static void find_containing(const Nan::FunctionCallbackInfo &info); - static void find_contained_in(const Nan::FunctionCallbackInfo &info); - static void find_starting_in(const Nan::FunctionCallbackInfo &info); - static void find_starting_at(const Nan::FunctionCallbackInfo &info); - static void find_ending_in(const Nan::FunctionCallbackInfo &info); - static void find_ending_at(const Nan::FunctionCallbackInfo &info); - static void find_boundaries_after(const Nan::FunctionCallbackInfo &info); - static void dump(const Nan::FunctionCallbackInfo &info); - MarkerIndexWrapper(unsigned seed); + Napi::Value splice(const Napi::CallbackInfo &info); +// static void generate_random_number(const Nan::FunctionCallbackInfo &info); +// static bool is_finite(v8::Local number); + static Napi::Object marker_ids_set_to_js(Napi::Env env, const MarkerIndex::MarkerIdSet &marker_ids); + Napi::Value has(const Napi::CallbackInfo &info); + static optional marker_id_from_js(Napi::Value value); + Napi::Value insert(const Napi::CallbackInfo &info); + Napi::Value compare(const Napi::CallbackInfo &info); + Napi::Value get_start(const Napi::CallbackInfo &info); + Napi::Value get_end(const Napi::CallbackInfo &info); + Napi::Value get_range(const Napi::CallbackInfo &info); + Napi::Value set_exclusive(const Napi::CallbackInfo &info); + Napi::Value remove(const Napi::CallbackInfo &info); + Napi::Value find_ending_at(const Napi::CallbackInfo &info); + Napi::Value find_ending_in(const Napi::CallbackInfo &info); + Napi::Value find_starting_at(const Napi::CallbackInfo &info); + Napi::Value find_starting_in(const Napi::CallbackInfo &info); + Napi::Value dump(const Napi::CallbackInfo &info); + Napi::Value find_intersecting(const Napi::CallbackInfo &info); + Napi::Value find_containing(const Napi::CallbackInfo &info); +// static v8::Local marker_ids_vector_to_js(const std::vector &marker_ids); +// static v8::Local snapshot_to_js(const std::unordered_map &snapshot); +// static void find_contained_in(const Nan::FunctionCallbackInfo &info); +// static void find_boundaries_after(const Nan::FunctionCallbackInfo &info); +// MarkerIndexWrapper(unsigned seed); MarkerIndex marker_index; + static Napi::FunctionReference *constructor; }; diff --git a/src/bindings/patch-wrapper.cc b/src/bindings/patch-wrapper.cc index f43d7d57..01e6bf20 100644 --- a/src/bindings/patch-wrapper.cc +++ b/src/bindings/patch-wrapper.cc @@ -245,8 +245,8 @@ Napi::Value PatchWrapper::get_changes_in_old_range(const Napi::CallbackInfo &inf auto env = info.Env(); auto start = PointWrapper::point_from_js(info[0]); auto end = PointWrapper::point_from_js(info[1]); - if (start.has_value() && end.has_value()) { - auto changes = patch.grab_changes_in_old_range(start.value(), end.value()); + if (start && end) { + auto changes = patch.grab_changes_in_old_range(*start, *start); auto js_result = Napi::Array::New(env, changes.size()); size_t i = 0; for (auto change : changes) { @@ -262,8 +262,8 @@ Napi::Value PatchWrapper::get_changes_in_new_range(const Napi::CallbackInfo &inf auto env = info.Env(); auto start = PointWrapper::point_from_js(info[0]); auto end = PointWrapper::point_from_js(info[1]); - if (start.has_value() && end.has_value()) { - auto changes = patch.grab_changes_in_new_range(start.value(), end.value()); + if (start && end) { + auto changes = patch.grab_changes_in_new_range(*start, *start); auto js_result = Napi::Array::New(env, changes.size()); size_t i = 0; for (auto change : changes) { @@ -277,8 +277,8 @@ Napi::Value PatchWrapper::get_changes_in_new_range(const Napi::CallbackInfo &inf Napi::Value PatchWrapper::change_for_old_position(const Napi::CallbackInfo &info) { auto start = PointWrapper::point_from_js(info[0]); - if (start.has_value()) { - auto change = patch.grab_change_starting_before_old_position(start.value()); + if (start) { + auto change = patch.grab_change_starting_before_old_position(*start); if (change) { return ChangeWrapper::FromChange(info.Env(), *change); } @@ -288,8 +288,8 @@ Napi::Value PatchWrapper::change_for_old_position(const Napi::CallbackInfo &info Napi::Value PatchWrapper::change_for_new_position(const Napi::CallbackInfo &info) { auto start = PointWrapper::point_from_js(info[0]); - if (start.has_value()) { - auto change = patch.grab_change_starting_before_new_position(start.value()); + if (start) { + auto change = patch.grab_change_starting_before_new_position(*start); if (change) { return ChangeWrapper::FromChange(info.Env(), *change); } diff --git a/src/bindings/point-wrapper.cc b/src/bindings/point-wrapper.cc index dd3cc992..e5a902ec 100644 --- a/src/bindings/point-wrapper.cc +++ b/src/bindings/point-wrapper.cc @@ -1,33 +1,15 @@ -#include #include "point-wrapper.h" -#include #include "napi.h" +#include +#include -// using namespace v8; - -// static Nan::Persistent row_string; -// static Nan::Persistent column_string; -// static Nan::Persistent constructor; -// -// static uint32_t number_from_js(Napi::Value js_number) { -// double number; -// if(js_number.IsNumber()) { -// number = js_number.ToNumber().DoubleValue(); -// } else { -// number = 0; -// } -// if (number > 0 && !std::isfinite(number)) { -// return UINT32_MAX; -// } else { -// return std::max(0.0, number); -// } -// } - -std::optional PointWrapper::point_from_js(Napi::Value value) { +// #include +auto Inf = std::numeric_limits::infinity(); +optional PointWrapper::point_from_js(Napi::Value value) { Napi::Env env = value.Env(); if (!value.IsObject()) { Napi::TypeError::New(env, "Expected an object with 'row' and 'column' properties.").ThrowAsJavaScriptException(); - return std::optional(); + return optional(); } Napi::Object object = value.ToObject(); @@ -35,17 +17,23 @@ std::optional PointWrapper::point_from_js(Napi::Value value) { auto js_column = object.Get("column");; if (!js_row.IsNumber() || !js_column.IsNumber()) { Napi::TypeError::New(env, "Expected an object with 'row' and 'column' properties.").ThrowAsJavaScriptException(); - return std::optional(); + return optional(); } - return Point(js_row.ToNumber().DoubleValue(), js_column.ToNumber().DoubleValue()); + auto row = js_row.ToNumber().DoubleValue(); + if(row == Inf) row = UINT_MAX; + auto col = js_column.ToNumber().DoubleValue(); + if(col == Inf) col = UINT_MAX; + return Point(row, col); } Napi::FunctionReference *PointWrapper::constructor; void PointWrapper::init(Napi::Env env, Napi::Object exports) { Napi::Function func = DefineClass(env, "Point", { - InstanceAccessor<&PointWrapper::get_row>("row"), - InstanceAccessor<&PointWrapper::get_column>("column"), + InstanceAccessor<&PointWrapper::get_row>("row", napi_default_jsproperty), + InstanceAccessor<&PointWrapper::get_column>("column", napi_default_jsproperty), + InstanceMethod<&PointWrapper::inspect>("inspect"), + InstanceMethod<&PointWrapper::inspect>("toString"), InstanceMethod<&PointWrapper::to_json>("toJSON"), }); @@ -66,8 +54,8 @@ PointWrapper::PointWrapper(const Napi::CallbackInfo& info) : Napi::ObjectWrappoint = *point.Data(); } else { auto maybe_point = PointWrapper::point_from_js(info[0]); - if(maybe_point.has_value()) { - this->point = maybe_point.value(); + if(maybe_point) { + this->point = *maybe_point; } } } @@ -84,3 +72,10 @@ Napi::Value PointWrapper::to_json(const Napi::CallbackInfo &info) { json.Set("column", this->point.column); return json; } +Napi::Value PointWrapper::inspect(const Napi::CallbackInfo &info) { + auto obj = this->to_json(info); + // auto json = Napi::Object::New(info.Env()); + // json.Set("row", this->point.row); + // json.Set("column", this->point.column); + return obj.ToString(); +} diff --git a/src/bindings/point-wrapper.h b/src/bindings/point-wrapper.h index 371499e9..d00c7266 100644 --- a/src/bindings/point-wrapper.h +++ b/src/bindings/point-wrapper.h @@ -3,19 +3,21 @@ #include "napi.h" #include "point.h" +#include "optional.h" class PointWrapper : public Napi::ObjectWrap { public: static void init(Napi::Env env, Napi::Object exports); static Napi::Value from_point(Napi::Env env, Point point); - static std::optional point_from_js(Napi::Value); + static optional point_from_js(Napi::Value); PointWrapper(const Napi::CallbackInfo& info); private: static Napi::FunctionReference *constructor; Napi::Value get_row(const Napi::CallbackInfo &info); Napi::Value get_column(const Napi::CallbackInfo &info); + Napi::Value inspect(const Napi::CallbackInfo &info); Napi::Value to_json(const Napi::CallbackInfo &info); Point point; }; diff --git a/src/bindings/range-wrapper.cc b/src/bindings/range-wrapper.cc index 8b968893..cd960f24 100644 --- a/src/bindings/range-wrapper.cc +++ b/src/bindings/range-wrapper.cc @@ -13,8 +13,8 @@ std::optional RangeWrapper::range_from_js(Napi::Value value) { auto start = PointWrapper::point_from_js(object.Get("start")); auto end = PointWrapper::point_from_js(object.Get("end")); - if (start.has_value() && end.has_value()) { - return Range{start.value(), end.value()}; + if (start && end) { + return Range{*start, *end}; } else { Napi::TypeError::New(env, "Expected an object with 'start' and 'end' properties.").ThrowAsJavaScriptException(); return std::optional(); @@ -34,8 +34,8 @@ void RangeWrapper::init(Napi::Env env, Napi::Object exports) { RangeWrapper::RangeWrapper(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { auto maybe_range = RangeWrapper::range_from_js(info[0]); - if(maybe_range.has_value()) { - this->range = maybe_range.value(); + if(maybe_range) { + this->range = *maybe_range; } } From 2f28fae4a03303c8e5b95d401dacca608f79dc17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Szabo?= Date: Tue, 11 Oct 2022 02:08:25 -0300 Subject: [PATCH 12/13] More things on binding.gyp --- binding.gyp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/binding.gyp b/binding.gyp index c3cc0510..226c17ef 100644 --- a/binding.gyp +++ b/binding.gyp @@ -11,8 +11,8 @@ ], "sources": [ "src/bindings/bindings.cc", - # "src/bindings/marker-index-wrapper.cc", - # "src/bindings/patch-wrapper.cc", + "src/bindings/marker-index-wrapper.cc", + "src/bindings/patch-wrapper.cc", "src/bindings/point-wrapper.cc", "src/bindings/range-wrapper.cc", # "src/bindings/text-buffer-wrapper.cc", @@ -21,6 +21,8 @@ # "src/bindings/string-conversion.cc", # "src/bindings/text-writer.cc", ], + 'cflags!': [ '-fno-exceptions' ], + 'cflags_cc!': [ '-fno-exceptions' ], "include_dirs": [ "src/core", " Date: Wed, 12 Apr 2023 09:35:20 -0300 Subject: [PATCH 13/13] Fix build flags --- binding.gyp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/binding.gyp b/binding.gyp index 226c17ef..fe1509ba 100644 --- a/binding.gyp +++ b/binding.gyp @@ -23,6 +23,7 @@ ], 'cflags!': [ '-fno-exceptions' ], 'cflags_cc!': [ '-fno-exceptions' ], + "cflags_cc": ["-std=c++17"], "include_dirs": [ "src/core", "