From ed791ef0ac8bfd71d4d776a1b9ebb88fda7132f0 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 13:27:34 +0200 Subject: [PATCH 01/22] upgrade abstract-leveldown to 5.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fb22981..e735e1d 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "tape": "^4.0.0" }, "dependencies": { - "abstract-leveldown": "~0.12.0", + "abstract-leveldown": "~5.0.0", "idb-wrapper": "^1.5.0", "isbuffer": "~0.0.0", "ltgt": "^2.1.2", From 558fb21908b4ada26ed5ccf3fc84b8e6b56d233b Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 13:28:06 +0200 Subject: [PATCH 02/22] upgrade levelup to 3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e735e1d..f0377ad 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "devDependencies": { "airtap": "0.0.5", "browserify": "~16.2.2", - "levelup": "~0.18.2", + "levelup": "~3.0.0", "tape": "^4.0.0" }, "dependencies": { From 75480e2bc86c19be71fcc98742ac91ea0a6aaaa1 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 13:30:58 +0200 Subject: [PATCH 03/22] include abstract/iterator-range-test --- test/test.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/test.js b/test/test.js index 28ab3dc..fba4c83 100644 --- a/test/test.js +++ b/test/test.js @@ -18,11 +18,7 @@ require('abstract-leveldown/abstract/batch-test').all(leveljs, tape, testCommon) require('abstract-leveldown/abstract/chained-batch-test').all(leveljs, tape, testCommon) require('abstract-leveldown/abstract/close-test').close(leveljs, tape, testCommon) require('abstract-leveldown/abstract/iterator-test').all(leveljs, tape, testCommon) - -// NOTE: exclude this because the handling of buffers is inconsistent between -// iterator-test and ranges-test. We can't make both pass, but that's OK, as -// ranges-test is removed in a later abstract-leveldown version anyway. -// require('abstract-leveldown/abstract/ranges-test').all(leveljs, tape, testCommon) +require('abstract-leveldown/abstract/iterator-range-test').all(leveljs, tape, testCommon) // non abstract-leveldown tests: require('./custom-tests.js').all(leveljs, tape, testCommon) From f5171a803c0cfb374d1b8abecd7c1db9b8e154df Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 13:31:41 +0200 Subject: [PATCH 04/22] remove testBuffer --- test/test.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/test.js b/test/test.js index fba4c83..77893e2 100644 --- a/test/test.js +++ b/test/test.js @@ -5,15 +5,13 @@ var testCommon = require('./testCommon') // load IndexedDBShim in the tests require('./idb-shim.js')() -var testBuffer = Buffer.from('foo') - /*** compatibility with basic LevelDOWN API ***/ require('abstract-leveldown/abstract/leveldown-test').args(leveljs, tape, testCommon) require('abstract-leveldown/abstract/open-test').open(leveljs, tape, testCommon) require('abstract-leveldown/abstract/put-test').all(leveljs, tape, testCommon) require('abstract-leveldown/abstract/del-test').all(leveljs, tape, testCommon) require('abstract-leveldown/abstract/get-test').all(leveljs, tape, testCommon) -require('abstract-leveldown/abstract/put-get-del-test').all(leveljs, tape, testCommon, testBuffer) +require('abstract-leveldown/abstract/put-get-del-test').all(leveljs, tape, testCommon) require('abstract-leveldown/abstract/batch-test').all(leveljs, tape, testCommon) require('abstract-leveldown/abstract/chained-batch-test').all(leveljs, tape, testCommon) require('abstract-leveldown/abstract/close-test').close(leveljs, tape, testCommon) From 698cc8bf071c0d7fdfa5fb955552ba329028ea2a Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 13:32:29 +0200 Subject: [PATCH 05/22] remove _isBuffer (closes #64) --- index.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/index.js b/index.js index 4792856..545bfc7 100644 --- a/index.js +++ b/index.js @@ -128,10 +128,6 @@ Level.prototype._approximateSize = function (start, end, callback) { throw err } -Level.prototype._isBuffer = function (obj) { - return Buffer.isBuffer(obj) -} - Level.destroy = function (db, callback) { if (typeof db === 'object') { var prefix = db.IDBOptions.storePrefix || 'IDBWrapper-' From 0253f857b2390e990b608adf4a753242194dc8ff Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 13:33:24 +0200 Subject: [PATCH 06/22] remove _approximateSize (closes #75) --- index.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/index.js b/index.js index 545bfc7..52c9c28 100644 --- a/index.js +++ b/index.js @@ -120,14 +120,6 @@ Level.prototype._close = function (callback) { callback() } -Level.prototype._approximateSize = function (start, end, callback) { - var err = new Error('Not implemented') - if (callback) - return callback(err) - - throw err -} - Level.destroy = function (db, callback) { if (typeof db === 'object') { var prefix = db.IDBOptions.storePrefix || 'IDBWrapper-' From 9e1e61f4d530c197efa162a10879a6b177e21ecc Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 13:56:16 +0200 Subject: [PATCH 07/22] fix constructor --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 52c9c28..dac1da8 100644 --- a/index.js +++ b/index.js @@ -10,7 +10,7 @@ var toBuffer = require('typedarray-to-buffer') function Level(location) { if (!(this instanceof Level)) return new Level(location) - if (!location) throw new Error("constructor requires at least a location argument") + AbstractLevelDOWN.call(this, location) this.IDBOptions = {} this.location = location } From fd167265dfd9dabc8f6e0eaf49a9127837e55022 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 13:57:57 +0200 Subject: [PATCH 08/22] fix #_iterator --- index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.js b/index.js index dac1da8..3947858 100644 --- a/index.js +++ b/index.js @@ -80,8 +80,7 @@ Level.prototype._serializeValue = function (value, options) { return value } -Level.prototype.iterator = function (options) { - if (typeof options !== 'object') options = {} +Level.prototype._iterator = function (options) { return new Iterator(this.idb, options) } From 2da8fed4b2a89f89726a16466cb81f5d9fd3ce5b Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 13:59:02 +0200 Subject: [PATCH 09/22] rely on default options in Iterator constructor --- iterator.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/iterator.js b/iterator.js index 579755f..bcd9265 100644 --- a/iterator.js +++ b/iterator.js @@ -24,9 +24,8 @@ function Iterator (db, options) { this._cache = [] this._completed = false - // TODO: in later abstract-leveldown, these have proper defaults - this._keyAsBuffer = options.keyAsBuffer !== false - this._valueAsBuffer = options.valueAsBuffer !== false + this._keyAsBuffer = options.keyAsBuffer + this._valueAsBuffer = options.valueAsBuffer var lower = ltgt.lowerBound(options) var upper = ltgt.upperBound(options) From cdd5e73f042d6970b902a0af88ec6a2aa13df2d3 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 14:02:06 +0200 Subject: [PATCH 10/22] add _serializeKey --- index.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/index.js b/index.js index 3947858..7d4c15a 100644 --- a/index.js +++ b/index.js @@ -65,6 +65,33 @@ Level.prototype._put = function (key, value, options, callback) { this.idb.put(key, value, function() { callback() }, callback) } +// Valid key types in IndexedDB Second Edition: +// +// - Number, except NaN. Includes Infinity and -Infinity +// - Date, except invalid (NaN) +// - String +// - ArrayBuffer or a view thereof (typed arrays) +// - Array, except cyclical and empty (e.g. Array(10)). Elements must be valid +// types themselves. +Level.prototype._serializeKey = function (key) { + // TODO: do we still need to support ArrayBuffer? + if (key instanceof ArrayBuffer) return Buffer.from(key) + + if (typeof key === 'string' || Buffer.isBuffer(key)) { + return key + } + + if (Array.isArray(key)) { + return key.map(this._serializeKey, this) + } + + if ((typeof key === 'number' || key instanceof Date) && !isNaN(key)) { + return key + } + + return String(key) +} + // NOTE: doesn't match abstract signature yet (which has no options argument). Level.prototype._serializeValue = function (value, options) { // TODO: do we still need to support ArrayBuffer? From d3687277ba684f12ee4583bc33780de2d44da794 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 14:03:34 +0200 Subject: [PATCH 11/22] remove options.raw (#65) --- index.js | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index 7d4c15a..9ed5b77 100644 --- a/index.js +++ b/index.js @@ -43,14 +43,12 @@ Level.prototype._get = function (key, options, callback) { // 'NotFound' error, consistent with LevelDOWN API return callback(new Error('NotFound')) } - // by default return buffers, unless explicitly told not to - var asBuffer = true - if (options.asBuffer === false) asBuffer = false - if (options.raw) asBuffer = false - if (asBuffer) { + + if (options.asBuffer) { if (value instanceof Uint8Array) value = toBuffer(value) else value = Buffer.from(String(value)) } + return callback(null, value, key) }, callback) } @@ -98,12 +96,6 @@ Level.prototype._serializeValue = function (value, options) { if (value instanceof ArrayBuffer) return Buffer.from(value) if (value == null) return '' - // TODO: remove - if (options.raw) return value - - // TODO: remove - if (typeof value !== 'object') return value.toString() - return value } From 356b004ed179e2ffd042d3dcbcc9465b2ffd265c Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 14:04:11 +0200 Subject: [PATCH 12/22] remove calls to _serializeValue --- index.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/index.js b/index.js index 9ed5b77..52fb99b 100644 --- a/index.js +++ b/index.js @@ -58,8 +58,6 @@ Level.prototype._del = function(id, options, callback) { } Level.prototype._put = function (key, value, options, callback) { - // TODO: once we upgrade abstract-leveldown, it will call _serializeValue for us. - value = this._serializeValue(value, options) this.idb.put(key, value, function() { callback() }, callback) } @@ -118,9 +116,6 @@ Level.prototype._batch = function (array, options, callback) { currentOp = array[i] modified[i] = copiedOp - // TODO: once we upgrade abstract-leveldown, it will call _serializeValue for us. - currentOp.value = this._serializeValue(currentOp.value, options) - for (k in currentOp) { if (k === 'type' && currentOp[k] == 'del') { copiedOp[k] = 'remove' From d2f4cb0eff8e1c56c76a4207107804833dfb7818 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 14:05:12 +0200 Subject: [PATCH 13/22] remove options argument from _serializeValue --- index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.js b/index.js index 52fb99b..aaada0a 100644 --- a/index.js +++ b/index.js @@ -88,8 +88,7 @@ Level.prototype._serializeKey = function (key) { return String(key) } -// NOTE: doesn't match abstract signature yet (which has no options argument). -Level.prototype._serializeValue = function (value, options) { +Level.prototype._serializeValue = function (value) { // TODO: do we still need to support ArrayBuffer? if (value instanceof ArrayBuffer) return Buffer.from(value) if (value == null) return '' From d103e4349feefb6d43b4c9753c611b14b045a580 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 14:12:04 +0200 Subject: [PATCH 14/22] fix iterator with limit=0 --- iterator.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/iterator.js b/iterator.js index bcd9265..e164fb2 100644 --- a/iterator.js +++ b/iterator.js @@ -18,15 +18,21 @@ function Iterator (db, options) { AbstractIterator.call(this, db) this._order = options.reverse ? 'DESC': 'ASC' - this._limit = options.limit || -1 + this._limit = options.limit this._count = 0 this._callback = null this._cache = [] this._completed = false + this.transaction = null this._keyAsBuffer = options.keyAsBuffer this._valueAsBuffer = options.valueAsBuffer + if (this._limit === 0) { + this._completed = true + return + } + var lower = ltgt.lowerBound(options) var upper = ltgt.upperBound(options) @@ -97,7 +103,7 @@ Iterator.prototype._next = function (callback) { // TODO: can remove this after upgrading abstract-leveldown if (!callback) throw new Error('next() requires a callback argument') - if (this.transaction.error !== null) { + if (this.transaction !== null && this.transaction.error !== null) { var err = this.transaction.error setTimeout(function() { From db364abfd89ab782353013e2fc9e333056a80ef3 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 14:28:21 +0200 Subject: [PATCH 15/22] temporarily add brfs to fix Level/levelup#578 --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index f0377ad..50c8d0f 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "license": "MIT", "devDependencies": { "airtap": "0.0.5", + "brfs": "~1.6.1", "browserify": "~16.2.2", "levelup": "~3.0.0", "tape": "^4.0.0" From e3d35d71d4795dafce5e1d938afec00d7f075609 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 14:29:49 +0200 Subject: [PATCH 16/22] fix native type tests --- test/custom-tests.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test/custom-tests.js b/test/custom-tests.js index e347979..af891d4 100644 --- a/test/custom-tests.js +++ b/test/custom-tests.js @@ -21,15 +21,14 @@ module.exports.all = function(leveljs, tape, testCommon) { }) }) - // TODO: this should be supported without raw: true. Which is possible once - // we upgrade abstract-leveldown (which only tests strings and Buffers now). - tape('store native JS types with raw = true', function(t) { + // TODO: merge this and the test below. Test all types. + tape('store native JS types', function(t) { var level = leveljs(testCommon.location()) level.open(function(err) { t.notOk(err, 'no error') - level.put('key', true, { raw: true }, function (err) { + level.put('key', true, function (err) { t.notOk(err, 'no error') - level.get('key', { raw: true }, function(err, value) { + level.get('key', { asBuffer: false }, function(err, value) { t.notOk(err, 'no error') t.ok(typeof value === 'boolean', 'is boolean type') t.ok(value, 'is truthy') @@ -45,9 +44,9 @@ module.exports.all = function(leveljs, tape, testCommon) { var level = leveljs(testCommon.location()) level.open(function(err) { t.notOk(err, 'no error') - level.put('key', NaN, { raw: true }, function (err) { + level.put('key', NaN, function (err) { t.notOk(err, 'no error') - level.get('key', { raw: true }, function(err, value) { + level.get('key', { asBuffer: false }, function(err, value) { t.notOk(err, 'no error') t.ok(Number.isNaN(value), 'is NaN') level.close(t.end.bind(t)) From 5618102a1247207c5c7483bc92d1f14ef2872913 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 14:33:45 +0200 Subject: [PATCH 17/22] fix destroy tests --- test/custom-tests.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/test/custom-tests.js b/test/custom-tests.js index af891d4..8488977 100644 --- a/test/custom-tests.js +++ b/test/custom-tests.js @@ -60,20 +60,20 @@ module.exports.all = function(leveljs, tape, testCommon) { tape('test levelup .destroy w/ string', function(t) { var location = testCommon.location() - var level = levelup(location, {db: leveljs}) - level.put('key', 'value', function (err) { + var db = levelup(leveljs(location)) + db.put('key', 'value', function (err) { t.notOk(err, 'no error') - level.get('key', function (err, value) { + db.get('key', { asBuffer: false }, function (err, value) { t.notOk(err, 'no error') t.equal(value, 'value', 'should have value') - level.close(function (err) { + db.close(function (err) { t.notOk(err, 'no error') leveljs.destroy(location, function (err) { t.notOk(err, 'no error') - var level2 = levelup(location, {db: leveljs}) - level2.get('key', function (err, value) { - t.ok(err, 'key is not there') - level2.close(t.end.bind(t)) + var db2 = levelup(leveljs(location)) + db2.get('key', { asBuffer: false }, function (err, value) { + t.ok(err && err.notFound, 'key is not there') + db2.close(t.end.bind(t)) }) }) }) @@ -83,20 +83,20 @@ module.exports.all = function(leveljs, tape, testCommon) { tape('test levelup .destroy w/ db instance', function(t) { var location = testCommon.location() - var level = levelup(location, {db: leveljs}) - level.put('key', 'value', function (err) { + var db = levelup(leveljs(location)) + db.put('key', 'value', function (err) { t.notOk(err, 'no error') - level.get('key', function (err, value) { + db.get('key', { asBuffer: false }, function (err, value) { t.notOk(err, 'no error') t.equal(value, 'value', 'should have value') - level.close(function (err) { + db.close(function (err) { t.notOk(err, 'no error') - leveljs.destroy(level.db, function (err) { + leveljs.destroy(db.db, function (err) { t.notOk(err, 'no error') - var level2 = levelup(location, {db: leveljs}) - level2.get('key', function (err, value) { - t.ok(err, 'key is not there') - level2.close(t.end.bind(t)) + var db2 = levelup(leveljs(location)) + db2.get('key', { asBuffer: false }, function (err, value) { + t.ok(err && err.notFound, 'key is not there') + db2.close(t.end.bind(t)) }) }) }) From c7bc3b484f15140cf5f12e81d458617415670fdc Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 14:44:51 +0200 Subject: [PATCH 18/22] fix levelup integration tests --- package.json | 1 + test/test-levelup.js | 32 +++++++++++++++----------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 50c8d0f..e86ec94 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "airtap": "0.0.5", "brfs": "~1.6.1", "browserify": "~16.2.2", + "encoding-down": "~5.0.2", "levelup": "~3.0.0", "tape": "^4.0.0" }, diff --git a/test/test-levelup.js b/test/test-levelup.js index 9e117e7..6b08230 100644 --- a/test/test-levelup.js +++ b/test/test-levelup.js @@ -1,27 +1,25 @@ /*** Levelup tests - Temporary to test integration, can be removed later. + NOTE: Temporary integration tests, can be removed later. Remember + to also remove the encoding-down devDependency. ***/ var levelup = require('levelup') +var encoding = require('encoding-down') var leveljs = require('../') var test = require('tape') var testCommon = require('./testCommon') -function identity (v) { - return v -} - test('setup', testCommon.setUp) test('levelup put', function (t) { t.plan(4) - // TODO: update signature after upgrading levelup - var db = levelup(testCommon.location(), { db: leveljs }) + var down = leveljs(testCommon.location()) + var db = levelup(down) db.put('name', 'LevelUP string', function (err) { t.ifError(err, 'no put error') - db.get('name', function (err, value) { + db.get('name', { asBuffer: false }, function (err, value) { t.ifError(err, 'no get error') t.is(value, 'LevelUP string') @@ -33,10 +31,10 @@ test('levelup put', function (t) { }) test('binary', function (t) { - t.plan(6) + t.plan(9) - // TODO: update signature after upgrading levelup - var db = levelup(testCommon.location(), { db: leveljs, valueEncoding: 'binary' }) + var down = leveljs(testCommon.location()) + var db = levelup(encoding(down, { valueEncoding: 'binary' })) var buf = Buffer.from('00ff', 'hex') db.put('binary', buf, function (err) { @@ -44,14 +42,14 @@ test('binary', function (t) { db.get('binary', function (err, value) { t.ifError(err, 'no get error') + t.ok(Buffer.isBuffer(value), 'is a buffer') + t.same(value, buf) - // This levelup is really old and its binary decoder does: - // `return process.browser ? buffer.toString(type) : buffer` - t.notOk(Buffer.isBuffer(value), 'not a buffer') - - db.get('binary', { valueEncoding: { decode: identity } }, function (err, value) { + db.get('binary', { valueEncoding: 'id' }, function (err, value) { t.ifError(err, 'no get error') - t.ok(Buffer.isBuffer(value), 'is a buffer') + t.notOk(Buffer.isBuffer(value), 'is not a buffer') + t.ok(value instanceof Uint8Array, 'is a Uint8Array') + t.same(Buffer.from(value), buf) db.close(function (err) { t.ifError(err, 'no close error') From f6db11630c579204d2d46199066aeff71d83c58a Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 15:05:56 +0200 Subject: [PATCH 19/22] test buffer keys --- test/custom-tests.js | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/test/custom-tests.js b/test/custom-tests.js index 8488977..64e2fd9 100644 --- a/test/custom-tests.js +++ b/test/custom-tests.js @@ -3,9 +3,7 @@ var levelup = require('levelup') module.exports.all = function(leveljs, tape, testCommon) { tape('setUp', testCommon.setUp) - // This is covered by abstract-leveldown tests, but we're - // not on latest yet, so this is insurance. - tape('store buffer value', function(t) { + tape('buffer value', function(t) { var level = leveljs(testCommon.location()) level.open(function(err) { t.notOk(err, 'no error') @@ -21,6 +19,46 @@ module.exports.all = function(leveljs, tape, testCommon) { }) }) + // This should be covered by abstract-leveldown tests, but that's + // prevented by process.browser checks (Level/abstract-leveldown#121). + // This test is adapted from memdown. + tape('buffer keys', function (t) { + var db = leveljs(testCommon.location()) + + db.open(function (err) { + t.ifError(err, 'no open error') + + var one = Buffer.from('80', 'hex') + var two = Buffer.from('c0', 'hex') + + t.ok(two.toString() === one.toString(), 'would be equal when not buffer-aware') + t.ok(Buffer.compare(two, one) > 0, 'but greater when buffer-aware') + + db.put(one, 'one', function (err) { + t.notOk(err, 'no error') + + db.get(one, { asBuffer: false }, function (err, value) { + t.notOk(err, 'no error') + t.equal(value, 'one', 'value one ok') + + db.put(two, 'two', function (err) { + t.notOk(err, 'no error') + + db.get(one, { asBuffer: false }, function (err, value) { + t.notOk(err, 'no error') + t.equal(value, 'one', 'value one is the same') + + db.close(function (err) { + t.ifError(err, 'no close error') + t.end() + }) + }) + }) + }) + }) + }) + }) + // TODO: merge this and the test below. Test all types. tape('store native JS types', function(t) { var level = leveljs(testCommon.location()) From f6009936bb0f8ab2fa0ae0dfbd3162342394995e Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 15:07:03 +0200 Subject: [PATCH 20/22] test that iterator stringifies buffer input --- test/custom-tests.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/custom-tests.js b/test/custom-tests.js index 64e2fd9..8086045 100644 --- a/test/custom-tests.js +++ b/test/custom-tests.js @@ -59,6 +59,31 @@ module.exports.all = function(leveljs, tape, testCommon) { }) }) + // Adapted from a memdown test. + tape('iterator stringifies buffer input', function (t) { + t.plan(6) + + var db = leveljs(testCommon.location()) + + db.open(function (err) { + t.ifError(err, 'no open error') + + db.put(1, 2, function (err) { + t.ifError(err, 'no put error') + + testCommon.collectEntries(db.iterator(), function (err, entries) { + t.ifError(err, 'no iterator error') + t.same(entries[0].key, Buffer.from('1'), 'key is stringified') + t.same(entries[0].value, Buffer.from('2'), 'value is stringified') + + db.close(function (err) { + t.ifError(err, 'no close error') + }) + }) + }) + }) + }) + // TODO: merge this and the test below. Test all types. tape('store native JS types', function(t) { var level = leveljs(testCommon.location()) From c94500d71558dd5affa1816a09f7129f43f2b173 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 16:43:49 +0200 Subject: [PATCH 21/22] detect binary key support (#58) --- index.js | 31 +++++++++++++++++++++---------- test/custom-tests.js | 4 ++-- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index aaada0a..29c51d9 100644 --- a/index.js +++ b/index.js @@ -17,6 +17,20 @@ function Level(location) { util.inherits(Level, AbstractLevelDOWN) +// Detect binary key support (IndexedDB Second Edition) +Level.binaryKeys = (function () { + if (typeof indexedDB === 'undefined') { + return false + } + + try { + indexedDB.cmp(new Uint8Array(0), 0) + return true + } catch (err) { + return false + } +})() + Level.prototype._open = function(options, callback) { var self = this @@ -71,17 +85,14 @@ Level.prototype._put = function (key, value, options, callback) { // types themselves. Level.prototype._serializeKey = function (key) { // TODO: do we still need to support ArrayBuffer? - if (key instanceof ArrayBuffer) return Buffer.from(key) - - if (typeof key === 'string' || Buffer.isBuffer(key)) { - return key - } - - if (Array.isArray(key)) { + if (key instanceof ArrayBuffer) { + key = Buffer.from(key) + return Level.binaryKeys ? key : key.toString() + } else if (Buffer.isBuffer(key)) { + return Level.binaryKeys ? key : key.toString() + } else if (Array.isArray(key)) { return key.map(this._serializeKey, this) - } - - if ((typeof key === 'number' || key instanceof Date) && !isNaN(key)) { + } else if ((typeof key === 'number' || key instanceof Date) && !isNaN(key)) { return key } diff --git a/test/custom-tests.js b/test/custom-tests.js index 8086045..234b42c 100644 --- a/test/custom-tests.js +++ b/test/custom-tests.js @@ -22,7 +22,7 @@ module.exports.all = function(leveljs, tape, testCommon) { // This should be covered by abstract-leveldown tests, but that's // prevented by process.browser checks (Level/abstract-leveldown#121). // This test is adapted from memdown. - tape('buffer keys', function (t) { + leveljs.binaryKeys && tape('buffer keys', function (t) { var db = leveljs(testCommon.location()) db.open(function (err) { @@ -60,7 +60,7 @@ module.exports.all = function(leveljs, tape, testCommon) { }) // Adapted from a memdown test. - tape('iterator stringifies buffer input', function (t) { + leveljs.binaryKeys && tape('iterator stringifies buffer input', function (t) { t.plan(6) var db = leveljs(testCommon.location()) From 4dd6909698317d436187bcd92c4b6af76038aa59 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 24 May 2018 18:30:52 +0200 Subject: [PATCH 22/22] remove brfs after levelup fix --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index e86ec94..bb4b2ec 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "license": "MIT", "devDependencies": { "airtap": "0.0.5", - "brfs": "~1.6.1", "browserify": "~16.2.2", "encoding-down": "~5.0.2", "levelup": "~3.0.0",