Ejemplo n.º 1
0
test( 'can find _super in prototype chain', function ( t ) {

	expect(1);

	var grandparent = { talk: () => t.ok( true ) },
		parent = create( grandparent ),
		instance = create( parent );

	instance.talk = wrap( parent, 'talk', callSuper );

	instance.talk();
});
Ejemplo n.º 2
0
function initialiseProperties ( ractive, options ) {
	// Generate a unique identifier, for places where you'd use a weak map if it
	// existed
	ractive._guid = 'r-' + uid++;

	// events
	ractive._subs = create( null );

	// storage for item configuration from instantiation to reset,
	// like dynamic functions or original values
	ractive._config = {};

	// two-way bindings
	ractive._twowayBindings = create( null );

	// animations (so we can stop any in progress at teardown)
	ractive._animations = [];

	// nodes registry
	ractive.nodes = {};

	// live queries
	ractive._liveQueries = [];
	ractive._liveComponentQueries = [];

	// bound data functions
	ractive._boundFunctions = [];

	// observers
	ractive._observers = [];


	// properties specific to inline components
	if ( options.component ) {
		ractive.parent = options.parent;
		ractive.container = options.container || null;
		ractive.root = ractive.parent.root;

		ractive.component = options.component;
		options.component.instance = ractive;

		// for hackability, this could be an open option
		// for any ractive instance, but for now, just
		// for components and just for ractive...
		ractive._inlinePartials = options.inlinePartials;
	} else {
		ractive.root = ractive;
		ractive.parent = ractive.container = null;
	}
}
Ejemplo n.º 3
0
	configure: function ( Parent, target, options ) {
		var name = this.name, option = options[ name ], registry;

		registry = create( Parent[name] );

		for ( let key in option ) {
			registry[ key ] = option[ key ];
		}

		target[ name ] = registry;
	},
Ejemplo n.º 4
0
test( 'only wraps when this._super used in method', function ( t ) {

	expect(1);

	var parent = { talk: () => t.ok( true ) },
		instance = create( parent ),
		method = function () {};

	t.equal( wrap( parent, 'talk', method), method );

});
Ejemplo n.º 5
0
test( 'can call _super on parent', function ( t ) {

	expect(1);

	var parent = { talk: () => t.ok( true ) },
		instance = create( parent );

	instance.talk = wrap( parent, 'talk', callSuper );

	instance.talk();
});
Ejemplo n.º 6
0
test( 'parent _super can be added later', function ( t ) {

	expect(1);

	var parent = {},
		instance = create( parent );

	instance.talk = wrap( parent, 'talk', callSuper );

	parent.talk = () => t.ok( true );

	instance.talk();
});
Ejemplo n.º 7
0
test( 'safe to use _super with no parent', function ( t ) {

	expect(1);

	var parent = {}, instance = create( parent );

	instance.talk = wrap( parent, 'talk', function () {
		this._super()
		t.ok( true )
	} );

	instance.talk();
});
Ejemplo n.º 8
0
test( 'if this._super is non-function, returns as value', function ( t ) {

	expect(1);

	var data = { foo: 'bar' },
		parent = { talk: data },
		instance = create( parent ),
		method = function () { return this._super(); };

	instance.talk = wrap( parent, 'talk', method );

	t.equal( instance.talk() , data );

});
Ejemplo n.º 9
0
test( 'parent instance can be changed', function ( t ) {

	expect(2);

	var parent = { talk: () => false },
		newParent = { talk: () => t.ok( true ) },
		instance = create( parent );

	instance.talk = wrap( parent, 'talk', callSuper );
	t.equal( instance.talk._parent, parent );
	instance.talk._parent = newParent;

	instance.talk();
});
Ejemplo n.º 10
0
test( '"this" in methods refers to correct instance', function ( t ) {

	expect(2);

	// no fat arrows! that would bind "this" to test method or module!

	var parent = {
			talk: function () {
				t.equal( this, instance, '_super method has correct "this"' );
			}
		},
		instance = create( parent );

	instance.talk = wrap( parent, 'talk', function () {
		t.equal( this, instance, 'instance method has correct "this"' );
		this._super();
	});

	instance.talk();
});
Ejemplo n.º 11
0
export default function readTemplate ( parser ) {
	let fragment = [];
	let partials = create( null );
	let hasPartials = false;

	let preserveWhitespace = parser.preserveWhitespace;

	while ( parser.pos < parser.str.length ) {
		let pos = parser.pos, item, partial;

		if ( partial = parser.read( PARTIAL_READERS ) ) {
			if ( partials[ partial.n ] ) {
				parser.pos = pos;
				parser.error( 'Duplicated partial definition' );
			}

			cleanup( partial.f, parser.stripComments, preserveWhitespace, !preserveWhitespace, !preserveWhitespace );

			partials[ partial.n ] = partial.f;
			hasPartials = true;
		} else if ( item = parser.read( READERS ) ) {
			fragment.push( item );
		} else  {
			parser.error( 'Unexpected template content' );
		}
	}

	let result = {
		v: TEMPLATE_VERSION,
		t: fragment
	};

	if ( hasPartials ) {
		result.p = partials;
	}

	return result;
}
Ejemplo n.º 12
0
var Viewmodel = function ( options ) {
	var { adapt, data, ractive, computed, mappings } = options,
		key,
		mapping;

	// TODO is it possible to remove this reference?
	this.ractive = ractive;

	this.adaptors = adapt;
	this.onchange = options.onchange;

	this.cache = {}; // we need to be able to use hasOwnProperty, so can't inherit from null
	this.cacheMap = create( null );

	this.deps = {
		computed: create( null ),
		'default': create( null )
	};
	this.depsMap = {
		computed: create( null ),
		'default': create( null )
	};

	this.patternObservers = [];

	this.specials = create( null );

	this.wrapped = create( null );
	this.computations = create( null );

	this.captureGroups = [];
	this.unresolvedImplicitDependencies = [];

	this.changes = [];
	this.implicitChanges = {};
	this.noCascade = {};

	this.data = data;

	// set up explicit mappings
	this.mappings = create( null );
	for ( key in mappings ) {
		this.map( getKeypath( key ), mappings[ key ] );
	}

	if ( data ) {
		// if data exists locally, but is missing on the parent,
		// we transfer ownership to the parent
		for ( key in data ) {
			if ( ( mapping = this.mappings[ key ] ) && mapping.getValue() === undefined ) {
				mapping.setValue( data[ key ] );
			}
		}
	}

	for ( key in computed ) {
		if ( mappings && key in mappings ) {
			fatal( 'Cannot map to a computed property (\'%s\')', key );
		}

		this.compute( getKeypath( key ), computed[ key ] );
	}

	this.ready = true;
};
Ejemplo n.º 13
0
	registryNames.forEach( name => {
		ractive[ name ] = extend( create( ractive.constructor[ name ] || null ), userOptions[ name ] );
	});
Ejemplo n.º 14
0
function initialiseRactiveInstance ( ractive, userOptions = {}, options = {} ) {
	var el, viewmodel;

	if ( Ractive.DEBUG ) {
		welcome();
	}

	initialiseProperties( ractive, options );

	// TODO remove this, eventually
	defineProperty( ractive, 'data', { get: deprecateRactiveData });

	// TODO don't allow `onconstruct` with `new Ractive()`, there's no need for it
	constructHook.fire( ractive, userOptions );

	// Add registries
	registryNames.forEach( name => {
		ractive[ name ] = extend( create( ractive.constructor[ name ] || null ), userOptions[ name ] );
	});

	// Create a viewmodel
	viewmodel = new Viewmodel({
		adapt: getAdaptors( ractive, ractive.adapt, userOptions ),
		data: dataConfigurator.init( ractive.constructor, ractive, userOptions ),
		computed: getComputationSignatures( ractive, extend( create( ractive.constructor.prototype.computed ), userOptions.computed ) ),
		mappings: options.mappings,
		ractive: ractive,
		onchange: () => runloop.addRactive( ractive )
	});

	ractive.viewmodel = viewmodel;

	// This can't happen earlier, because computed properties may call `ractive.get()`, etc
	viewmodel.init();

	// init config from Parent and options
	config.init( ractive.constructor, ractive, userOptions );

	configHook.fire( ractive );
	initHook.begin( ractive );

	// // If this is a component with a function `data` property, call the function
	// // with `ractive` as context (unless the child was also a function)
	// if ( typeof ractive.constructor.prototype.data === 'function' && typeof userOptions.data !== 'function' ) {
	// 	viewmodel.reset( ractive.constructor.prototype.data.call( ractive ) || fatal( '`data` functions must return a data object' ) );
	// }


	// Render virtual DOM
	if ( ractive.template ) {
		let cssIds;

		if ( options.cssIds || ractive.cssId ) {
			cssIds = options.cssIds ? options.cssIds.slice() : [];

			if ( ractive.cssId ) {
				cssIds.push( ractive.cssId );
			}
		}

		ractive.fragment = new Fragment({
			template: ractive.template,
			root: ractive,
			owner: ractive, // saves doing `if ( this.parent ) { /*...*/ }` later on
			cssIds
		});
	}

	initHook.end( ractive );

	// render automatically ( if `el` is specified )
	if ( el = getElement( ractive.el ) ) {
		let promise = ractive.render( el, ractive.append );

		if ( Ractive.DEBUG_PROMISES ) {
			promise.catch( err => {
				warnOnceIfDebug( 'Promise debugging is enabled, to help solve errors that happen asynchronously. Some browsers will log unhandled promise rejections, in which case you can safely disable promise debugging:\n  Ractive.DEBUG_PROMISES = false;' );
				warnIfDebug( 'An error happened during rendering', { ractive });
				err.stack && logIfDebug( err.stack );

				throw err;
			});
		}
	}
}