implemented module loader for yjs
This commit is contained in:
		
							parent
							
								
									138afe39dc
								
							
						
					
					
						commit
						6dc347642b
					
				@ -21,31 +21,10 @@ module.exports = function (gulp, helperOptions) {
 | 
			
		||||
    options.regenerator = false
 | 
			
		||||
    // TODO: include './node_modules/gulp-babel/node_modules/babel-core/node_modules/regenerator/runtime.js'
 | 
			
		||||
  }
 | 
			
		||||
  var concatOrder = [
 | 
			
		||||
    'y.js',
 | 
			
		||||
    'Connector.js',
 | 
			
		||||
    'Database.js',
 | 
			
		||||
    'Transaction.js',
 | 
			
		||||
    'Struct.js',
 | 
			
		||||
    'Utils.js',
 | 
			
		||||
    'Databases/RedBlackTree.js',
 | 
			
		||||
    'Databases/Memory.js',
 | 
			
		||||
    'Databases/IndexedDB.js',
 | 
			
		||||
    'Connectors/Test.js',
 | 
			
		||||
    'Types/Array.js',
 | 
			
		||||
    'Types/Map.js',
 | 
			
		||||
    'Types/TextBind.js'
 | 
			
		||||
  ]
 | 
			
		||||
  var yjsfiles = concatOrder.map(function (f) {
 | 
			
		||||
    return '../yjs/src/' + f
 | 
			
		||||
  })
 | 
			
		||||
  var files = {
 | 
			
		||||
    dist: helperOptions.polyfills.concat(helperOptions.files.map(function (f) {
 | 
			
		||||
      return 'src/' + f
 | 
			
		||||
    })),
 | 
			
		||||
    test: ['../yjs/src/Helper.spec.js'].concat(yjsfiles).concat(helperOptions.files.map(function (f) {
 | 
			
		||||
      return 'src/' + f
 | 
			
		||||
    }).concat(['src/' + options.testfiles]))
 | 
			
		||||
    dist: helperOptions.entry,
 | 
			
		||||
    specs: helperOptions.specs,
 | 
			
		||||
    src: './src/**/*.js'
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var babelOptions = {
 | 
			
		||||
@ -54,38 +33,10 @@ module.exports = function (gulp, helperOptions) {
 | 
			
		||||
    experimental: true
 | 
			
		||||
  }
 | 
			
		||||
  if (options.regenerator) {
 | 
			
		||||
    files.test = helperOptions.polyfills.concat(files.test)
 | 
			
		||||
    files.specs = helperOptions.polyfills.concat(files.specs)
 | 
			
		||||
  } else {
 | 
			
		||||
    babelOptions.blacklist = 'regenerator'
 | 
			
		||||
  }
 | 
			
		||||
  // babelOptions.blacklist = 'regenerator'
 | 
			
		||||
 | 
			
		||||
  gulp.task('dist', ['build:dist'], function () {
 | 
			
		||||
    function createDist (pipe) {
 | 
			
		||||
      return pipe
 | 
			
		||||
        .pipe($.if(options.debug, $.sourcemaps.init({loadMaps: true})))
 | 
			
		||||
        .pipe($.concat(options.targetName))
 | 
			
		||||
        .pipe($.if(!options.debug && options.regenerator, $.uglify()))
 | 
			
		||||
        .pipe($.if(options.debug, $.sourcemaps.write('.')))
 | 
			
		||||
        .pipe(gulp.dest('./dist/'))
 | 
			
		||||
    }
 | 
			
		||||
    var pipe
 | 
			
		||||
    if (options.browserify || true) {
 | 
			
		||||
      var browserify = require('browserify')
 | 
			
		||||
      var source = require('vinyl-source-stream')
 | 
			
		||||
      var buffer = require('vinyl-buffer')
 | 
			
		||||
 | 
			
		||||
      pipe = browserify({
 | 
			
		||||
        entries: 'build/' + options.targetName,
 | 
			
		||||
        debug: options.debug
 | 
			
		||||
      }).bundle()
 | 
			
		||||
        .pipe(source(options.targetName))
 | 
			
		||||
        .pipe(buffer())
 | 
			
		||||
    } else {
 | 
			
		||||
      pipe = gulp.src('build/' + options.targetName)
 | 
			
		||||
    }
 | 
			
		||||
    return createDist(pipe)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  gulp.task('dist', function () {
 | 
			
		||||
    var browserify = require('browserify')
 | 
			
		||||
@ -99,7 +50,7 @@ module.exports = function (gulp, helperOptions) {
 | 
			
		||||
      .pipe(source(options.targetName))
 | 
			
		||||
      .pipe(buffer())
 | 
			
		||||
      .pipe($.if(options.debug, $.sourcemaps.init({loadMaps: true})))
 | 
			
		||||
      .pipe($.concat(options.targetName))
 | 
			
		||||
      .pipe($.if(!options.debug && options.regenerator, $.babel(babelOptions)))
 | 
			
		||||
      .pipe($.if(!options.debug && options.regenerator, $.uglify()))
 | 
			
		||||
      .pipe($.if(options.debug, $.sourcemaps.write('.')))
 | 
			
		||||
      .pipe(gulp.dest('./dist/'))
 | 
			
		||||
@ -108,11 +59,46 @@ module.exports = function (gulp, helperOptions) {
 | 
			
		||||
  gulp.task('watch:dist', function (cb) {
 | 
			
		||||
    options.debug = true
 | 
			
		||||
    runSequence('dist', function () {
 | 
			
		||||
      gulp.watch(files.dist, ['dist'])
 | 
			
		||||
      gulp.watch(files.src, ['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,
 | 
			
		||||
      debug: options.debug
 | 
			
		||||
    }).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.testport}))
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  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([
 | 
			
		||||
@ -168,24 +154,4 @@ module.exports = function (gulp, helperOptions) {
 | 
			
		||||
        }))
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  gulp.task('dev:node', ['test'], function () {
 | 
			
		||||
    gulp.watch(files.dist, ['test'])
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  gulp.task('dev:browser', ['watch:build'], function () {
 | 
			
		||||
    return gulp.src(files.test)
 | 
			
		||||
      .pipe($.watch(['build/**/*']))
 | 
			
		||||
      .pipe($.jasmineBrowser.specRunner())
 | 
			
		||||
      .pipe($.jasmineBrowser.server({port: options.testport}))
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  gulp.task('test', function () {
 | 
			
		||||
    console.log(files.test)
 | 
			
		||||
    return gulp.src('./dist/y.js')
 | 
			
		||||
      .pipe($.jasmine({
 | 
			
		||||
        verbose: true,
 | 
			
		||||
        includeStuckTrace: true
 | 
			
		||||
      }))
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										24
									
								
								gulpfile.js
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								gulpfile.js
									
									
									
									
									
								
							@ -49,23 +49,15 @@ var runSequence = require('run-sequence').use(gulp)
 | 
			
		||||
 | 
			
		||||
require('./gulpfile.helper.js')(gulp, {
 | 
			
		||||
  polyfills: [],
 | 
			
		||||
  files: [
 | 
			
		||||
    'y.js',
 | 
			
		||||
    'Connector.js',
 | 
			
		||||
    'Database.js',
 | 
			
		||||
    'Transaction.js',
 | 
			
		||||
    'Struct.js',
 | 
			
		||||
    'Utils.js',
 | 
			
		||||
    'Databases/RedBlackTree.js',
 | 
			
		||||
    'Databases/Memory.js',
 | 
			
		||||
    'Databases/IndexedDB.js',
 | 
			
		||||
    'Connectors/Test.js',
 | 
			
		||||
    'Types/Array.js',
 | 
			
		||||
    'Types/Map.js',
 | 
			
		||||
    'Types/TextBind.js'
 | 
			
		||||
  ],
 | 
			
		||||
  entry: './src/y.js',
 | 
			
		||||
  targetName: 'y.js',
 | 
			
		||||
  moduleName: 'yjs'
 | 
			
		||||
  moduleName: 'yjs',
 | 
			
		||||
  specs: [
 | 
			
		||||
    './src/Databases/RedBlackTree.spec.js',
 | 
			
		||||
    './src/Types/Array.spec.js',
 | 
			
		||||
    './src/Types/Map.spec.js',
 | 
			
		||||
    './src/Database.spec.js'
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
gulp.task('dev:examples', ['updateSubmodule', 'watch:dist'], function () {
 | 
			
		||||
 | 
			
		||||
@ -68,6 +68,7 @@
 | 
			
		||||
    "run-sequence": "^1.1.4",
 | 
			
		||||
    "standard": "^5.2.2",
 | 
			
		||||
    "vinyl-buffer": "^1.0.0",
 | 
			
		||||
    "vinyl-source-stream": "^1.1.0"
 | 
			
		||||
    "vinyl-source-stream": "^1.1.0",
 | 
			
		||||
    "watchify": "^3.6.0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
/* globals Y */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
class AbstractConnector {
 | 
			
		||||
module.exports = function (Y) {
 | 
			
		||||
  class AbstractConnector {
 | 
			
		||||
    /*
 | 
			
		||||
      opts contains the following information:
 | 
			
		||||
       role : String Role of this client ("master" or "slave")
 | 
			
		||||
@ -324,5 +324,6 @@ class AbstractConnector {
 | 
			
		||||
        throw new Error("I can't encode this json!")
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  Y.AbstractConnector = AbstractConnector
 | 
			
		||||
}
 | 
			
		||||
Y.AbstractConnector = AbstractConnector
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,8 @@
 | 
			
		||||
/* global getRandom, Y, wait, async */
 | 
			
		||||
/* global getRandom, wait, async */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
var globalRoom = {
 | 
			
		||||
module.exports = function (Y) {
 | 
			
		||||
  var globalRoom = {
 | 
			
		||||
    users: {},
 | 
			
		||||
    buffers: {},
 | 
			
		||||
    removeUser: function (user) {
 | 
			
		||||
@ -22,10 +23,10 @@ var globalRoom = {
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
Y.utils.globalRoom = globalRoom
 | 
			
		||||
  }
 | 
			
		||||
  Y.utils.globalRoom = globalRoom
 | 
			
		||||
 | 
			
		||||
function flushOne () {
 | 
			
		||||
  function flushOne () {
 | 
			
		||||
    var bufs = []
 | 
			
		||||
    for (var i in globalRoom.buffers) {
 | 
			
		||||
      if (globalRoom.buffers[i].length > 0) {
 | 
			
		||||
@ -41,13 +42,13 @@ function flushOne () {
 | 
			
		||||
    } else {
 | 
			
		||||
      return false
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
// setInterval(flushOne, 10)
 | 
			
		||||
  // setInterval(flushOne, 10)
 | 
			
		||||
 | 
			
		||||
var userIdCounter = 0
 | 
			
		||||
  var userIdCounter = 0
 | 
			
		||||
 | 
			
		||||
class Test extends Y.AbstractConnector {
 | 
			
		||||
  class Test extends Y.AbstractConnector {
 | 
			
		||||
    constructor (y, options) {
 | 
			
		||||
      if (options === undefined) {
 | 
			
		||||
        throw new Error('Options must not be undefined!')
 | 
			
		||||
@ -131,6 +132,7 @@ class Test extends Y.AbstractConnector {
 | 
			
		||||
    flushOne () {
 | 
			
		||||
      flushOne()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
Y.Test = Test
 | 
			
		||||
  Y.Test = Test
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
module.exports = function (Y) {
 | 
			
		||||
  /*
 | 
			
		||||
    Partial definition of an OperationStore.
 | 
			
		||||
    TODO: name it Database, operation store only holds operations.
 | 
			
		||||
 | 
			
		||||
@ -12,8 +12,8 @@
 | 
			
		||||
      - request a transaction
 | 
			
		||||
    * destroy()
 | 
			
		||||
      - destroy the database
 | 
			
		||||
*/
 | 
			
		||||
class AbstractDatabase {
 | 
			
		||||
  */
 | 
			
		||||
  class AbstractDatabase {
 | 
			
		||||
    constructor (y, opts) {
 | 
			
		||||
      this.y = y
 | 
			
		||||
      // E.g. this.listenersById[id] : Array<Listener>
 | 
			
		||||
@ -337,5 +337,6 @@ class AbstractDatabase {
 | 
			
		||||
        this.waitingTransactions.push(makeGen)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  Y.AbstractDatabase = AbstractDatabase
 | 
			
		||||
}
 | 
			
		||||
Y.AbstractDatabase = AbstractDatabase
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,8 @@
 | 
			
		||||
/* global Y, async, databases */
 | 
			
		||||
/* global async, databases */
 | 
			
		||||
/* eslint-env browser,jasmine,console */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
var Y = require('./SpecHelper.js')
 | 
			
		||||
 | 
			
		||||
for (let database of databases) {
 | 
			
		||||
  describe(`Database (${database})`, function () {
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,6 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
Y.IndexedDB = (function () {
 | 
			
		||||
module.exports = function (Y) {
 | 
			
		||||
  class Store {
 | 
			
		||||
    constructor (transaction, name) {
 | 
			
		||||
      this.store = transaction.objectStore(name)
 | 
			
		||||
@ -177,5 +175,5 @@ Y.IndexedDB = (function () {
 | 
			
		||||
      yield window.indexedDB.deleteDatabase(this.namespace)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return OperationStore
 | 
			
		||||
})()
 | 
			
		||||
  Y.IndexedDB = OperationStore
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,19 +0,0 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
/* eslint-env browser,jasmine */
 | 
			
		||||
 | 
			
		||||
if (typeof window !== 'undefined' && false) {
 | 
			
		||||
  describe('IndexedDB', function () {
 | 
			
		||||
    var ob
 | 
			
		||||
    beforeAll(function () {
 | 
			
		||||
      ob = new Y.IndexedDB(null, {namespace: 'Test', gcTimeout: -1})
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    afterAll(function (done) {
 | 
			
		||||
      ob.requestTransaction(function *() {
 | 
			
		||||
        yield* ob.removeDatabase()
 | 
			
		||||
        ob = null
 | 
			
		||||
        done()
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
Y.Memory = (function () {
 | 
			
		||||
module.exports = function (Y) {
 | 
			
		||||
  class Transaction extends Y.Transaction {
 | 
			
		||||
    constructor (store) {
 | 
			
		||||
      super(store)
 | 
			
		||||
@ -59,5 +58,5 @@ Y.Memory = (function () {
 | 
			
		||||
      delete this.ds
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return Database
 | 
			
		||||
})()
 | 
			
		||||
  Y.Memory = Database
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,11 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  This file contains a not so fancy implemantion of a Red Black Tree.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
class N {
 | 
			
		||||
module.exports = function (Y) {
 | 
			
		||||
  class N {
 | 
			
		||||
    // A created node is always red!
 | 
			
		||||
    constructor (val) {
 | 
			
		||||
      this.val = val
 | 
			
		||||
@ -123,9 +123,9 @@ class N {
 | 
			
		||||
        return this.parent.parent.left
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
class RBTree {
 | 
			
		||||
  class RBTree {
 | 
			
		||||
    constructor () {
 | 
			
		||||
      this.root = null
 | 
			
		||||
      this.length = 0
 | 
			
		||||
@ -484,6 +484,7 @@ class RBTree {
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
Y.utils.RBTree = RBTree
 | 
			
		||||
  Y.utils.RBTree = RBTree
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
/* eslint-env browser,jasmine,console */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
var Y = require('../SpecHelper.js')
 | 
			
		||||
var numberOfRBTreeTests = 1000
 | 
			
		||||
 | 
			
		||||
function itRedNodesDoNotHaveBlackChildren () {
 | 
			
		||||
 | 
			
		||||
@ -1,288 +0,0 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
/* eslint-env browser, jasmine */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  This is just a compilation of functions that help to test this library!
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// When testing, you store everything on the global object. We call it g
 | 
			
		||||
var g
 | 
			
		||||
if (typeof global !== 'undefined') {
 | 
			
		||||
  g = global
 | 
			
		||||
} else if (typeof window !== 'undefined') {
 | 
			
		||||
  g = window
 | 
			
		||||
} else {
 | 
			
		||||
  throw new Error('No global object?')
 | 
			
		||||
}
 | 
			
		||||
g.g = g
 | 
			
		||||
 | 
			
		||||
g.YConcurrency_TestingMode = true
 | 
			
		||||
 | 
			
		||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000
 | 
			
		||||
 | 
			
		||||
g.describeManyTimes = function describeManyTimes (times, name, f) {
 | 
			
		||||
  for (var i = 0; i < times; i++) {
 | 
			
		||||
    describe(name, f)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Wait for a specified amount of time (in ms). defaults to 5ms
 | 
			
		||||
*/
 | 
			
		||||
function wait (t) {
 | 
			
		||||
  if (t == null) {
 | 
			
		||||
    t = 5
 | 
			
		||||
  }
 | 
			
		||||
  return new Promise(function (resolve) {
 | 
			
		||||
    setTimeout(function () {
 | 
			
		||||
      resolve()
 | 
			
		||||
    }, t * 2)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
g.wait = wait
 | 
			
		||||
 | 
			
		||||
g.databases = ['Memory']
 | 
			
		||||
if (typeof window !== 'undefined') {
 | 
			
		||||
  g.databases.push('IndexedDB')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  returns a random element of o.
 | 
			
		||||
  works on Object, and Array
 | 
			
		||||
*/
 | 
			
		||||
function getRandom (o) {
 | 
			
		||||
  if (o instanceof Array) {
 | 
			
		||||
    return o[Math.floor(Math.random() * o.length)]
 | 
			
		||||
  } else if (o.constructor === Object) {
 | 
			
		||||
    var ks = []
 | 
			
		||||
    for (var key in o) {
 | 
			
		||||
      ks.push(key)
 | 
			
		||||
    }
 | 
			
		||||
    return o[getRandom(ks)]
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
g.getRandom = getRandom
 | 
			
		||||
 | 
			
		||||
function getRandomNumber (n) {
 | 
			
		||||
  if (n == null) {
 | 
			
		||||
    n = 9999
 | 
			
		||||
  }
 | 
			
		||||
  return Math.floor(Math.random() * n)
 | 
			
		||||
}
 | 
			
		||||
g.getRandomNumber = getRandomNumber
 | 
			
		||||
 | 
			
		||||
function * applyTransactions (relAmount, numberOfTransactions, objects, users, transactions) {
 | 
			
		||||
  function randomTransaction (root) {
 | 
			
		||||
    var f = getRandom(transactions)
 | 
			
		||||
    f(root)
 | 
			
		||||
  }
 | 
			
		||||
  for (var i = 0; i < numberOfTransactions * relAmount + 1; i++) {
 | 
			
		||||
    var r = Math.random()
 | 
			
		||||
    if (r >= 0.5) {
 | 
			
		||||
      // 50% chance to flush
 | 
			
		||||
      users[0].connector.flushOne() // flushes for some user.. (not necessarily 0)
 | 
			
		||||
    } else if (r >= 0.05) {
 | 
			
		||||
      // 45% chance to create operation
 | 
			
		||||
      randomTransaction(getRandom(objects))
 | 
			
		||||
    } else {
 | 
			
		||||
      // 5% chance to disconnect/reconnect
 | 
			
		||||
      var u = getRandom(users)
 | 
			
		||||
      if (u.connector.isDisconnected()) {
 | 
			
		||||
        yield u.reconnect()
 | 
			
		||||
      } else {
 | 
			
		||||
        yield u.disconnect()
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    yield wait()
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
g.applyRandomTransactionsAllRejoinNoGC = async(function * applyRandomTransactions (users, objects, transactions, numberOfTransactions) {
 | 
			
		||||
  yield* applyTransactions(1, numberOfTransactions, objects, users, transactions)
 | 
			
		||||
  yield users[0].connector.flushAll()
 | 
			
		||||
  yield wait()
 | 
			
		||||
  for (var u in users) {
 | 
			
		||||
    yield users[u].reconnect()
 | 
			
		||||
  }
 | 
			
		||||
  yield wait(100)
 | 
			
		||||
  yield users[0].connector.flushAll()
 | 
			
		||||
  yield g.garbageCollectAllUsers(users)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
g.applyRandomTransactionsWithGC = async(function * applyRandomTransactions (users, objects, transactions, numberOfTransactions) {
 | 
			
		||||
  yield* applyTransactions(1, numberOfTransactions, objects, users.slice(1), transactions)
 | 
			
		||||
  yield users[0].connector.flushAll()
 | 
			
		||||
  yield g.garbageCollectAllUsers(users)
 | 
			
		||||
  yield wait(100)
 | 
			
		||||
  for (var u in users) {
 | 
			
		||||
    // TODO: here, we enforce that two users never sync at the same time with u[0]
 | 
			
		||||
    //       enforce that in the connector itself!
 | 
			
		||||
    yield users[u].reconnect()
 | 
			
		||||
  }
 | 
			
		||||
  yield wait(100)
 | 
			
		||||
  yield users[0].connector.flushAll()
 | 
			
		||||
  yield wait(100)
 | 
			
		||||
  yield g.garbageCollectAllUsers(users)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
g.garbageCollectAllUsers = async(function * garbageCollectAllUsers (users) {
 | 
			
		||||
  // gc two times because of the two gc phases (really collect everything)
 | 
			
		||||
  yield wait(100)
 | 
			
		||||
  for (var i in users) {
 | 
			
		||||
    yield users[i].db.garbageCollect()
 | 
			
		||||
    yield users[i].db.garbageCollect()
 | 
			
		||||
  }
 | 
			
		||||
  yield wait(100)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
g.compareAllUsers = async(function * compareAllUsers (users) {
 | 
			
		||||
  var s1, s2 // state sets
 | 
			
		||||
  var ds1, ds2 // delete sets
 | 
			
		||||
  var allDels1, allDels2 // all deletions
 | 
			
		||||
  var db1 = [] // operation store of user1
 | 
			
		||||
 | 
			
		||||
  // 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()
 | 
			
		||||
    allDels1 = []
 | 
			
		||||
    yield* this.ds.iterate(this, null, null, function * (d) {
 | 
			
		||||
      allDels1.push(d)
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
  function * t2 () {
 | 
			
		||||
    s2 = yield* this.getStateSet()
 | 
			
		||||
    ds2 = yield* this.getDeleteSet()
 | 
			
		||||
    allDels2 = []
 | 
			
		||||
    yield* this.ds.iterate(this, null, null, function * (d) {
 | 
			
		||||
      allDels2.push(d)
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
  yield users[0].connector.flushAll()
 | 
			
		||||
  yield wait()
 | 
			
		||||
  yield g.garbageCollectAllUsers(users)
 | 
			
		||||
 | 
			
		||||
  for (var uid = 0; uid < users.length; uid++) {
 | 
			
		||||
    var u = users[uid]
 | 
			
		||||
    u.db.requestTransaction(function * () {
 | 
			
		||||
      // compare deleted ops against deleteStore
 | 
			
		||||
      yield* this.os.iterate(this, null, null, function * (o) {
 | 
			
		||||
        if (o.deleted === true) {
 | 
			
		||||
          expect(yield* this.isDeleted(o.id)).toBeTruthy()
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      // compare deleteStore against deleted ops
 | 
			
		||||
      var ds = []
 | 
			
		||||
      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.getOperation([d.id[0], d.id[1] + i])
 | 
			
		||||
          // gc'd or deleted
 | 
			
		||||
          if (d.gc) {
 | 
			
		||||
            expect(o).toBeFalsy()
 | 
			
		||||
          } else {
 | 
			
		||||
            expect(o.deleted).toBeTruthy()
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    // compare allDels tree
 | 
			
		||||
    yield wait()
 | 
			
		||||
    if (s1 == null) {
 | 
			
		||||
      u.db.requestTransaction(function * () {
 | 
			
		||||
        yield* t1.call(this)
 | 
			
		||||
        yield* this.os.iterate(this, null, null, function * (o) {
 | 
			
		||||
          o = Y.utils.copyObject(o)
 | 
			
		||||
          delete o.origin
 | 
			
		||||
          db1.push(o)
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
      yield wait()
 | 
			
		||||
    } else {
 | 
			
		||||
      // TODO: make requestTransaction return a promise..
 | 
			
		||||
      u.db.requestTransaction(function * () {
 | 
			
		||||
        yield* t2.call(this)
 | 
			
		||||
        expect(s1).toEqual(s2)
 | 
			
		||||
        expect(allDels1).toEqual(allDels2) // inner structure
 | 
			
		||||
        expect(ds1).toEqual(ds2) // exported structure
 | 
			
		||||
        var count = 0
 | 
			
		||||
        yield* this.os.iterate(this, null, null, function * (o) {
 | 
			
		||||
          o = Y.utils.copyObject(o)
 | 
			
		||||
          delete o.origin
 | 
			
		||||
          expect(db1[count++]).toEqual(o)
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
      yield wait()
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
g.createUsers = async(function * createUsers (self, numberOfUsers, database) {
 | 
			
		||||
  if (Y.utils.globalRoom.users[0] != null) {
 | 
			
		||||
    yield Y.utils.globalRoom.users[0].flushAll()
 | 
			
		||||
  }
 | 
			
		||||
  // destroy old users
 | 
			
		||||
  for (var u in Y.utils.globalRoom.users) {
 | 
			
		||||
    Y.utils.globalRoom.users[u].y.destroy()
 | 
			
		||||
  }
 | 
			
		||||
  self.users = null
 | 
			
		||||
 | 
			
		||||
  var promises = []
 | 
			
		||||
  for (var i = 0; i < numberOfUsers; i++) {
 | 
			
		||||
    promises.push(Y({
 | 
			
		||||
      db: {
 | 
			
		||||
        name: database,
 | 
			
		||||
        namespace: 'User ' + i,
 | 
			
		||||
        cleanStart: true,
 | 
			
		||||
        gcTimeout: -1
 | 
			
		||||
      },
 | 
			
		||||
      connector: {
 | 
			
		||||
        name: 'Test',
 | 
			
		||||
        debug: false
 | 
			
		||||
      }
 | 
			
		||||
    }))
 | 
			
		||||
  }
 | 
			
		||||
  self.users = yield Promise.all(promises)
 | 
			
		||||
  return self.users
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Until async/await arrives in js, we use this function to wait for promises
 | 
			
		||||
  by yielding them.
 | 
			
		||||
*/
 | 
			
		||||
function async (makeGenerator) {
 | 
			
		||||
  return function (arg) {
 | 
			
		||||
    var generator = makeGenerator.apply(this, arguments)
 | 
			
		||||
 | 
			
		||||
    function handle (result) {
 | 
			
		||||
      if (result.done) return Promise.resolve(result.value)
 | 
			
		||||
 | 
			
		||||
      return Promise.resolve(result.value).then(function (res) {
 | 
			
		||||
        return handle(generator.next(res))
 | 
			
		||||
      }, function (err) {
 | 
			
		||||
        return handle(generator.throw(err))
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
    try {
 | 
			
		||||
      return handle(generator.next())
 | 
			
		||||
    } catch (ex) {
 | 
			
		||||
      generator.throw(ex)
 | 
			
		||||
      // return Promise.reject(ex)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
g.async = async
 | 
			
		||||
 | 
			
		||||
function logUsers (self) {
 | 
			
		||||
  if (self.constructor === Array) {
 | 
			
		||||
    self = {users: self}
 | 
			
		||||
  }
 | 
			
		||||
  self.users[0].db.logTable()
 | 
			
		||||
  self.users[1].db.logTable()
 | 
			
		||||
  self.users[2].db.logTable()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
g.logUsers = logUsers
 | 
			
		||||
@ -1,4 +1,3 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -19,8 +18,8 @@
 | 
			
		||||
 * requiredOps
 | 
			
		||||
     - Operations that are required to execute this operation.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
var Struct = {
 | 
			
		||||
module.exports = function (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
 | 
			
		||||
 | 
			
		||||
@ -332,5 +331,6 @@ var Struct = {
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  Y.Struct = Struct
 | 
			
		||||
}
 | 
			
		||||
Y.Struct = Struct
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,3 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -74,7 +73,8 @@
 | 
			
		||||
     - this is called only by `getOperations(startSS)`. It makes an operation
 | 
			
		||||
       applyable on a given SS.
 | 
			
		||||
*/
 | 
			
		||||
class Transaction {
 | 
			
		||||
module.exports = function (Y) {
 | 
			
		||||
  class Transaction {
 | 
			
		||||
    /*
 | 
			
		||||
      Get a type based on the id of its model.
 | 
			
		||||
      If it does not exist yes, create it.
 | 
			
		||||
@ -649,5 +649,6 @@ class Transaction {
 | 
			
		||||
      op.left = op.origin
 | 
			
		||||
      return op
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  Y.Transaction = Transaction
 | 
			
		||||
}
 | 
			
		||||
Y.Transaction = Transaction
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
;(function () {
 | 
			
		||||
function extend (Y) {
 | 
			
		||||
  class YArray {
 | 
			
		||||
    constructor (os, _model, idArray, valArray) {
 | 
			
		||||
      this.os = os
 | 
			
		||||
@ -166,7 +165,7 @@
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Y.Array = new Y.utils.CustomType({
 | 
			
		||||
  Y.extend('Array', new Y.utils.CustomType({
 | 
			
		||||
    class: YArray,
 | 
			
		||||
    createType: function * YArrayCreator () {
 | 
			
		||||
      var modelid = this.store.getNextOpId()
 | 
			
		||||
@ -188,5 +187,11 @@
 | 
			
		||||
      })
 | 
			
		||||
      return new YArray(os, model.id, idArray, valArray)
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
})()
 | 
			
		||||
  }))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (typeof Y !== 'undefined') {
 | 
			
		||||
  extend(Y)
 | 
			
		||||
} else {
 | 
			
		||||
  module.exports = extend
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,8 @@
 | 
			
		||||
/* global createUsers, databases, wait, Y, compareAllUsers, getRandomNumber, applyRandomTransactionsAllRejoinNoGC, applyRandomTransactionsWithGC, async, garbageCollectAllUsers, describeManyTimes */
 | 
			
		||||
/* global createUsers, databases, wait, compareAllUsers, getRandomNumber, applyRandomTransactionsAllRejoinNoGC, applyRandomTransactionsWithGC, async, garbageCollectAllUsers, describeManyTimes */
 | 
			
		||||
/* eslint-env browser,jasmine */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
var Y = require('../SpecHelper.js')
 | 
			
		||||
var numberOfYArrayTests = 10
 | 
			
		||||
var repeatArrayTests = 2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
;(function () {
 | 
			
		||||
module.exports = function (Y) {
 | 
			
		||||
  class YMap {
 | 
			
		||||
    constructor (os, model, contents, opContents) {
 | 
			
		||||
      this._model = model.id
 | 
			
		||||
@ -292,4 +291,4 @@
 | 
			
		||||
      return new YMap(os, model, contents, opContents)
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
})()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,8 @@
 | 
			
		||||
/* global createUsers, Y, databases, compareAllUsers, getRandomNumber, applyRandomTransactionsAllRejoinNoGC, applyRandomTransactionsWithGC, async, describeManyTimes */
 | 
			
		||||
/* global createUsers, databases, compareAllUsers, getRandomNumber, applyRandomTransactionsAllRejoinNoGC, applyRandomTransactionsWithGC, async, describeManyTimes */
 | 
			
		||||
/* eslint-env browser,jasmine */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
var Y = require('../SpecHelper.js')
 | 
			
		||||
var numberOfYMapTests = 10
 | 
			
		||||
var repeatMapTeasts = 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
;(function () {
 | 
			
		||||
module.exports = function (Y) {
 | 
			
		||||
  class YTextBind extends Y.Array['class'] {
 | 
			
		||||
    constructor (os, _model, idArray, valArray) {
 | 
			
		||||
      super(os, _model, idArray, valArray)
 | 
			
		||||
@ -287,4 +286,4 @@
 | 
			
		||||
      return new YTextBind(os, model.id, idArray, valArray)
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
})()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								src/Utils.js
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								src/Utils.js
									
									
									
									
									
								
							@ -1,4 +1,3 @@
 | 
			
		||||
/* global Y */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -21,7 +20,10 @@
 | 
			
		||||
  database request to finish). EventHandler will help you to make your type
 | 
			
		||||
  synchronously.
 | 
			
		||||
*/
 | 
			
		||||
class EventHandler {
 | 
			
		||||
module.exports = function (Y) {
 | 
			
		||||
  Y.utils = {}
 | 
			
		||||
 | 
			
		||||
  class EventHandler {
 | 
			
		||||
    /*
 | 
			
		||||
      onevent: is called when the structure changes.
 | 
			
		||||
 | 
			
		||||
@ -132,10 +134,10 @@ class EventHandler {
 | 
			
		||||
        this.onevent(events)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
Y.utils.EventHandler = EventHandler
 | 
			
		||||
  }
 | 
			
		||||
  Y.utils.EventHandler = EventHandler
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  /*
 | 
			
		||||
    A wrapper for the definition of a custom type.
 | 
			
		||||
    Every custom type must have three properties:
 | 
			
		||||
 | 
			
		||||
@ -145,8 +147,8 @@ Y.utils.EventHandler = EventHandler
 | 
			
		||||
      - Given a model, creates a custom type
 | 
			
		||||
    * class
 | 
			
		||||
      - the constructor of the custom type (e.g. in order to inherit from a type)
 | 
			
		||||
*/
 | 
			
		||||
class CustomType { // eslint-disable-line
 | 
			
		||||
  */
 | 
			
		||||
  class CustomType { // eslint-disable-line
 | 
			
		||||
    constructor (def) {
 | 
			
		||||
      if (def.createType == null ||
 | 
			
		||||
        def.initType == null ||
 | 
			
		||||
@ -158,31 +160,31 @@ class CustomType { // eslint-disable-line
 | 
			
		||||
      this.initType = def.initType
 | 
			
		||||
      this.class = def.class
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
Y.utils.CustomType = CustomType
 | 
			
		||||
  }
 | 
			
		||||
  Y.utils.CustomType = CustomType
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  /*
 | 
			
		||||
    Make a flat copy of an object
 | 
			
		||||
    (just copy properties)
 | 
			
		||||
*/
 | 
			
		||||
function copyObject (o) {
 | 
			
		||||
  */
 | 
			
		||||
  function copyObject (o) {
 | 
			
		||||
    var c = {}
 | 
			
		||||
    for (var key in o) {
 | 
			
		||||
      c[key] = o[key]
 | 
			
		||||
    }
 | 
			
		||||
    return c
 | 
			
		||||
}
 | 
			
		||||
Y.utils.copyObject = copyObject
 | 
			
		||||
  }
 | 
			
		||||
  Y.utils.copyObject = copyObject
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  /*
 | 
			
		||||
    Defines a smaller relation on Id's
 | 
			
		||||
*/
 | 
			
		||||
function smaller (a, b) {
 | 
			
		||||
  */
 | 
			
		||||
  function smaller (a, b) {
 | 
			
		||||
    return a[0] < b[0] || (a[0] === b[0] && a[1] < b[1])
 | 
			
		||||
}
 | 
			
		||||
Y.utils.smaller = smaller
 | 
			
		||||
  }
 | 
			
		||||
  Y.utils.smaller = smaller
 | 
			
		||||
 | 
			
		||||
function compareIds (id1, id2) {
 | 
			
		||||
  function compareIds (id1, id2) {
 | 
			
		||||
    if (id1 == null || id2 == null) {
 | 
			
		||||
      if (id1 == null && id2 == null) {
 | 
			
		||||
        return true
 | 
			
		||||
@ -194,5 +196,6 @@ function compareIds (id1, id2) {
 | 
			
		||||
    } else {
 | 
			
		||||
      return false
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  Y.utils.compareIds = compareIds
 | 
			
		||||
}
 | 
			
		||||
Y.utils.compareIds = compareIds
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										63
									
								
								src/y.js
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								src/y.js
									
									
									
									
									
								
							@ -1,7 +1,63 @@
 | 
			
		||||
/* @flow */
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
require('./Connector.js')(Y)
 | 
			
		||||
require('./Database.js')(Y)
 | 
			
		||||
require('./Transaction.js')(Y)
 | 
			
		||||
require('./Struct.js')(Y)
 | 
			
		||||
require('./Utils.js')(Y)
 | 
			
		||||
require('./Databases/RedBlackTree.js')(Y)
 | 
			
		||||
require('./Databases/Memory.js')(Y)
 | 
			
		||||
require('./Databases/IndexedDB.js')(Y)
 | 
			
		||||
require('./Connectors/Test.js')(Y)
 | 
			
		||||
 | 
			
		||||
var requiringModules = {}
 | 
			
		||||
 | 
			
		||||
module.exports = Y
 | 
			
		||||
 | 
			
		||||
Y.extend = function (name, value) {
 | 
			
		||||
  Y[name] = value
 | 
			
		||||
  var resolves = requiringModules[name]
 | 
			
		||||
  if (requiringModules[name] != null) {
 | 
			
		||||
    for (var i = 0; i < resolves.length; i++) {
 | 
			
		||||
      resolves[i]()
 | 
			
		||||
    }
 | 
			
		||||
    delete requiringModules[name]
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
require('./Types/Array.js')(Y)
 | 
			
		||||
require('./Types/Map.js')(Y)
 | 
			
		||||
require('./Types/TextBind.js')(Y)
 | 
			
		||||
 | 
			
		||||
function Y (opts) {
 | 
			
		||||
  opts.types = opts.types != null ? opts.types : []
 | 
			
		||||
  var modules = [opts.db.name, opts.connector.name].concat(opts.types)
 | 
			
		||||
  var promises = []
 | 
			
		||||
  for (var i = 0; i < modules.length; i++) {
 | 
			
		||||
    if (Y[modules[i]] == null) {
 | 
			
		||||
      try {
 | 
			
		||||
        require(modules[i])(Y)
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
        // module does not exist
 | 
			
		||||
        if (window != null) {
 | 
			
		||||
          if (requiringModules[modules[i]] == null) {
 | 
			
		||||
            var imported = document.createElement('script')
 | 
			
		||||
            var name = modules[i].toLowerCase()
 | 
			
		||||
            imported.src = opts.sourceDir + '/y-' + name + '/y-' + name + '.js'
 | 
			
		||||
            document.head.appendChild(imported)
 | 
			
		||||
            requiringModules[modules[i]] = []
 | 
			
		||||
          }
 | 
			
		||||
          promises.push(new Promise(function (resolve) {
 | 
			
		||||
            requiringModules[modules[i]].push(resolve)
 | 
			
		||||
          }))
 | 
			
		||||
        } else {
 | 
			
		||||
          throw e
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return Promise.all(promises).then(function () {
 | 
			
		||||
    return new Promise(function (resolve) {
 | 
			
		||||
      var yconfig = new YConfig(opts, function () {
 | 
			
		||||
        yconfig.db.whenUserIdSet(function () {
 | 
			
		||||
@ -9,6 +65,7 @@ function Y (opts) {
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class YConfig {
 | 
			
		||||
@ -49,9 +106,3 @@ class YConfig {
 | 
			
		||||
if (typeof window !== 'undefined') {
 | 
			
		||||
  window.Y = Y
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (typeof YConcurrency_TestingMode !== 'undefined') {
 | 
			
		||||
  g.Y = Y //eslint-disable-line
 | 
			
		||||
  // debugger //eslint-disable-line
 | 
			
		||||
}
 | 
			
		||||
Y.utils = {}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user