use rollup for yjs

This commit is contained in:
Kevin Jahns 2017-05-16 18:35:30 +02:00
parent edf47d3491
commit 0a321610aa
17 changed files with 509 additions and 877 deletions

12
.babelrc Normal file
View File

@ -0,0 +1,12 @@
{
"presets": [
["latest", {
"es2015": {
"modules": false
}
}]
],
"plugins": [
"external-helpers"
]
}

View File

@ -1,72 +0,0 @@
/* @flow */
type UserId = string
type Id = [UserId, number|string]
/*
type Struct = {
id: Id,
left?: Id,
right?: Id,
target?: Id,
struct: 'Insert' | 'Delete'
}*/
type Struct = Insertion | Deletion
type Operation = Struct
type Insertion = {
id: Id,
left: ?Id,
origin: ?Id,
right: ?Id,
parent: Id,
parentSub: ?Id,
opContent: ?Id,
content: ?any,
struct: 'Insert'
}
type Deletion = {
target: Id,
struct: 'Delete'
}
type MapStruct = {
id: Id,
type: TypeNames,
map: any
}
type ListStruct = {
id: Id,
type: TypeNames,
start: Id,
end: Id
}
type MessageSyncStep1 = {
type: 'sync step 1',
deleteSet: any,
stateSet: any
}
type MessageSyncStep2 = {
type: 'sync step 2',
os: Array<Operation>,
deleteSet: any,
stateSet: any
}
type MessageUpdate = {
type: 'update',
ops: Array<Operation>
}
type MessageSyncDone = {
type: 'sync done'
}
type Message = MessageSyncStep1 | MessageSyncStep2 | MessageUpdate | MessageSyncDone

View File

View File

@ -1,34 +0,0 @@
/* @flow */
type YGlobal = {
utils: Object,
Struct: any,
AbstractDatabase: any,
AbstractConnector: any,
Transaction: any
}
type YConfig = {
db: Object,
connector: Object,
root: Object
}
type TypeName = 'array' | 'map' | 'text'
declare var YConcurrency_TestingMode : boolean
type Transaction<A> = Generator<any, A, any>
type SyncRole = 'master' | 'slave'
declare class Store {
find: (id:Id) => Transaction<any>;
put: (n:any) => Transaction<void>;
delete: (id:Id) => Transaction<void>;
findWithLowerBound: (start:Id) => Transaction<any>;
findWithUpperBound: (end:Id) => Transaction<any>;
findNext: (id:Id) => Transaction<any>;
findPrev: (id:Id) => Transaction<any>;
iterate: (t:any,start:?Id,end:?Id,gen:any) => Transaction<any>;
}

View File

@ -1,214 +0,0 @@
var $ = require('gulp-load-plugins')()
var minimist = require('minimist')
var browserify = require('browserify')
var source = require('vinyl-source-stream')
var buffer = require('vinyl-buffer')
module.exports = function (gulp, helperOptions) {
var runSequence = require('run-sequence').use(gulp)
var options = minimist(process.argv.slice(2), {
string: ['modulename', 'export', 'name', 'port', 'testfiles', 'es6'],
default: {
moduleName: helperOptions.moduleName,
targetName: helperOptions.targetName,
export: 'ignore',
port: '8888',
testfiles: '**/*.spec.js',
es6: false,
browserify: helperOptions.browserify != null ? helperOptions.browserify : false,
includeRuntime: helperOptions.includeRuntime || false,
debug: false
}
})
if (options.es6 !== false) {
options.es6 = true
}
var files = {
dist: helperOptions.entry,
specs: helperOptions.specs,
src: './src/**/*.js'
}
if (options.includeRuntime) {
files.distEs5 = ['node_modules/regenerator/runtime.js', files.dist]
} else {
files.distEs5 = [files.dist]
}
var header = require('gulp-header')
var banner = ['/**',
' * <%= pkg.name %> - <%= pkg.description %>',
' * @version v<%= pkg.version %>',
' * @link <%= pkg.homepage %>',
' * @license <%= pkg.license %>',
' */',
''].join('\n')
gulp.task('dist:es5', function () {
var babelOptions = {
presets: ['es2015']
}
return (browserify({
entries: files.distEs5,
debug: true,
standalone: options.moduleName
}).transform('babelify', babelOptions)
.bundle()
.pipe(source(options.targetName))
.pipe(buffer())
.pipe($.sourcemaps.init({loadMaps: true}))
.pipe($.if(!options.debug, $.uglify().on('error', function (e) {
console.log('\x07', e.message, JSON.stringify(e)); return this.end()
})))
.pipe(header(banner, { pkg: require('./package.json') }))
.pipe($.sourcemaps.write('.'))
.pipe(gulp.dest('./dist/')))
})
gulp.task('dist:es6', function () {
return (browserify({
entries: files.dist,
debug: true,
standalone: options.moduleName
}).bundle()
.pipe(source(options.targetName))
.pipe(buffer())
.pipe($.sourcemaps.init({loadMaps: true}))
// .pipe($.uglify()) -- generators not yet supported see #448
.pipe($.rename({
extname: '.es6'
}))
.pipe(header(banner, { pkg: require('./package.json') }))
.pipe($.sourcemaps.write('.'))
.pipe(gulp.dest('./dist/')))
})
gulp.task('dist', ['dist:es6', 'dist:es5'])
gulp.task('watch:dist', function (cb) {
options.debug = true
gulp.src(['./README.md'])
.pipe($.watch('./README.md'))
.pipe(gulp.dest('./dist/'))
runSequence('dist', function () {
gulp.watch(files.src.concat('./README.md'), ['dist'])
cb()
})
})
gulp.task('dev:node', ['test'], function () {
gulp.watch(files.src, ['test'])
})
gulp.task('spec-build', function () {
var browserify = require('browserify')
var source = require('vinyl-source-stream')
var buffer = require('vinyl-buffer')
return browserify({
entries: files.specs, // .concat(files.distEs5),
debug: true
})// .transform('babelify', { presets: ['es2015'] })
.bundle()
.pipe(source('specs.js'))
.pipe(buffer())
// .pipe($.sourcemaps.init({loadMaps: true}))
// .pipe($.sourcemaps.write('.'))
.pipe(gulp.dest('./build/'))
})
gulp.task('dev:browser', ['spec-build'], function () {
gulp.watch(files.src, ['spec-build'])
return gulp.src('./build/specs.js')
.pipe($.jasmineBrowser.specRunner())
.pipe($.jasmineBrowser.server({port: options.port}))
})
gulp.task('test', function () {
return gulp.src(files.specs)
.pipe($.jasmine({
verbose: true,
includeStuckTrace: true
}))
})
gulp.task('updateSubmodule', function () {
return gulp.src('./package.json', {read: false})
.pipe($.shell([
'git submodule update --init',
'cd dist && git pull origin dist'
]))
})
gulp.task('bump', function (cb) {
gulp.src(['./package.json', './bower.json', './dist/bower.json'], {base: '.'})
.pipe($.prompt.prompt({
type: 'checkbox',
name: 'bump',
message: 'What type of bump would you like to do?',
choices: ['patch', 'minor', 'major']
}, function (res) {
if (res.bump.length === 0) {
console.info('You have to select a bump type. Now I\'m going to use "patch" as bump type..')
}
var bumptype = res.bump[0]
if (bumptype === 'major') {
runSequence('bump_major', cb)
} else if (bumptype === 'minor') {
runSequence('bump_minor', cb)
} else {
runSequence('bump_patch', cb)
}
}))
})
gulp.task('bump_patch', function () {
return gulp.src(['./package.json', './bower.json', './dist/bower.json'], {base: '.'})
.pipe($.bump({type: 'patch'}))
.pipe(gulp.dest('./'))
})
gulp.task('bump_minor', function () {
return gulp.src(['./package.json', './bower.json', './dist/bower.json'], {base: '.'})
.pipe($.bump({type: 'minor'}))
.pipe(gulp.dest('./'))
})
gulp.task('bump_major', function () {
return gulp.src(['./package.json', './bower.json', './dist/bower.json'], {base: '.'})
.pipe($.bump({type: 'major'}))
.pipe(gulp.dest('./'))
})
gulp.task('publish_commits', function () {
return gulp.src('./package.json')
.pipe($.prompt.confirm({
message: 'Are you sure you want to publish this release?',
default: false
}))
.pipe($.shell([
'cp README.md dist',
'standard',
'echo "Deploying version <%= getVersion(file.path) %>"',
'git pull',
'cd ./dist/ && git add -A',
'cd ./dist/ && git commit -am "Deploy <%= getVersion(file.path) %>" -n',
'cd ./dist/ && git push origin HEAD:dist',
'cd ./dist/ && git tag -a v<%= getVersion(file.path) %> -m "Release <%= getVersion(file.path) %>"',
'cd ./dist/ && git push origin --tags',
'git commit -am "Release <%= getVersion(file.path) %>" -n',
'git push',
'npm publish',
'echo Finished'
], {
templateData: {
getVersion: function () {
return JSON.parse(String.fromCharCode.apply(null, this.file._contents)).version
}
}
}))
})
gulp.task('publish', function (cb) {
/* TODO: include 'test',*/
runSequence('updateSubmodule', 'bump', 'dist', 'publish_commits', cb)
})
}

View File

@ -1,104 +0,0 @@
/* eslint-env node */
/** Gulp Commands
gulp command*
[--export ModuleType]
[--name ModuleName]
[--testport TestPort]
[--testfiles TestFiles]
Module name (ModuleName):
Compile this to "y.js" (default)
Supported module types (ModuleType):
- amd
- amdStrict
- common
- commonStrict
- ignore (default)
- system
- umd
- umdStrict
Test port (TestPort):
Serve the specs on port 8888 (default)
Test files (TestFiles):
Specify which specs to use!
Commands:
- build:deploy
Build this library for deployment (es6->es5, minified)
- dev:browser
Watch the ./src directory.
Builds the library on changes.
Starts an http-server and serves the test suite on http://127.0.0.1:8888.
- dev:node
Watch the ./src directory.
Builds and specs the library on changes.
Usefull to run with node-inspector.
`node-debug $(which gulp) dev:node
- test:
Test this library
*/
var gulp = require('gulp')
var $ = require('gulp-load-plugins')()
var runSequence = require('run-sequence').use(gulp)
require('./gulpfile.helper.js')(gulp, {
polyfills: [],
entry: './src/y.js',
targetName: 'y.js',
moduleName: 'Y',
includeRuntime: true,
specs: [
'./src/Database.spec.js',
'../y-array/src/Array.spec.js',
'../y-map/src/Map.spec.js'
]
})
gulp.task('dev:examples', ['watch:dist'], function () {
// watch all distfiles and copy them to bower_components
var distfiles = ['./dist/*.{js,es6}', './dist/*.{js,es6}.map', '../y-*/dist/*.{js,es6}', '../y-*/dist/*.{js,es6}.map']
gulp.src(distfiles)
.pipe($.watch(distfiles))
.pipe($.rename(function (path) {
var dir = path.dirname.split(/[\\\/]/)[0]
console.log(JSON.stringify(path))
path.dirname = dir === '.' ? 'yjs' : dir
}))
.pipe(gulp.dest('./dist/Examples/bower_components/'))
return $.serve('dist/Examples/')()
})
gulp.task('default', ['updateSubmodule'], function (cb) {
gulp.src('package.json')
.pipe($.prompt.prompt({
type: 'checkbox',
name: 'tasks',
message: 'Which tasks would you like to run?',
choices: [
'test Test this project',
'dev:examples Serve the examples directory in ./dist/',
'dev:browser Watch files & serve the testsuite for the browser',
'dev:nodejs Watch filse & test this project with nodejs',
'bump Bump the current state of the project',
'publish Publish this project. Creates a github tag',
'dist Build the distribution files'
]
}, function (res) {
var tasks = res.tasks.map(function (task) {
return task.split(' ')[0]
})
if (tasks.length > 0) {
console.info('gulp ' + tasks.join(' '))
runSequence(tasks, cb)
} else {
console.info('Ok, .. goodbye')
}
}))
})

View File

@ -4,19 +4,15 @@
"description": "A framework for real-time p2p shared editing on any data",
"main": "./src/y.js",
"scripts": {
"test": "node --harmony ./node_modules/.bin/gulp test",
"lint": "./node_modules/.bin/standard"
"lint": "standard",
"dist": "rollup -c rollup.dist.js"
},
"pre-commit": [
"lint",
"test"
],
"standard": {
"parser": "babel-eslint",
"ignore": [
"build/**",
"dist/**",
"declarations/**",
"./y.js",
"./y.js.map"
]
@ -42,41 +38,22 @@
},
"homepage": "http://y-js.org",
"devDependencies": {
"babel-eslint": "^5.0.0-beta6",
"babel-plugin-transform-runtime": "^6.1.18",
"babel-preset-es2015": "^6.1.18",
"babelify": "^7.2.0",
"browserify": "^12.0.1",
"eslint": "^1.10.2",
"gulp": "^3.9.0",
"gulp-bump": "^1.0.0",
"gulp-concat": "^2.6.0",
"gulp-filter": "^3.0.1",
"gulp-git": "^1.6.0",
"gulp-header": "^1.8.8",
"gulp-if": "^2.0.0",
"gulp-jasmine": "^2.0.1",
"gulp-jasmine-browser": "^0.2.3",
"gulp-load-plugins": "^1.0.0",
"gulp-prompt": "^0.1.2",
"gulp-rename": "^1.2.2",
"gulp-serve": "^1.2.0",
"gulp-shell": "^0.5.1",
"gulp-sourcemaps": "^1.5.2",
"gulp-tag-version": "^1.3.0",
"gulp-uglify": "^2.0.0",
"gulp-util": "^3.0.6",
"gulp-watch": "^4.3.5",
"minimist": "^1.2.0",
"pre-commit": "^1.1.1",
"regenerator": "^0.8.42",
"run-sequence": "^1.1.4",
"seedrandom": "^2.4.2",
"standard": "^5.2.2",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0"
"babel-cli": "^6.24.1",
"babel-plugin-external-helpers": "^6.22.0",
"babel-plugin-transform-regenerator": "^6.24.1",
"babel-plugin-transform-runtime": "^6.23.0",
"rollup-plugin-babel": "^2.7.1",
"rollup-plugin-commonjs": "^8.0.2",
"rollup-plugin-multi-entry": "^2.0.1",
"rollup-plugin-node-resolve": "^3.0.0",
"rollup-plugin-uglify": "^1.0.2",
"rollup-regenerator-runtime": "^6.23.1",
"rollup-watch": "^3.2.2",
"standard": "^10.0.2"
},
"dependencies": {
"debug": "^2.6.3"
"babel-plugin-external-helpers": "^6.22.0",
"babel-preset-latest": "^6.24.1",
"debug": "^2.6.6"
}
}

47
rollup.dist.js Normal file
View File

@ -0,0 +1,47 @@
import inject from 'rollup-plugin-inject'
import babel from 'rollup-plugin-babel'
import uglify from 'rollup-plugin-uglify'
import nodeResolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
var pkg = require('./package.json')
export default {
entry: 'src/y.js',
moduleName: 'yjs',
format: 'umd',
plugins: [
nodeResolve({
main: true,
module: true,
browser: true
}),
commonjs(),
babel({
runtimeHelpers: true
}),
inject({
regeneratorRuntime: 'regenerator-runtime'
}),
uglify({
output: {
comments: function (node, comment) {
var text = comment.value
var type = comment.type
if (type === 'comment2') {
// multiline comment
return /@license/i.test(text)
}
}
}
})
],
dest: 'y.js',
sourceMap: true,
banner: `
/**
* ${pkg.name} - ${pkg.description}
* @version v${pkg.version}
* @license ${pkg.license}
*/
`
}

20
rollup.test.js Normal file
View File

@ -0,0 +1,20 @@
import nodeResolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import multiEntry from 'rollup-plugin-multi-entry'
export default {
entry: 'tests/*.js',
moduleName: 'y-array-tests',
format: 'umd',
plugins: [
nodeResolve({
main: true,
module: true,
browser: true
}),
commonjs(),
multiEntry()
],
dest: 'y-array.test.js',
sourceMap: true
}

View File

@ -4,7 +4,7 @@
function canRead (auth) { return auth === 'read' || auth === 'write' }
function canWrite (auth) { return auth === 'write' }
module.exports = function (Y/* :any */) {
export default function extendConnector (Y/* :any */) {
class AbstractConnector {
/* ::
y: YConfig;
@ -113,7 +113,7 @@ module.exports = function (Y/* :any */) {
this.userEventListeners.push(f)
}
removeUserEventListener (f) {
this.userEventListeners = this.userEventListeners.filter(g => { f !== g })
this.userEventListeners = this.userEventListeners.filter(g => f !== g)
}
userLeft (user) {
if (this.connections[user] != null) {
@ -181,9 +181,9 @@ module.exports = function (Y/* :any */) {
var conn = this
if (syncUser != null) {
this.currentSyncTarget = syncUser
this.y.db.requestTransaction(function *() {
var stateSet = yield* this.getStateSet()
var deleteSet = yield* this.getDeleteSet()
this.y.db.requestTransaction(function * () {
var stateSet = yield * this.getStateSet()
var deleteSet = yield * this.getDeleteSet()
var answer = {
type: 'sync step 1',
stateSet: stateSet,
@ -198,11 +198,11 @@ module.exports = function (Y/* :any */) {
})
} else {
if (!conn.isSynced) {
this.y.db.requestTransaction(function *() {
this.y.db.requestTransaction(function * () {
if (!conn.isSynced) {
// it is crucial that isSynced is set at the time garbageCollectAfterSync is called
conn.isSynced = true
yield* this.garbageCollectAfterSync()
yield * this.garbageCollectAfterSync()
// call whensynced listeners
for (var f of conn.whenSyncedListeners) {
f()
@ -268,7 +268,7 @@ module.exports = function (Y/* :any */) {
type: 'sync stop',
protocolVersion: this.protocolVersion
})
return Promise.reject('Incompatible protocol version')
return Promise.reject(new Error('Incompatible protocol version'))
}
if (message.auth != null && this.connections[sender] != null) {
// authenticate using auth in message
@ -293,13 +293,13 @@ module.exports = function (Y/* :any */) {
let conn = this
let m = message
this.y.db.requestTransaction(function *() {
var currentStateSet = yield* this.getStateSet()
this.y.db.requestTransaction(function * () {
var currentStateSet = yield * this.getStateSet()
if (canWrite(auth)) {
yield* this.applyDeleteSet(m.deleteSet)
yield * this.applyDeleteSet(m.deleteSet)
}
var ds = yield* this.getDeleteSet()
var ds = yield * this.getDeleteSet()
var answer = {
type: 'sync step 2',
stateSet: currentStateSet,
@ -308,9 +308,9 @@ module.exports = function (Y/* :any */) {
auth: this.authInfo
}
if (message.preferUntransformed === true && Object.keys(m.stateSet).length === 0) {
answer.osUntransformed = yield* this.getOperationsUntransformed()
answer.osUntransformed = yield * this.getOperationsUntransformed()
} else {
answer.os = yield* this.getOperations(m.stateSet)
answer.os = yield * this.getOperations(m.stateSet)
}
conn.send(sender, answer)
if (this.forwardToSyncingClients) {
@ -338,9 +338,9 @@ module.exports = function (Y/* :any */) {
this.syncStep2 = defer.promise
let m /* :MessageSyncStep2 */ = message
db.requestTransaction(function * () {
yield* this.applyDeleteSet(m.deleteSet)
yield * this.applyDeleteSet(m.deleteSet)
if (m.osUntransformed != null) {
yield* this.applyOperationsUntransformed(m.osUntransformed, m.stateSet)
yield * this.applyOperationsUntransformed(m.osUntransformed, m.stateSet)
} else {
this.store.apply(m.os)
}
@ -388,7 +388,7 @@ module.exports = function (Y/* :any */) {
}
})
} else {
return Promise.reject('Unable to deliver message')
return Promise.reject(new Error('Unable to deliver message'))
}
}
_setSyncedWith (user) {

View File

@ -1,7 +1,7 @@
/* @flow */
'use strict'
module.exports = function (Y /* :any */) {
export default function extendDatabase (Y /* :any */) {
/*
Partial definition of an OperationStore.
TODO: name it Database, operation store only holds operations.
@ -42,11 +42,11 @@ module.exports = function (Y /* :any */) {
this.dbOpts = opts
var os = this
this.userId = null
var resolve
this.userIdPromise = new Promise(function (r) {
resolve = r
var resolve_
this.userIdPromise = new Promise(function (resolve) {
resolve_ = resolve
})
this.userIdPromise.resolve = resolve
this.userIdPromise.resolve = resolve_
// whether to broadcast all applied operations (insert & delete hook)
this.forwardAppliedOperations = false
// E.g. this.listenersById[id] : Array<Listener>
@ -71,7 +71,7 @@ module.exports = function (Y /* :any */) {
this.waitingTransactions = []
this.transactionInProgress = false
this.transactionIsFlushed = false
if (typeof YConcurrency_TestingMode !== 'undefined') {
if (typeof YConcurrencyTestingMode !== 'undefined') {
this.executeOrder = []
}
this.gc1 = [] // first stage
@ -88,7 +88,7 @@ module.exports = function (Y /* :any */) {
if (os.y.connector != null && os.y.connector.isSynced) {
for (var i = 0; i < os.gc2.length; i++) {
var oid = os.gc2[i]
yield* this.garbageCollectOperation(oid)
yield * this.garbageCollectOperation(oid)
}
os.gc2 = os.gc1
os.gc1 = []
@ -177,7 +177,7 @@ module.exports = function (Y /* :any */) {
})
}
addToDebug () {
if (typeof YConcurrency_TestingMode !== 'undefined') {
if (typeof YConcurrencyTestingMode !== 'undefined') {
var command /* :string */ = Array.prototype.map.call(arguments, function (s) {
if (typeof s === 'string') {
return s
@ -201,10 +201,10 @@ module.exports = function (Y /* :any */) {
self.gc1 = []
self.gc2 = []
for (var i = 0; i < ungc.length; i++) {
var op = yield* this.getOperation(ungc[i])
var op = yield * this.getOperation(ungc[i])
if (op != null) {
delete op.gc
yield* this.setOperation(op)
yield * this.setOperation(op)
}
}
resolve()
@ -234,12 +234,12 @@ module.exports = function (Y /* :any */) {
if (left != null && left.deleted === true) {
gc = true
} else if (op.content != null && op.content.length > 1) {
op = yield* this.getInsertionCleanStart([op.id[0], op.id[1] + 1])
op = yield * this.getInsertionCleanStart([op.id[0], op.id[1] + 1])
gc = true
}
if (gc) {
op.gc = true
yield* this.setOperation(op)
yield * this.setOperation(op)
this.store.queueGarbageCollector(op.id)
return true
}
@ -275,7 +275,7 @@ module.exports = function (Y /* :any */) {
var self = this
self.requestTransaction(function * () {
self.userId = userId
var state = yield* this.getState(userId)
var state = yield * this.getState(userId)
self.opClock = state.clock
self.userIdPromise.resolve(userId)
})
@ -363,7 +363,7 @@ module.exports = function (Y /* :any */) {
for (let key = 0; key < exeNow.length; key++) {
let o = exeNow[key].op
yield* store.tryExecute.call(this, o)
yield * store.tryExecute.call(this, o)
}
for (var sid in ls) {
@ -371,9 +371,9 @@ module.exports = function (Y /* :any */) {
var id = JSON.parse(sid)
var op
if (typeof id[1] === 'string') {
op = yield* this.getOperation(id)
op = yield * this.getOperation(id)
} else {
op = yield* this.getInsertion(id)
op = yield * this.getInsertion(id)
}
if (op == null) {
store.listenersById[sid] = l
@ -382,7 +382,7 @@ module.exports = function (Y /* :any */) {
let listener = l[i]
let o = listener.op
if (--listener.missing === 0) {
yield* store.tryExecute.call(this, o)
yield * store.tryExecute.call(this, o)
}
}
}
@ -402,12 +402,12 @@ module.exports = function (Y /* :any */) {
* tryExecute (op) {
this.store.addToDebug('yield* this.store.tryExecute.call(this, ', JSON.stringify(op), ')')
if (op.struct === 'Delete') {
yield* Y.Struct.Delete.execute.call(this, op)
yield * Y.Struct.Delete.execute.call(this, op)
// this is now called in Transaction.deleteOperation!
// yield* this.store.operationAdded(this, op)
} else {
// check if this op was defined
var defined = yield* this.getInsertion(op.id)
var defined = yield * this.getInsertion(op.id)
while (defined != null && defined.content != null) {
// check if this op has a longer content in the case it is defined
if (defined.id[1] + defined.content.length < op.id[1] + op.content.length) {
@ -416,23 +416,23 @@ module.exports = function (Y /* :any */) {
op.id = [op.id[0], op.id[1] + overlapSize]
op.left = Y.utils.getLastId(defined)
op.origin = op.left
defined = yield* this.getOperation(op.id) // getOperation suffices here
defined = yield * this.getOperation(op.id) // getOperation suffices here
} else {
break
}
}
if (defined == null) {
var opid = op.id
var isGarbageCollected = yield* this.isGarbageCollected(opid)
var isGarbageCollected = yield * this.isGarbageCollected(opid)
if (!isGarbageCollected) {
// TODO: reduce number of get / put calls for op ..
yield* Y.Struct[op.struct].execute.call(this, op)
yield* this.addOperation(op)
yield* this.store.operationAdded(this, op)
yield * Y.Struct[op.struct].execute.call(this, op)
yield * this.addOperation(op)
yield * this.store.operationAdded(this, op)
// operationAdded can change op..
op = yield* this.getOperation(opid)
op = yield * this.getOperation(opid)
// if insertion, try to combine with left
yield* this.tryCombineWithLeft(op)
yield * this.tryCombineWithLeft(op)
}
}
}
@ -453,11 +453,11 @@ module.exports = function (Y /* :any */) {
if (op.struct === 'Delete') {
var type = this.initializedTypes[JSON.stringify(op.targetParent)]
if (type != null) {
yield* type._changed(transaction, op)
yield * type._changed(transaction, op)
}
} else {
// increase SS
yield* transaction.updateState(op.id[0])
yield * transaction.updateState(op.id[0])
var opLen = op.content != null ? op.content.length : 1
for (let i = 0; i < opLen; i++) {
// notify whenOperation listeners (by id)
@ -477,9 +477,9 @@ module.exports = function (Y /* :any */) {
// if parent is deleted, mark as gc'd and return
if (op.parent != null) {
var parentIsDeleted = yield* transaction.isDeleted(op.parent)
var parentIsDeleted = yield * transaction.isDeleted(op.parent)
if (parentIsDeleted) {
yield* transaction.deleteList(op.id)
yield * transaction.deleteList(op.id)
return
}
}
@ -487,7 +487,7 @@ module.exports = function (Y /* :any */) {
// notify parent, if it was instanciated as a custom type
if (t != null) {
let o = Y.utils.copyOperation(op)
yield* t._changed(transaction, o)
yield * t._changed(transaction, o)
}
if (!op.deleted) {
// Delete if DS says this is actually deleted
@ -496,13 +496,13 @@ module.exports = function (Y /* :any */) {
// TODO: !! console.log('TODO: change this before commiting')
for (let i = 0; i < len; i++) {
var id = [startId[0], startId[1] + i]
var opIsDeleted = yield* transaction.isDeleted(id)
var opIsDeleted = yield * transaction.isDeleted(id)
if (opIsDeleted) {
var delop = {
struct: 'Delete',
target: id
}
yield* this.tryExecute.call(transaction, delop)
yield * this.tryExecute.call(transaction, delop)
}
}
}
@ -511,12 +511,12 @@ module.exports = function (Y /* :any */) {
whenTransactionsFinished () {
if (this.transactionInProgress) {
if (this.transactionsFinished == null) {
var resolve
var promise = new Promise(function (r) {
resolve = r
var resolve_
var promise = new Promise(function (resolve) {
resolve_ = resolve
})
this.transactionsFinished = {
resolve: resolve,
resolve: resolve_,
promise: promise
}
}
@ -540,7 +540,7 @@ module.exports = function (Y /* :any */) {
} else {
this.transactionIsFlushed = true
return function * () {
yield* this.flush()
yield * this.flush()
}
}
} else {
@ -571,9 +571,9 @@ module.exports = function (Y /* :any */) {
var sid = JSON.stringify(id)
var t = this.store.initializedTypes[sid]
if (t == null) {
var op/* :MapStruct | ListStruct */ = yield* this.getOperation(id)
var op/* :MapStruct | ListStruct */ = yield * this.getOperation(id)
if (op != null) {
t = yield* Y[op.type].typeDefinition.initType.call(this, this.store, op, args)
t = yield * Y[op.type].typeDefinition.initType.call(this, this.store, op, args)
this.store.initializedTypes[sid] = t
}
}
@ -590,9 +590,9 @@ module.exports = function (Y /* :any */) {
this.requestTransaction(function * () {
if (op.id[0] === '_') {
yield* this.setOperation(op)
yield * this.setOperation(op)
} else {
yield* this.applyCreatedOperations([op])
yield * this.applyCreatedOperations([op])
}
})
var t = Y[op.type].typeDefinition.createType(this, op, typedefinition[1])

View File

@ -17,141 +17,141 @@ for (let database of databases) {
})
afterEach(function (done) {
store.requestTransaction(function * () {
yield* this.store.destroy()
yield * this.store.destroy()
done()
})
})
it('Deleted operation is deleted', async(function * (done) {
store.requestTransaction(function * () {
yield* this.markDeleted(['u1', 10], 1)
expect(yield* this.isDeleted(['u1', 10])).toBeTruthy()
expect(yield* this.getDeleteSet()).toEqual({'u1': [[10, 1, false]]})
yield * this.markDeleted(['u1', 10], 1)
expect(yield * this.isDeleted(['u1', 10])).toBeTruthy()
expect(yield * this.getDeleteSet()).toEqual({'u1': [[10, 1, false]]})
done()
})
}))
it('Deleted operation extends other deleted operation', async(function * (done) {
store.requestTransaction(function * () {
yield* this.markDeleted(['u1', 10], 1)
yield* this.markDeleted(['u1', 11], 1)
expect(yield* this.isDeleted(['u1', 10])).toBeTruthy()
expect(yield* this.isDeleted(['u1', 11])).toBeTruthy()
expect(yield* this.getDeleteSet()).toEqual({'u1': [[10, 2, false]]})
yield * this.markDeleted(['u1', 10], 1)
yield * this.markDeleted(['u1', 11], 1)
expect(yield * this.isDeleted(['u1', 10])).toBeTruthy()
expect(yield * this.isDeleted(['u1', 11])).toBeTruthy()
expect(yield * this.getDeleteSet()).toEqual({'u1': [[10, 2, false]]})
done()
})
}))
it('Deleted operation extends other deleted operation', async(function * (done) {
store.requestTransaction(function * () {
yield* this.markDeleted(['0', 3], 1)
yield* this.markDeleted(['0', 4], 1)
yield* this.markDeleted(['0', 2], 1)
expect(yield* this.getDeleteSet()).toEqual({'0': [[2, 3, false]]})
yield * this.markDeleted(['0', 3], 1)
yield * this.markDeleted(['0', 4], 1)
yield * this.markDeleted(['0', 2], 1)
expect(yield * this.getDeleteSet()).toEqual({'0': [[2, 3, false]]})
done()
})
}))
it('Debug #1', async(function * (done) {
store.requestTransaction(function * () {
yield* this.markDeleted(['166', 0], 1)
yield* this.markDeleted(['166', 2], 1)
yield* this.markDeleted(['166', 0], 1)
yield* this.markDeleted(['166', 2], 1)
yield* this.markGarbageCollected(['166', 2], 1)
yield* this.markDeleted(['166', 1], 1)
yield* this.markDeleted(['166', 3], 1)
yield* this.markGarbageCollected(['166', 3], 1)
yield* this.markDeleted(['166', 0], 1)
expect(yield* this.getDeleteSet()).toEqual({'166': [[0, 2, false], [2, 2, true]]})
yield * this.markDeleted(['166', 0], 1)
yield * this.markDeleted(['166', 2], 1)
yield * this.markDeleted(['166', 0], 1)
yield * this.markDeleted(['166', 2], 1)
yield * this.markGarbageCollected(['166', 2], 1)
yield * this.markDeleted(['166', 1], 1)
yield * this.markDeleted(['166', 3], 1)
yield * this.markGarbageCollected(['166', 3], 1)
yield * this.markDeleted(['166', 0], 1)
expect(yield * this.getDeleteSet()).toEqual({'166': [[0, 2, false], [2, 2, true]]})
done()
})
}))
it('Debug #2', async(function * (done) {
store.requestTransaction(function * () {
yield* this.markDeleted(['293', 0], 1)
yield* this.markDeleted(['291', 2], 1)
yield* this.markDeleted(['291', 2], 1)
yield* this.markGarbageCollected(['293', 0], 1)
yield* this.markDeleted(['293', 1], 1)
yield* this.markGarbageCollected(['291', 2], 1)
expect(yield* this.getDeleteSet()).toEqual({'291': [[2, 1, true]], '293': [[0, 1, true], [1, 1, false]]})
yield * this.markDeleted(['293', 0], 1)
yield * this.markDeleted(['291', 2], 1)
yield * this.markDeleted(['291', 2], 1)
yield * this.markGarbageCollected(['293', 0], 1)
yield * this.markDeleted(['293', 1], 1)
yield * this.markGarbageCollected(['291', 2], 1)
expect(yield * this.getDeleteSet()).toEqual({'291': [[2, 1, true]], '293': [[0, 1, true], [1, 1, false]]})
done()
})
}))
it('Debug #3', async(function * (done) {
store.requestTransaction(function * () {
yield* this.markDeleted(['581', 0], 1)
yield* this.markDeleted(['581', 1], 1)
yield* this.markDeleted(['580', 0], 1)
yield* this.markDeleted(['580', 0], 1)
yield* this.markGarbageCollected(['581', 0], 1)
yield* this.markDeleted(['581', 2], 1)
yield* this.markDeleted(['580', 1], 1)
yield* this.markDeleted(['580', 2], 1)
yield* this.markDeleted(['580', 1], 1)
yield* this.markDeleted(['580', 2], 1)
yield* this.markGarbageCollected(['581', 2], 1)
yield* this.markGarbageCollected(['581', 1], 1)
yield* this.markGarbageCollected(['580', 1], 1)
expect(yield* this.getDeleteSet()).toEqual({'580': [[0, 1, false], [1, 1, true], [2, 1, false]], '581': [[0, 3, true]]})
yield * this.markDeleted(['581', 0], 1)
yield * this.markDeleted(['581', 1], 1)
yield * this.markDeleted(['580', 0], 1)
yield * this.markDeleted(['580', 0], 1)
yield * this.markGarbageCollected(['581', 0], 1)
yield * this.markDeleted(['581', 2], 1)
yield * this.markDeleted(['580', 1], 1)
yield * this.markDeleted(['580', 2], 1)
yield * this.markDeleted(['580', 1], 1)
yield * this.markDeleted(['580', 2], 1)
yield * this.markGarbageCollected(['581', 2], 1)
yield * this.markGarbageCollected(['581', 1], 1)
yield * this.markGarbageCollected(['580', 1], 1)
expect(yield * this.getDeleteSet()).toEqual({'580': [[0, 1, false], [1, 1, true], [2, 1, false]], '581': [[0, 3, true]]})
done()
})
}))
it('Debug #4', async(function * (done) {
store.requestTransaction(function * () {
yield* this.markDeleted(['544', 0], 1)
yield* this.markDeleted(['543', 2], 1)
yield* this.markDeleted(['544', 0], 1)
yield* this.markDeleted(['543', 2], 1)
yield* this.markGarbageCollected(['544', 0], 1)
yield* this.markDeleted(['545', 1], 1)
yield* this.markDeleted(['543', 4], 1)
yield* this.markDeleted(['543', 3], 1)
yield* this.markDeleted(['544', 1], 1)
yield* this.markDeleted(['544', 2], 1)
yield* this.markDeleted(['544', 1], 1)
yield* this.markDeleted(['544', 2], 1)
yield* this.markGarbageCollected(['543', 2], 1)
yield* this.markGarbageCollected(['543', 4], 1)
yield* this.markGarbageCollected(['544', 2], 1)
yield* this.markGarbageCollected(['543', 3], 1)
expect(yield* this.getDeleteSet()).toEqual({'543': [[2, 3, true]], '544': [[0, 1, true], [1, 1, false], [2, 1, true]], '545': [[1, 1, false]]})
yield * this.markDeleted(['544', 0], 1)
yield * this.markDeleted(['543', 2], 1)
yield * this.markDeleted(['544', 0], 1)
yield * this.markDeleted(['543', 2], 1)
yield * this.markGarbageCollected(['544', 0], 1)
yield * this.markDeleted(['545', 1], 1)
yield * this.markDeleted(['543', 4], 1)
yield * this.markDeleted(['543', 3], 1)
yield * this.markDeleted(['544', 1], 1)
yield * this.markDeleted(['544', 2], 1)
yield * this.markDeleted(['544', 1], 1)
yield * this.markDeleted(['544', 2], 1)
yield * this.markGarbageCollected(['543', 2], 1)
yield * this.markGarbageCollected(['543', 4], 1)
yield * this.markGarbageCollected(['544', 2], 1)
yield * this.markGarbageCollected(['543', 3], 1)
expect(yield * this.getDeleteSet()).toEqual({'543': [[2, 3, true]], '544': [[0, 1, true], [1, 1, false], [2, 1, true]], '545': [[1, 1, false]]})
done()
})
}))
it('Debug #5', async(function * (done) {
store.requestTransaction(function * () {
yield* this.applyDeleteSet({'16': [[1, 2, false]], '17': [[0, 1, true], [1, 3, false]]})
expect(yield* this.getDeleteSet()).toEqual({'16': [[1, 2, false]], '17': [[0, 1, true], [1, 3, false]]})
yield* this.applyDeleteSet({'16': [[1, 2, false]], '17': [[0, 4, true]]})
expect(yield* this.getDeleteSet()).toEqual({'16': [[1, 2, false]], '17': [[0, 4, true]]})
yield * this.applyDeleteSet({'16': [[1, 2, false]], '17': [[0, 1, true], [1, 3, false]]})
expect(yield * this.getDeleteSet()).toEqual({'16': [[1, 2, false]], '17': [[0, 1, true], [1, 3, false]]})
yield * this.applyDeleteSet({'16': [[1, 2, false]], '17': [[0, 4, true]]})
expect(yield * this.getDeleteSet()).toEqual({'16': [[1, 2, false]], '17': [[0, 4, true]]})
done()
})
}))
it('Debug #6', async(function * (done) {
store.requestTransaction(function * () {
yield* this.applyDeleteSet({'40': [[0, 3, false]]})
expect(yield* this.getDeleteSet()).toEqual({'40': [[0, 3, false]]})
yield* this.applyDeleteSet({'39': [[2, 2, false]], '40': [[0, 1, true], [1, 2, false]], '41': [[2, 1, false]]})
expect(yield* this.getDeleteSet()).toEqual({'39': [[2, 2, false]], '40': [[0, 1, true], [1, 2, false]], '41': [[2, 1, false]]})
yield * this.applyDeleteSet({'40': [[0, 3, false]]})
expect(yield * this.getDeleteSet()).toEqual({'40': [[0, 3, false]]})
yield * this.applyDeleteSet({'39': [[2, 2, false]], '40': [[0, 1, true], [1, 2, false]], '41': [[2, 1, false]]})
expect(yield * this.getDeleteSet()).toEqual({'39': [[2, 2, false]], '40': [[0, 1, true], [1, 2, false]], '41': [[2, 1, false]]})
done()
})
}))
it('Debug #7', async(function * (done) {
store.requestTransaction(function * () {
yield* this.markDeleted(['9', 2], 1)
yield* this.markDeleted(['11', 2], 1)
yield* this.markDeleted(['11', 4], 1)
yield* this.markDeleted(['11', 1], 1)
yield* this.markDeleted(['9', 4], 1)
yield* this.markDeleted(['10', 0], 1)
yield* this.markGarbageCollected(['11', 2], 1)
yield* this.markDeleted(['11', 2], 1)
yield* this.markGarbageCollected(['11', 3], 1)
yield* this.markDeleted(['11', 3], 1)
yield* this.markDeleted(['11', 3], 1)
yield* this.markDeleted(['9', 4], 1)
yield* this.markDeleted(['10', 0], 1)
yield* this.markGarbageCollected(['11', 1], 1)
yield* this.markDeleted(['11', 1], 1)
expect(yield* this.getDeleteSet()).toEqual({'9': [[2, 1, false], [4, 1, false]], '10': [[0, 1, false]], '11': [[1, 3, true], [4, 1, false]]})
yield * this.markDeleted(['9', 2], 1)
yield * this.markDeleted(['11', 2], 1)
yield * this.markDeleted(['11', 4], 1)
yield * this.markDeleted(['11', 1], 1)
yield * this.markDeleted(['9', 4], 1)
yield * this.markDeleted(['10', 0], 1)
yield * this.markGarbageCollected(['11', 2], 1)
yield * this.markDeleted(['11', 2], 1)
yield * this.markGarbageCollected(['11', 3], 1)
yield * this.markDeleted(['11', 3], 1)
yield * this.markDeleted(['11', 3], 1)
yield * this.markDeleted(['9', 4], 1)
yield * this.markDeleted(['10', 0], 1)
yield * this.markGarbageCollected(['11', 1], 1)
yield * this.markDeleted(['11', 1], 1)
expect(yield * this.getDeleteSet()).toEqual({'9': [[2, 1, false], [4, 1, false]], '10': [[0, 1, false]], '11': [[1, 3, true], [4, 1, false]]})
done()
})
}))
@ -167,54 +167,54 @@ for (let database of databases) {
})
afterEach(function (done) {
store.requestTransaction(function * () {
yield* this.store.destroy()
yield * this.store.destroy()
done()
})
})
it('debug #1', function (done) {
store.requestTransaction(function * () {
yield* this.os.put({id: [2]})
yield* this.os.put({id: [0]})
yield* this.os.delete([2])
yield* this.os.put({id: [1]})
expect(yield* this.os.find([0])).toBeTruthy()
expect(yield* this.os.find([1])).toBeTruthy()
expect(yield* this.os.find([2])).toBeFalsy()
yield * this.os.put({id: [2]})
yield * this.os.put({id: [0]})
yield * this.os.delete([2])
yield * this.os.put({id: [1]})
expect(yield * this.os.find([0])).toBeTruthy()
expect(yield * this.os.find([1])).toBeTruthy()
expect(yield * this.os.find([2])).toBeFalsy()
done()
})
})
it('can add&retrieve 5 elements', function (done) {
store.requestTransaction(function * () {
yield* this.os.put({val: 'four', id: [4]})
yield* this.os.put({val: 'one', id: [1]})
yield* this.os.put({val: 'three', id: [3]})
yield* this.os.put({val: 'two', id: [2]})
yield* this.os.put({val: 'five', id: [5]})
expect((yield* this.os.find([1])).val).toEqual('one')
expect((yield* this.os.find([2])).val).toEqual('two')
expect((yield* this.os.find([3])).val).toEqual('three')
expect((yield* this.os.find([4])).val).toEqual('four')
expect((yield* this.os.find([5])).val).toEqual('five')
yield * this.os.put({val: 'four', id: [4]})
yield * this.os.put({val: 'one', id: [1]})
yield * this.os.put({val: 'three', id: [3]})
yield * this.os.put({val: 'two', id: [2]})
yield * this.os.put({val: 'five', id: [5]})
expect((yield * this.os.find([1])).val).toEqual('one')
expect((yield * this.os.find([2])).val).toEqual('two')
expect((yield * this.os.find([3])).val).toEqual('three')
expect((yield * this.os.find([4])).val).toEqual('four')
expect((yield * this.os.find([5])).val).toEqual('five')
done()
})
})
it('5 elements do not exist anymore after deleting them', function (done) {
store.requestTransaction(function * () {
yield* this.os.put({val: 'four', id: [4]})
yield* this.os.put({val: 'one', id: [1]})
yield* this.os.put({val: 'three', id: [3]})
yield* this.os.put({val: 'two', id: [2]})
yield* this.os.put({val: 'five', id: [5]})
yield* this.os.delete([4])
expect(yield* this.os.find([4])).not.toBeTruthy()
yield* this.os.delete([3])
expect(yield* this.os.find([3])).not.toBeTruthy()
yield* this.os.delete([2])
expect(yield* this.os.find([2])).not.toBeTruthy()
yield* this.os.delete([1])
expect(yield* this.os.find([1])).not.toBeTruthy()
yield* this.os.delete([5])
expect(yield* this.os.find([5])).not.toBeTruthy()
yield * this.os.put({val: 'four', id: [4]})
yield * this.os.put({val: 'one', id: [1]})
yield * this.os.put({val: 'three', id: [3]})
yield * this.os.put({val: 'two', id: [2]})
yield * this.os.put({val: 'five', id: [5]})
yield * this.os.delete([4])
expect(yield * this.os.find([4])).not.toBeTruthy()
yield * this.os.delete([3])
expect(yield * this.os.find([3])).not.toBeTruthy()
yield * this.os.delete([2])
expect(yield * this.os.find([2])).not.toBeTruthy()
yield * this.os.delete([1])
expect(yield * this.os.find([1])).not.toBeTruthy()
yield * this.os.delete([5])
expect(yield * this.os.find([5])).not.toBeTruthy()
done()
})
})
@ -232,9 +232,9 @@ for (let database of databases) {
var r = Math.random()
if (r < 0.8) {
var obj = [Math.floor(Math.random() * numberOfOSTests * 10000)]
if (!(yield* this.os.find(obj))) {
if (!(yield * this.os.find(obj))) {
elements.push(obj)
yield* this.os.put({id: obj})
yield * this.os.put({id: obj})
}
} else if (elements.length > 0) {
var elemid = Math.floor(Math.random() * elements.length)
@ -242,7 +242,7 @@ for (let database of databases) {
elements = elements.filter(function (e) {
return !Y.utils.compareIds(e, elem)
})
yield* this.os.delete(elem)
yield * this.os.delete(elem)
}
}
done()
@ -250,14 +250,14 @@ for (let database of databases) {
})
afterAll(function (done) {
store.requestTransaction(function * () {
yield* this.store.destroy()
yield * this.store.destroy()
done()
})
})
it('can find every object', function (done) {
store.requestTransaction(function * () {
for (var id of elements) {
expect((yield* this.os.find(id)).id).toEqual(id)
expect((yield * this.os.find(id)).id).toEqual(id)
}
done()
})
@ -266,7 +266,7 @@ for (let database of databases) {
it('can find every object with lower bound search', function (done) {
store.requestTransaction(function * () {
for (var id of elements) {
var e = yield* this.os.findWithLowerBound(id)
var e = yield * this.os.findWithLowerBound(id)
expect(e.id).toEqual(id)
}
done()
@ -281,7 +281,7 @@ for (let database of databases) {
var actualResults = 0
store.requestTransaction(function * () {
yield* this.os.iterate(this, lowerBound, null, function * (val) {
yield * this.os.iterate(this, lowerBound, null, function * (val) {
expect(val).toBeDefined()
actualResults++
})
@ -297,7 +297,7 @@ for (let database of databases) {
}).length
var actualResults = 0
store.requestTransaction(function * () {
yield* this.os.iterate(this, lowerBound, null, function * (val) {
yield * this.os.iterate(this, lowerBound, null, function * (val) {
expect(val).toBeDefined()
actualResults++
})
@ -314,7 +314,7 @@ for (let database of databases) {
var actualResults = 0
store.requestTransaction(function * () {
yield* this.os.iterate(this, null, upperBound, function * (val) {
yield * this.os.iterate(this, null, upperBound, function * (val) {
expect(val).toBeDefined()
actualResults++
})
@ -340,7 +340,7 @@ for (let database of databases) {
}).length
var actualResults = 0
store.requestTransaction(function * () {
yield* this.os.iterate(this, lowerBound, upperBound, function * (val) {
yield * this.os.iterate(this, lowerBound, upperBound, function * (val) {
expect(val).toBeDefined()
actualResults++
})

View File

@ -46,7 +46,7 @@ g.setRandomSeed = function setRandomSeed (seed) {
g.generateRandomSeed()
g.YConcurrency_TestingMode = true
g.YConcurrencyTestingMode = true
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200000
@ -168,7 +168,7 @@ function fixAwaitingInType (type) {
type.os.requestTransaction(function * () {
if (type.eventHandler.awaiting > 0 && type.eventHandler._debuggingAwaiting === true) {
type.eventHandler._debuggingAwaiting = false
yield* type.eventHandler.awaitOps(this, function * () { /* mock function */ })
yield * type.eventHandler.awaitOps(this, function * () { /* mock function */ })
}
wait(50).then(type.os.whenTransactionsFinished()).then(wait(50)).then(resolve)
})
@ -178,13 +178,13 @@ function fixAwaitingInType (type) {
g.fixAwaitingInType = fixAwaitingInType
g.applyRandomTransactionsNoGCNoDisconnect = async(function * applyRandomTransactions (users, objects, transactions, numberOfTransactions) {
yield* applyTransactions(1, numberOfTransactions, objects, users, transactions, true)
yield * applyTransactions(1, numberOfTransactions, objects, users, transactions, true)
yield Y.utils.globalRoom.flushAll()
yield Promise.all(objects.map(fixAwaitingInType))
})
g.applyRandomTransactionsAllRejoinNoGC = async(function * applyRandomTransactions (users, objects, transactions, numberOfTransactions) {
yield* applyTransactions(1, numberOfTransactions, objects, users, transactions)
yield * applyTransactions(1, numberOfTransactions, objects, users, transactions)
yield Promise.all(objects.map(fixAwaitingInType))
yield Y.utils.globalRoom.flushAll()
yield Promise.all(objects.map(fixAwaitingInType))
@ -200,7 +200,7 @@ g.applyRandomTransactionsAllRejoinNoGC = async(function * applyRandomTransaction
})
g.applyRandomTransactionsWithGC = async(function * applyRandomTransactions (users, objects, transactions, numberOfTransactions) {
yield* applyTransactions(1, numberOfTransactions, objects, users.slice(1), transactions)
yield * applyTransactions(1, numberOfTransactions, objects, users.slice(1), transactions)
yield Y.utils.globalRoom.flushAll()
yield Promise.all(objects.map(fixAwaitingInType))
for (var u in users) {
@ -242,18 +242,18 @@ g.compareAllUsers = async(function * compareAllUsers (users) {
// t1 and t2 basically do the same. They define t[1,2], ds[1,2], and allDels[1,2]
function * t1 () {
s1 = yield* this.getStateSet()
ds1 = yield* this.getDeleteSet()
s1 = yield * this.getStateSet()
ds1 = yield * this.getDeleteSet()
allDels1 = []
yield* this.ds.iterate(this, null, null, function * (d) {
yield * this.ds.iterate(this, null, null, function * (d) {
allDels1.push(d)
})
}
function * t2 () {
s2 = yield* this.getStateSet()
ds2 = yield* this.getDeleteSet()
s2 = yield * this.getStateSet()
ds2 = yield * this.getDeleteSet()
allDels2 = []
yield* this.ds.iterate(this, null, null, function * (d) {
yield * this.ds.iterate(this, null, null, function * (d) {
allDels2.push(d)
})
}
@ -269,25 +269,25 @@ g.compareAllUsers = async(function * compareAllUsers (users) {
for (var uid = 0; uid < users.length; uid++) {
var u = users[uid]
u.db.requestTransaction(function * () {
var sv = yield* this.getStateVector()
var sv = yield * this.getStateVector()
for (var s of sv) {
yield* this.updateState(s.user)
yield * this.updateState(s.user)
}
// compare deleted ops against deleteStore
yield* this.os.iterate(this, null, null, function * (o) {
yield * this.os.iterate(this, null, null, function * (o) {
if (o.deleted === true) {
expect(yield* this.isDeleted(o.id)).toBeTruthy()
expect(yield * this.isDeleted(o.id)).toBeTruthy()
}
})
// compare deleteStore against deleted ops
var ds = []
yield* this.ds.iterate(this, null, null, function * (d) {
yield * this.ds.iterate(this, null, null, function * (d) {
ds.push(d)
})
for (var j in ds) {
var d = ds[j]
for (var i = 0; i < d.len; i++) {
var o = yield* this.getInsertion([d.id[0], d.id[1] + i])
var o = yield * this.getInsertion([d.id[0], d.id[1] + i])
// gc'd or deleted
if (d.gc) {
expect(o).toBeFalsy()
@ -300,8 +300,8 @@ g.compareAllUsers = async(function * compareAllUsers (users) {
// compare allDels tree
if (s1 == null) {
u.db.requestTransaction(function * () {
yield* t1.call(this)
yield* this.os.iterate(this, null, null, function * (o) {
yield * t1.call(this)
yield * this.os.iterate(this, null, null, function * (o) {
o = Y.utils.copyObject(o)
delete o.origin
delete o.originOf
@ -310,9 +310,9 @@ g.compareAllUsers = async(function * compareAllUsers (users) {
})
} else {
u.db.requestTransaction(function * () {
yield* t2.call(this)
yield * t2.call(this)
var db2 = []
yield* this.os.iterate(this, null, null, function * (o) {
yield * this.os.iterate(this, null, null, function * (o) {
o = Y.utils.copyObject(o)
delete o.origin
delete o.originOf

View File

@ -19,7 +19,7 @@
* requiredOps
- Operations that are required to execute this operation.
*/
module.exports = function (Y/* :any */) {
export default function extendStruct (Y) {
var Struct = {
/* This is the only operation that is actually not a structure, because
it is not stored in the OS. This is why it _does not_ have an id
@ -40,7 +40,7 @@ module.exports = function (Y/* :any */) {
return [] // [op.target]
},
execute: function * (op) {
return yield* this.deleteOperation(op.target, op.length || 1)
return yield * this.deleteOperation(op.target, op.length || 1)
}
},
Insert: {
@ -101,13 +101,13 @@ module.exports = function (Y/* :any */) {
return 0
} else {
var d = 0
var o = yield* this.getInsertion(op.left)
var o = yield * this.getInsertion(op.left)
while (!Y.utils.matchesId(o, op.origin)) {
d++
if (o.left == null) {
break
} else {
o = yield* this.getInsertion(o.left)
o = yield * this.getInsertion(o.left)
}
}
return d
@ -138,17 +138,17 @@ module.exports = function (Y/* :any */) {
if (op.origin != null) { // TODO: !== instead of !=
// we save in origin that op originates in it
// we need that later when we eventually garbage collect origin (see transaction)
var origin = yield* this.getInsertionCleanEnd(op.origin)
var origin = yield * this.getInsertionCleanEnd(op.origin)
if (origin.originOf == null) {
origin.originOf = []
}
origin.originOf.push(op.id)
yield* this.setOperation(origin)
yield * this.setOperation(origin)
if (origin.right != null) {
tryToRemergeLater.push(origin.right)
}
}
var distanceToOrigin = i = yield* Struct.Insert.getDistanceToOrigin.call(this, op) // most cases: 0 (starts from 0)
var distanceToOrigin = i = yield * Struct.Insert.getDistanceToOrigin.call(this, op) // most cases: 0 (starts from 0)
// now we begin to insert op in the list of insertions..
var o
@ -157,29 +157,29 @@ module.exports = function (Y/* :any */) {
// find o. o is the first conflicting operation
if (op.left != null) {
o = yield* this.getInsertionCleanEnd(op.left)
o = yield * this.getInsertionCleanEnd(op.left)
if (!Y.utils.compareIds(op.left, op.origin) && o.right != null) {
// only if not added previously
tryToRemergeLater.push(o.right)
}
o = (o.right == null) ? null : yield* this.getOperation(o.right)
o = (o.right == null) ? null : yield * this.getOperation(o.right)
} else { // left == null
parent = yield* this.getOperation(op.parent)
parent = yield * this.getOperation(op.parent)
let startId = op.parentSub ? parent.map[op.parentSub] : parent.start
start = startId == null ? null : yield* this.getOperation(startId)
start = startId == null ? null : yield * this.getOperation(startId)
o = start
}
// make sure to split op.right if necessary (also add to tryCombineWithLeft)
if (op.right != null) {
tryToRemergeLater.push(op.right)
yield* this.getInsertionCleanStart(op.right)
yield * this.getInsertionCleanStart(op.right)
}
// handle conflicts
while (true) {
if (o != null && !Y.utils.compareIds(o.id, op.right)) {
var oOriginDistance = yield* Struct.Insert.getDistanceToOrigin.call(this, o)
var oOriginDistance = yield * Struct.Insert.getDistanceToOrigin.call(this, o)
if (oOriginDistance === i) {
// case 1
if (o.id[0] < op.id[0]) {
@ -197,7 +197,7 @@ module.exports = function (Y/* :any */) {
}
i++
if (o.right != null) {
o = yield* this.getInsertion(o.right)
o = yield * this.getInsertion(o.right)
} else {
o = null
}
@ -210,17 +210,17 @@ module.exports = function (Y/* :any */) {
var left = null
var right = null
if (parent == null) {
parent = yield* this.getOperation(op.parent)
parent = yield * this.getOperation(op.parent)
}
// reconnect left and set right of op
if (op.left != null) {
left = yield* this.getInsertion(op.left)
left = yield * this.getInsertion(op.left)
// link left
op.right = left.right
left.right = op.id
yield* this.setOperation(left)
yield * this.setOperation(left)
} else {
// set op.right from parent, if necessary
op.right = op.parentSub ? parent.map[op.parentSub] || null : parent.start
@ -228,33 +228,33 @@ module.exports = function (Y/* :any */) {
// reconnect right
if (op.right != null) {
// TODO: wanna connect right too?
right = yield* this.getOperation(op.right)
right = yield * this.getOperation(op.right)
right.left = Y.utils.getLastId(op)
// if right exists, and it is supposed to be gc'd. Remove it from the gc
if (right.gc != null) {
if (right.content != null && right.content.length > 1) {
right = yield* this.getInsertionCleanEnd(right.id)
right = yield * this.getInsertionCleanEnd(right.id)
}
this.store.removeFromGarbageCollector(right)
}
yield* this.setOperation(right)
yield * this.setOperation(right)
}
// update parents .map/start/end properties
if (op.parentSub != null) {
if (left == null) {
parent.map[op.parentSub] = op.id
yield* this.setOperation(parent)
yield * this.setOperation(parent)
}
// is a child of a map struct.
// Then also make sure that only the most left element is not deleted
// We do not call the type in this case (this is what the third parameter is for)
if (op.right != null) {
yield* this.deleteOperation(op.right, 1, true)
yield * this.deleteOperation(op.right, 1, true)
}
if (op.left != null) {
yield* this.deleteOperation(op.id, 1, true)
yield * this.deleteOperation(op.id, 1, true)
}
} else {
if (right == null || left == null) {
@ -264,14 +264,14 @@ module.exports = function (Y/* :any */) {
if (left == null) {
parent.start = op.id
}
yield* this.setOperation(parent)
yield * this.setOperation(parent)
}
}
// try to merge original op.left and op.origin
for (i = 0; i < tryToRemergeLater.length; i++) {
var m = yield* this.getOperation(tryToRemergeLater[i])
yield* this.tryCombineWithLeft(m)
var m = yield * this.getOperation(tryToRemergeLater[i])
yield * this.tryCombineWithLeft(m)
}
}
},
@ -329,7 +329,7 @@ module.exports = function (Y/* :any */) {
return null
}
var res = null
var o = yield* this.getOperation(op.start)
var o = yield * this.getOperation(op.start)
while (true) {
if (!o.deleted) {
@ -337,7 +337,7 @@ module.exports = function (Y/* :any */) {
pos--
}
if (pos >= 0 && o.right != null) {
o = yield* this.getOperation(o.right)
o = yield * this.getOperation(o.right)
} else {
break
}
@ -348,7 +348,7 @@ module.exports = function (Y/* :any */) {
o = o.start
var res = []
while (o != null) { // TODO: change to != (at least some convention)
var operation = yield* this.getOperation(o)
var operation = yield * this.getOperation(o)
if (!operation.deleted) {
res.push(f(operation))
}
@ -398,13 +398,13 @@ module.exports = function (Y/* :any */) {
get: function * (op, name) {
var oid = op.map[name]
if (oid != null) {
var res = yield* this.getOperation(oid)
var res = yield * this.getOperation(oid)
if (res == null || res.deleted) {
return void 0
} else if (res.opContent == null) {
return res.content[0]
} else {
return yield* this.getType(res.opContent)
return yield * this.getType(res.opContent)
}
}
}

View File

@ -74,7 +74,7 @@
- this is called only by `getOperations(startSS)`. It makes an operation
applyable on a given SS.
*/
module.exports = function (Y/* :any */) {
export default function extendTransaction (Y) {
class TransactionInterface {
/* ::
store: Y.AbstractDatabase;
@ -91,7 +91,7 @@ module.exports = function (Y/* :any */) {
var send = []
for (var i = 0; i < ops.length; i++) {
var op = ops[i]
yield* this.store.tryExecute.call(this, op)
yield * this.store.tryExecute.call(this, op)
if (op.id == null || typeof op.id[1] !== 'string') {
send.push(Y.Struct[op.struct].encode(op))
}
@ -104,15 +104,15 @@ module.exports = function (Y/* :any */) {
* deleteList (start) {
while (start != null) {
start = yield* this.getOperation(start)
start = yield * this.getOperation(start)
if (!start.gc) {
start.gc = true
start.deleted = true
yield* this.setOperation(start)
yield * this.setOperation(start)
var delLength = start.content != null ? start.content.length : 1
yield* this.markDeleted(start.id, delLength)
yield * this.markDeleted(start.id, delLength)
if (start.opContent != null) {
yield* this.deleteOperation(start.opContent)
yield * this.deleteOperation(start.opContent)
}
this.store.queueGarbageCollector(start.id)
}
@ -127,10 +127,10 @@ module.exports = function (Y/* :any */) {
if (length == null) {
length = 1
}
yield* this.markDeleted(targetId, length)
yield * this.markDeleted(targetId, length)
while (length > 0) {
var callType = false
var target = yield* this.os.findWithUpperBound([targetId[0], targetId[1] + length - 1])
var target = yield * this.os.findWithUpperBound([targetId[0], targetId[1] + length - 1])
var targetLength = target != null && target.content != null ? target.content.length : 1
if (target == null || target.id[0] !== targetId[0] || target.id[1] + targetLength <= targetId[1]) {
// does not exist or is not in the range of the deletion
@ -141,12 +141,12 @@ module.exports = function (Y/* :any */) {
if (!target.deleted) {
if (target.id[1] < targetId[1]) {
// starts to the left of the deletion range
target = yield* this.getInsertionCleanStart(targetId)
target = yield * this.getInsertionCleanStart(targetId)
targetLength = target.content.length // must have content property!
}
if (target.id[1] + targetLength > targetId[1] + length) {
// ends to the right of the deletion range
target = yield* this.getInsertionCleanEnd([targetId[0], targetId[1] + length - 1])
target = yield * this.getInsertionCleanEnd([targetId[0], targetId[1] + length - 1])
targetLength = target.content.length
}
}
@ -161,35 +161,35 @@ module.exports = function (Y/* :any */) {
// delete containing lists
if (target.start != null) {
// TODO: don't do it like this .. -.-
yield* this.deleteList(target.start)
yield * this.deleteList(target.start)
// yield* this.deleteList(target.id) -- do not gc itself because this may still get referenced
}
if (target.map != null) {
for (var name in target.map) {
yield* this.deleteList(target.map[name])
yield * this.deleteList(target.map[name])
}
// TODO: here to.. (see above)
// yield* this.deleteList(target.id) -- see above
}
if (target.opContent != null) {
yield* this.deleteOperation(target.opContent)
yield * this.deleteOperation(target.opContent)
// target.opContent = null
}
if (target.requires != null) {
for (var i = 0; i < target.requires.length; i++) {
yield* this.deleteOperation(target.requires[i])
yield * this.deleteOperation(target.requires[i])
}
}
}
var left
if (target.left != null) {
left = yield* this.getInsertion(target.left)
left = yield * this.getInsertion(target.left)
} else {
left = null
}
// set here because it was deleted and/or gc'd
yield* this.setOperation(target)
yield * this.setOperation(target)
/*
Check if it is possible to add right to the gc.
@ -198,12 +198,12 @@ module.exports = function (Y/* :any */) {
*/
var right
if (target.right != null) {
right = yield* this.getOperation(target.right)
right = yield * this.getOperation(target.right)
} else {
right = null
}
if (callType && !preventCallType) {
yield* this.store.operationAdded(this, {
yield * this.store.operationAdded(this, {
struct: 'Delete',
target: target.id,
length: targetLength,
@ -211,9 +211,9 @@ module.exports = function (Y/* :any */) {
})
}
// need to gc in the end!
yield* this.store.addToGarbageCollector.call(this, target, left)
yield * this.store.addToGarbageCollector.call(this, target, left)
if (right != null) {
yield* this.store.addToGarbageCollector.call(this, right, target)
yield * this.store.addToGarbageCollector.call(this, right, target)
}
}
}
@ -224,22 +224,22 @@ module.exports = function (Y/* :any */) {
* markGarbageCollected (id, len) {
// this.mem.push(["gc", id]);
this.store.addToDebug('yield* this.markGarbageCollected(', id, ', ', len, ')')
var n = yield* this.markDeleted(id, len)
var n = yield * this.markDeleted(id, len)
if (n.id[1] < id[1] && !n.gc) {
// un-extend left
var newlen = n.len - (id[1] - n.id[1])
n.len -= newlen
yield* this.ds.put(n)
yield * this.ds.put(n)
n = {id: id, len: newlen, gc: false}
yield* this.ds.put(n)
yield * this.ds.put(n)
}
// get prev&next before adding a new operation
var prev = yield* this.ds.findPrev(id)
var next = yield* this.ds.findNext(id)
var prev = yield * this.ds.findPrev(id)
var next = yield * this.ds.findNext(id)
if (id[1] + len < n.id[1] + n.len && !n.gc) {
// un-extend right
yield* this.ds.put({id: [id[0], id[1] + len], len: n.len - len, gc: false})
yield * this.ds.put({id: [id[0], id[1] + len], len: n.len - len, gc: false})
n.len = len
}
// set gc'd
@ -251,7 +251,7 @@ module.exports = function (Y/* :any */) {
Y.utils.compareIds([prev.id[0], prev.id[1] + prev.len], n.id)
) {
prev.len += n.len
yield* this.ds.delete(n.id)
yield * this.ds.delete(n.id)
n = prev
// ds.put n here?
}
@ -262,10 +262,10 @@ module.exports = function (Y/* :any */) {
Y.utils.compareIds([n.id[0], n.id[1] + n.len], next.id)
) {
n.len += next.len
yield* this.ds.delete(next.id)
yield * this.ds.delete(next.id)
}
yield* this.ds.put(n)
yield* this.updateState(n.id[0])
yield * this.ds.put(n)
yield * this.updateState(n.id[0])
}
/*
Mark an operation as deleted.
@ -277,7 +277,7 @@ module.exports = function (Y/* :any */) {
length = 1
}
// this.mem.push(["del", id]);
var n = yield* this.ds.findWithUpperBound(id)
var n = yield * this.ds.findWithUpperBound(id)
if (n != null && n.id[0] === id[0]) {
if (n.id[1] <= id[1] && id[1] <= n.id[1] + n.len) {
// id is in n's range
@ -291,7 +291,7 @@ module.exports = function (Y/* :any */) {
if (diff < length) {
// a partial deletion
n = {id: [id[0], id[1] + diff], len: length - diff, gc: false}
yield* this.ds.put(n)
yield * this.ds.put(n)
} else {
// already gc'd
throw new Error('Cannot happen! (it dit though.. :()')
@ -305,15 +305,15 @@ module.exports = function (Y/* :any */) {
} else {
// cannot extend left (there is no left!)
n = {id: id, len: length, gc: false}
yield* this.ds.put(n) // TODO: you double-put !!
yield * this.ds.put(n) // TODO: you double-put !!
}
} else {
// cannot extend left
n = {id: id, len: length, gc: false}
yield* this.ds.put(n)
yield * this.ds.put(n)
}
// can extend right?
var next = yield* this.ds.findNext(n.id)
var next = yield * this.ds.findNext(n.id)
if (
next != null &&
n.id[0] === next.id[0] &&
@ -329,8 +329,8 @@ module.exports = function (Y/* :any */) {
// delete the missing range after next
diff = diff - next.len // missing range after next
if (diff > 0) {
yield* this.ds.put(n) // unneccessary? TODO!
yield* this.markDeleted([next.id[0], next.id[1] + next.len], diff)
yield * this.ds.put(n) // unneccessary? TODO!
yield * this.markDeleted([next.id[0], next.id[1] + next.len], diff)
}
}
break
@ -339,8 +339,8 @@ module.exports = function (Y/* :any */) {
if (diff > next.len) {
// n is even longer than next
// get next.next, and try to extend it
var _next = yield* this.ds.findNext(next.id)
yield* this.ds.delete(next.id)
var _next = yield * this.ds.findNext(next.id)
yield * this.ds.delete(next.id)
if (_next == null || n.id[0] !== _next.id[0]) {
break
} else {
@ -351,13 +351,13 @@ module.exports = function (Y/* :any */) {
} else {
// n just partially overlaps with next. extend n, delete next, and break this loop
n.len += next.len - diff
yield* this.ds.delete(next.id)
yield * this.ds.delete(next.id)
break
}
}
}
}
yield* this.ds.put(n)
yield * this.ds.put(n)
return n
}
/*
@ -372,28 +372,28 @@ module.exports = function (Y/* :any */) {
if (!this.store.gc) {
return
}
yield* this.os.iterate(this, null, null, function * (op) {
yield * this.os.iterate(this, null, null, function * (op) {
if (op.gc) {
delete op.gc
yield* this.setOperation(op)
yield * this.setOperation(op)
}
if (op.parent != null) {
var parentDeleted = yield* this.isDeleted(op.parent)
var parentDeleted = yield * this.isDeleted(op.parent)
if (parentDeleted) {
op.gc = true
if (!op.deleted) {
yield* this.markDeleted(op.id, op.content != null ? op.content.length : 1)
yield * this.markDeleted(op.id, op.content != null ? op.content.length : 1)
op.deleted = true
if (op.opContent != null) {
yield* this.deleteOperation(op.opContent)
yield * this.deleteOperation(op.opContent)
}
if (op.requires != null) {
for (var i = 0; i < op.requires.length; i++) {
yield* this.deleteOperation(op.requires[i])
yield * this.deleteOperation(op.requires[i])
}
}
}
yield* this.setOperation(op)
yield * this.setOperation(op)
this.store.gc1.push(op.id) // this is ok becaues its shortly before sync (otherwise use queueGarbageCollector!)
return
}
@ -401,9 +401,9 @@ module.exports = function (Y/* :any */) {
if (op.deleted) {
var left = null
if (op.left != null) {
left = yield* this.getInsertion(op.left)
left = yield * this.getInsertion(op.left)
}
yield* this.store.addToGarbageCollector.call(this, op, left)
yield * this.store.addToGarbageCollector.call(this, op, left)
}
})
}
@ -418,8 +418,8 @@ module.exports = function (Y/* :any */) {
*/
* garbageCollectOperation (id) {
this.store.addToDebug('yield* this.garbageCollectOperation(', id, ')')
var o = yield* this.getOperation(id)
yield* this.markGarbageCollected(id, (o != null && o.content != null) ? o.content.length : 1) // always mark gc'd
var o = yield * this.getOperation(id)
yield * this.markGarbageCollected(id, (o != null && o.content != null) ? o.content.length : 1) // always mark gc'd
// if op exists, then clean that mess up..
if (o != null) {
var deps = []
@ -430,32 +430,32 @@ module.exports = function (Y/* :any */) {
deps = deps.concat(o.requires)
}
for (var i = 0; i < deps.length; i++) {
var dep = yield* this.getOperation(deps[i])
var dep = yield * this.getOperation(deps[i])
if (dep != null) {
if (!dep.deleted) {
yield* this.deleteOperation(dep.id)
dep = yield* this.getOperation(dep.id)
yield * this.deleteOperation(dep.id)
dep = yield * this.getOperation(dep.id)
}
dep.gc = true
yield* this.setOperation(dep)
yield * this.setOperation(dep)
this.store.queueGarbageCollector(dep.id)
} else {
yield* this.markGarbageCollected(deps[i], 1)
yield * this.markGarbageCollected(deps[i], 1)
}
}
// remove gc'd op from the left op, if it exists
if (o.left != null) {
var left = yield* this.getInsertion(o.left)
var left = yield * this.getInsertion(o.left)
left.right = o.right
yield* this.setOperation(left)
yield * this.setOperation(left)
}
// remove gc'd op from the right op, if it exists
// also reset origins of right ops
if (o.right != null) {
var right = yield* this.getOperation(o.right)
var right = yield * this.getOperation(o.right)
right.left = o.left
yield* this.setOperation(right)
yield * this.setOperation(right)
if (o.originOf != null && o.originOf.length > 0) {
// find new origin of right ops
@ -463,7 +463,7 @@ module.exports = function (Y/* :any */) {
var neworigin = o.left
var neworigin_ = null
while (neworigin != null) {
neworigin_ = yield* this.getInsertion(neworigin)
neworigin_ = yield * this.getInsertion(neworigin)
if (neworigin_.deleted) {
break
}
@ -506,10 +506,10 @@ module.exports = function (Y/* :any */) {
// ** Now the new implementation starts **
// reset neworigin of all originOf[*]
for (var _i in o.originOf) {
var originsIn = yield* this.getOperation(o.originOf[_i])
var originsIn = yield * this.getOperation(o.originOf[_i])
if (originsIn != null) {
originsIn.origin = neworigin
yield* this.setOperation(originsIn)
yield * this.setOperation(originsIn)
}
}
if (neworigin != null) {
@ -518,7 +518,7 @@ module.exports = function (Y/* :any */) {
} else {
neworigin_.originOf = o.originOf.concat(neworigin_.originOf)
}
yield* this.setOperation(neworigin_)
yield * this.setOperation(neworigin_)
}
// we don't need to set right here, because
// right should be in o.originOf => it is set it the previous for loop
@ -527,15 +527,15 @@ module.exports = function (Y/* :any */) {
// o may originate in another operation.
// Since o is deleted, we have to reset o.origin's `originOf` property
if (o.origin != null) {
var origin = yield* this.getInsertion(o.origin)
var origin = yield * this.getInsertion(o.origin)
origin.originOf = origin.originOf.filter(function (_id) {
return !Y.utils.compareIds(id, _id)
})
yield* this.setOperation(origin)
yield * this.setOperation(origin)
}
var parent
if (o.parent != null) {
parent = yield* this.getOperation(o.parent)
parent = yield * this.getOperation(o.parent)
}
// remove gc'd op from parent, if it exists
if (parent != null) {
@ -562,32 +562,32 @@ module.exports = function (Y/* :any */) {
}
}
if (setParent) {
yield* this.setOperation(parent)
yield * this.setOperation(parent)
}
}
// finally remove it from the os
yield* this.removeOperation(o.id)
yield * this.removeOperation(o.id)
}
}
* checkDeleteStoreForState (state) {
var n = yield* this.ds.findWithUpperBound([state.user, state.clock])
var n = yield * this.ds.findWithUpperBound([state.user, state.clock])
if (n != null && n.id[0] === state.user && n.gc) {
state.clock = Math.max(state.clock, n.id[1] + n.len)
}
}
* updateState (user) {
var state = yield* this.getState(user)
yield* this.checkDeleteStoreForState(state)
var o = yield* this.getInsertion([user, state.clock])
var state = yield * this.getState(user)
yield * this.checkDeleteStoreForState(state)
var o = yield * this.getInsertion([user, state.clock])
var oLength = (o != null && o.content != null) ? o.content.length : 1
while (o != null && user === o.id[0] && o.id[1] <= state.clock && o.id[1] + oLength > state.clock) {
// either its a new operation (1. case), or it is an operation that was deleted, but is not yet in the OS
state.clock += oLength
yield* this.checkDeleteStoreForState(state)
o = yield* this.os.findNext(o.id)
yield * this.checkDeleteStoreForState(state)
o = yield * this.os.findNext(o.id)
oLength = (o != null && o.content != null) ? o.content.length : 1
}
yield* this.setState(state)
yield * this.setState(state)
}
/*
apply a delete set in order to get
@ -600,7 +600,7 @@ module.exports = function (Y/* :any */) {
var dv = ds[user]
var pos = 0
var d = dv[pos]
yield* this.ds.iterate(this, [user, 0], [user, Number.MAX_VALUE], function * (n) {
yield * this.ds.iterate(this, [user, 0], [user, Number.MAX_VALUE], function * (n) {
// cases:
// 1. d deletes something to the right of n
// => go to next n (break)
@ -649,14 +649,14 @@ module.exports = function (Y/* :any */) {
for (var i = 0; i < deletions.length; i++) {
var del = deletions[i]
// always try to delete..
yield* this.deleteOperation([del[0], del[1]], del[2])
yield * this.deleteOperation([del[0], del[1]], del[2])
if (del[3]) {
// gc..
yield* this.markGarbageCollected([del[0], del[1]], del[2]) // always mark gc'd
yield * this.markGarbageCollected([del[0], del[1]], del[2]) // always mark gc'd
// remove operation..
var counter = del[1] + del[2]
while (counter >= del[1]) {
var o = yield* this.os.findWithUpperBound([del[0], counter - 1])
var o = yield * this.os.findWithUpperBound([del[0], counter - 1])
if (o == null) {
break
}
@ -667,14 +667,14 @@ module.exports = function (Y/* :any */) {
}
if (o.id[1] + oLen > del[1] + del[2]) {
// overlaps right
o = yield* this.getInsertionCleanEnd([del[0], del[1] + del[2] - 1])
o = yield * this.getInsertionCleanEnd([del[0], del[1] + del[2] - 1])
}
if (o.id[1] < del[1]) {
// overlaps left
o = yield* this.getInsertionCleanStart([del[0], del[1]])
o = yield * this.getInsertionCleanStart([del[0], del[1]])
}
counter = o.id[1]
yield* this.garbageCollectOperation(o.id)
yield * this.garbageCollectOperation(o.id)
}
}
if (this.store.forwardAppliedOperations) {
@ -685,7 +685,7 @@ module.exports = function (Y/* :any */) {
}
}
* isGarbageCollected (id) {
var n = yield* this.ds.findWithUpperBound(id)
var n = yield * this.ds.findWithUpperBound(id)
return n != null && n.id[0] === id[0] && id[1] < n.id[1] + n.len && n.gc
}
/*
@ -693,7 +693,7 @@ module.exports = function (Y/* :any */) {
*/
* getDeleteSet () {
var ds = {}
yield* this.ds.iterate(this, null, null, function * (n) {
yield * this.ds.iterate(this, null, null, function * (n) {
var user = n.id[0]
var counter = n.id[1]
var len = n.len
@ -708,15 +708,15 @@ module.exports = function (Y/* :any */) {
return ds
}
* isDeleted (id) {
var n = yield* this.ds.findWithUpperBound(id)
var n = yield * this.ds.findWithUpperBound(id)
return n != null && n.id[0] === id[0] && id[1] < n.id[1] + n.len
}
* setOperation (op) {
yield* this.os.put(op)
yield * this.os.put(op)
return op
}
* addOperation (op) {
yield* this.os.put(op)
yield * this.os.put(op)
if (this.store.y.connector.isSynced && this.store.forwardAppliedOperations && typeof op.id[1] !== 'string') {
// is connected, and this is not going to be send in addOperation
this.store.y.connector.broadcastOps([op])
@ -731,7 +731,7 @@ module.exports = function (Y/* :any */) {
op.left[0] === op.id[0] &&
Y.utils.compareIds(op.left, op.origin)
) {
var left = yield* this.getInsertion(op.left)
var left = yield * this.getInsertion(op.left)
if (left.content != null &&
left.id[1] + left.content.length === op.id[1] &&
left.originOf.length === 1 &&
@ -746,13 +746,13 @@ module.exports = function (Y/* :any */) {
}
left.content = left.content.concat(op.content)
left.right = op.right
yield* this.os.delete(op.id)
yield* this.setOperation(left)
yield * this.os.delete(op.id)
yield * this.setOperation(left)
}
}
}
* getInsertion (id) {
var ins = yield* this.os.findWithUpperBound(id)
var ins = yield * this.os.findWithUpperBound(id)
if (ins == null) {
return null
} else {
@ -765,13 +765,13 @@ module.exports = function (Y/* :any */) {
}
}
* getInsertionCleanStartEnd (id) {
yield* this.getInsertionCleanStart(id)
return yield* this.getInsertionCleanEnd(id)
yield * this.getInsertionCleanStart(id)
return yield * this.getInsertionCleanEnd(id)
}
// Return an insertion such that id is the first element of content
// This function manipulates an operation, if necessary
* getInsertionCleanStart (id) {
var ins = yield* this.getInsertion(id)
var ins = yield * this.getInsertion(id)
if (ins != null) {
if (ins.id[1] === id[1]) {
return ins
@ -785,8 +785,8 @@ module.exports = function (Y/* :any */) {
left.right = ins.id
ins.left = leftLid
// debugger // check
yield* this.setOperation(left)
yield* this.setOperation(ins)
yield * this.setOperation(left)
yield * this.setOperation(ins)
if (left.gc) {
this.store.queueGarbageCollector(ins.id)
}
@ -799,7 +799,7 @@ module.exports = function (Y/* :any */) {
// Return an insertion such that id is the last element of content
// This function manipulates an operation, if necessary
* getInsertionCleanEnd (id) {
var ins = yield* this.getInsertion(id)
var ins = yield * this.getInsertion(id)
if (ins != null) {
if (ins.content == null || (ins.id[1] + ins.content.length - 1 === id[1])) {
return ins
@ -813,8 +813,8 @@ module.exports = function (Y/* :any */) {
ins.right = right.id
right.left = insLid
// debugger // check
yield* this.setOperation(right)
yield* this.setOperation(ins)
yield * this.setOperation(right)
yield * this.setOperation(ins)
if (ins.gc) {
this.store.queueGarbageCollector(right.id)
}
@ -825,7 +825,7 @@ module.exports = function (Y/* :any */) {
}
}
* getOperation (id/* :any */)/* :Transaction<any> */ {
var o = yield* this.os.find(id)
var o = yield * this.os.find(id)
if (id[0] !== '_' || o != null) {
return o
} else { // type is string
@ -835,7 +835,7 @@ module.exports = function (Y/* :any */) {
var struct = comp[0]
var op = Y.Struct[struct].create(id)
op.type = comp[1]
yield* this.setOperation(op)
yield * this.setOperation(op)
return op
} else {
// won't be called. but just in case..
@ -846,17 +846,17 @@ module.exports = function (Y/* :any */) {
}
}
* removeOperation (id) {
yield* this.os.delete(id)
yield * this.os.delete(id)
}
* setState (state) {
var val = {
id: [state.user],
clock: state.clock
}
yield* this.ss.put(val)
yield * this.ss.put(val)
}
* getState (user) {
var n = yield* this.ss.find([user])
var n = yield * this.ss.find([user])
var clock = n == null ? null : n.clock
if (clock == null) {
clock = 0
@ -868,7 +868,7 @@ module.exports = function (Y/* :any */) {
}
* getStateVector () {
var stateVector = []
yield* this.ss.iterate(this, null, null, function * (n) {
yield * this.ss.iterate(this, null, null, function * (n) {
stateVector.push({
user: n.id[0],
clock: n.clock
@ -878,7 +878,7 @@ module.exports = function (Y/* :any */) {
}
* getStateSet () {
var ss = {}
yield* this.ss.iterate(this, null, null, function * (n) {
yield * this.ss.iterate(this, null, null, function * (n) {
ss[n.id[0]] = n.clock
})
return ss
@ -936,7 +936,7 @@ module.exports = function (Y/* :any */) {
}
var send = []
var endSV = yield* this.getStateVector()
var endSV = yield * this.getStateVector()
for (var endState of endSV) {
var user = endState.user
if (user === '_') {
@ -946,14 +946,14 @@ module.exports = function (Y/* :any */) {
if (startPos > 0) {
// There is a change that [user, startPos] is in a composed Insertion (with a smaller counter)
// find out if that is the case
var firstMissing = yield* this.getInsertion([user, startPos])
var firstMissing = yield * this.getInsertion([user, startPos])
if (firstMissing != null) {
// update startPos
startPos = firstMissing.id[1]
startSS[user] = startPos
}
}
yield* this.os.iterate(this, [user, startPos], [user, Number.MAX_VALUE], function * (op) {
yield * this.os.iterate(this, [user, startPos], [user, Number.MAX_VALUE], function * (op) {
op = Y.Struct[op.struct].encode(op)
if (op.struct !== 'Insert') {
send.push(op)
@ -966,7 +966,7 @@ module.exports = function (Y/* :any */) {
// 2. or to the first operation that has an origin that is not to the
// right of op.
// For this we maintain a list of ops which origins are not found yet.
var missing_origins = [op]
var missingOrigins = [op]
var newright = op.right
while (true) {
if (o.left == null) {
@ -974,15 +974,15 @@ module.exports = function (Y/* :any */) {
send.push(op)
if (!Y.utils.compareIds(o.id, op.id)) {
o = Y.Struct[op.struct].encode(o)
o.right = missing_origins[missing_origins.length - 1].id
o.right = missingOrigins[missingOrigins.length - 1].id
send.push(o)
}
break
}
o = yield* this.getInsertion(o.left)
// we set another o, check if we can reduce $missing_origins
while (missing_origins.length > 0 && Y.utils.matchesId(o, missing_origins[missing_origins.length - 1].origin)) {
missing_origins.pop()
o = yield * this.getInsertion(o.left)
// we set another o, check if we can reduce $missingOrigins
while (missingOrigins.length > 0 && Y.utils.matchesId(o, missingOrigins[missingOrigins.length - 1].origin)) {
missingOrigins.pop()
}
if (o.id[1] < (startSS[o.id[0]] || 0)) {
// case 2. o is known
@ -995,17 +995,17 @@ module.exports = function (Y/* :any */) {
send.push(op)
op = Y.Struct[op.struct].encode(o)
op.right = newright
if (missing_origins.length > 0) {
if (missingOrigins.length > 0) {
console.log('This should not happen .. :( please report this')
}
missing_origins = [op]
missingOrigins = [op]
} else {
// case 4. send o, continue to find op.origin
var s = Y.Struct[op.struct].encode(o)
s.right = missing_origins[missing_origins.length - 1].id
s.right = missingOrigins[missingOrigins.length - 1].id
s.left = s.origin
send.push(s)
missing_origins.push(o)
missingOrigins.push(o)
}
}
}
@ -1020,7 +1020,7 @@ module.exports = function (Y/* :any */) {
*/
* getOperationsUntransformed () {
var ops = []
yield* this.os.iterate(this, null, null, function * (op) {
yield * this.os.iterate(this, null, null, function * (op) {
if (op.id[0] !== '_') {
ops.push(op)
}
@ -1039,25 +1039,25 @@ module.exports = function (Y/* :any */) {
// update parents .map/start/end properties
if (op.parentSub != null && op.left == null) {
// op is child of Map
let parent = yield* this.getOperation(op.parent)
let parent = yield * this.getOperation(op.parent)
parent.map[op.parentSub] = op.id
yield* this.setOperation(parent)
yield * this.setOperation(parent)
} else if (op.right == null || op.left == null) {
let parent = yield* this.getOperation(op.parent)
let parent = yield * this.getOperation(op.parent)
if (op.right == null) {
parent.end = Y.utils.getLastId(op)
}
if (op.left == null) {
parent.start = op.id
}
yield* this.setOperation(parent)
yield * this.setOperation(parent)
}
}
}
yield* this.os.put(op)
yield * this.os.put(op)
}
for (var user in stateSet) {
yield* this.ss.put({
yield * this.ss.put({
id: [user],
clock: stateSet[user]
})
@ -1089,9 +1089,9 @@ module.exports = function (Y/* :any */) {
}
*/
* flush () {
yield* this.os.flush()
yield* this.ss.flush()
yield* this.ds.flush()
yield * this.os.flush()
yield * this.ss.flush()
yield * this.ds.flush()
}
}
Y.Transaction = TransactionInterface

View File

@ -1,6 +1,3 @@
/* @flow */
'use strict'
/*
EventHandler is an helper class for constructing custom types.
@ -23,7 +20,8 @@
database request to finish). EventHandler helps you to make your type
synchronous.
*/
module.exports = function (Y /* : any*/) {
export default function Utils (Y) {
Y.utils = {}
Y.utils.bubbleEvent = function (type, event) {
@ -299,7 +297,7 @@ module.exports = function (Y /* : any*/) {
}
var before = this.waiting.length
// somehow create new operations
yield* f.apply(transaction, args)
yield * f.apply(transaction, args)
// remove all appended ops / awaited ops
this.waiting.splice(before)
if (this.awaiting > 0) this.awaiting--
@ -309,7 +307,7 @@ module.exports = function (Y /* : any*/) {
for (let i = 0; i < this.waiting.length; i++) {
var o = this.waiting[i]
if (o.struct === 'Insert') {
var _o = yield* transaction.getInsertion(o.id)
var _o = yield * transaction.getInsertion(o.id)
if (_o.parentSub != null && _o.left != null) {
// if o is an insertion of a map struc (parentSub is defined), then it shouldn't be necessary to compute left
this.waiting.splice(i, 1)
@ -321,10 +319,10 @@ module.exports = function (Y /* : any*/) {
o.left = null
} else {
// find next undeleted op
var left = yield* transaction.getInsertion(_o.left)
var left = yield * transaction.getInsertion(_o.left)
while (left.deleted != null) {
if (left.left != null) {
left = yield* transaction.getInsertion(left.left)
left = yield * transaction.getInsertion(left.left)
} else {
left = null
break
@ -662,7 +660,7 @@ module.exports = function (Y /* : any*/) {
if (i < 0 && noSuperCall === undefined) {
// did not reach break in last loop
// read id and put it to the end of readBuffer
o = yield* super.find(id)
o = yield * super.find(id)
}
if (o != null) {
for (i = 0; i < this.readBuffer.length - 1; i++) {
@ -692,7 +690,7 @@ module.exports = function (Y /* : any*/) {
// write writeBuffer[0]
var write = this.writeBuffer[0]
if (write.id[0] !== null) {
yield* super.put(write)
yield * super.put(write)
}
// put o to the end of writeBuffer
for (i = 0; i < this.writeBuffer.length - 1; i++) {
@ -722,44 +720,44 @@ module.exports = function (Y /* : any*/) {
}
}
}
yield* this.flush()
yield* super.delete(id)
yield * this.flush()
yield * super.delete(id)
}
* findWithLowerBound (id) {
var o = yield* this.find(id, true)
var o = yield * this.find(id, true)
if (o != null) {
return o
} else {
yield* this.flush()
return yield* super.findWithLowerBound.apply(this, arguments)
yield * this.flush()
return yield * super.findWithLowerBound.apply(this, arguments)
}
}
* findWithUpperBound (id) {
var o = yield* this.find(id, true)
var o = yield * this.find(id, true)
if (o != null) {
return o
} else {
yield* this.flush()
return yield* super.findWithUpperBound.apply(this, arguments)
yield * this.flush()
return yield * super.findWithUpperBound.apply(this, arguments)
}
}
* findNext () {
yield* this.flush()
return yield* super.findNext.apply(this, arguments)
yield * this.flush()
return yield * super.findNext.apply(this, arguments)
}
* findPrev () {
yield* this.flush()
return yield* super.findPrev.apply(this, arguments)
yield * this.flush()
return yield * super.findPrev.apply(this, arguments)
}
* iterate () {
yield* this.flush()
yield* super.iterate.apply(this, arguments)
yield * this.flush()
yield * super.iterate.apply(this, arguments)
}
* flush () {
for (var i = 0; i < this.writeBuffer.length; i++) {
var write = this.writeBuffer[i]
if (write.id[0] !== null) {
yield* super.put(write)
yield * super.put(write)
this.writeBuffer[i] = {
id: [null, null]
}

View File

@ -1,18 +1,20 @@
/* @flow */
'use strict'
import debug from 'debug'
import extendConnector from './Connector.js'
import extendDatabase from './Database.js'
import extendTransaction from './Transaction.js'
import extendStruct from './Struct.js'
import extendUtils from './Utils.js'
require('./Connector.js')(Y)
require('./Database.js')(Y)
require('./Transaction.js')(Y)
require('./Struct.js')(Y)
require('./Utils.js')(Y)
require('./Connectors/Test.js')(Y)
extendConnector(Y)
extendDatabase(Y)
extendTransaction(Y)
extendStruct(Y)
extendUtils(Y)
Y.debug = require('debug')
Y.debug = debug
var requiringModules = {}
module.exports = Y
Y.requiringModules = requiringModules
Y.extend = function (name, value) {
@ -110,7 +112,7 @@ type YOptions = {
}
*/
function Y (opts/* :YOptions */) /* :Promise<YConfig> */ {
export default function Y (opts/* :YOptions */) /* :Promise<YConfig> */ {
if (opts.hasOwnProperty('sourceDir')) {
Y.sourceDir = opts.sourceDir
}
@ -120,11 +122,11 @@ function Y (opts/* :YOptions */) /* :Promise<YConfig> */ {
modules.push(opts.share[name])
}
return new Promise(function (resolve, reject) {
if (opts == null) reject('An options object is expected! ')
else if (opts.connector == null) reject('You must specify a connector! (missing connector property)')
else if (opts.connector.name == null) reject('You must specify connector name! (missing connector.name property)')
else if (opts.db == null) reject('You must specify a database! (missing db property)')
else if (opts.connector.name == null) reject('You must specify db name! (missing db.name property)')
if (opts == null) reject(new Error('An options object is expected!'))
else if (opts.connector == null) reject(new Error('You must specify a connector! (missing connector property)'))
else if (opts.connector.name == null) reject(new Error('You must specify connector name! (missing connector.name property)'))
else if (opts.db == null) reject(new Error('You must specify a database! (missing db property)'))
else if (opts.connector.name == null) reject(new Error('You must specify db name! (missing db.name property)'))
else {
opts = Y.utils.copyObject(opts)
opts.connector = Y.utils.copyObject(opts.connector)
@ -182,7 +184,7 @@ class YConfig {
args = typedef.parseArguments(args[0])[1]
}
}
share[propertyname] = yield* this.store.initType.call(this, id, args)
share[propertyname] = yield * this.store.initType.call(this, id, args)
}
this.store.whenTransactionsFinished()
.then(callback)
@ -229,7 +231,7 @@ class YConfig {
this.db.destroyTypes()
// make sure to wait for all transactions before destroying the db
this.db.requestTransaction(function * () {
yield* self.db.destroy()
yield * self.db.destroy()
})
return this.db.whenTransactionsFinished()
})