Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 117 additions & 79 deletions built/spec/vue_component_spec.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
Expand All @@ -12,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
var vue_ext_1 = require("../src/vue_ext");
var vue_api_1 = require("../src/vue_api");
var Vue = require('vue');
var es6_constructor_util_1 = require("../src/es6_constructor_util");
function getVueClass(tsClass) {
return new Promise(tsClass.getVueClassAsync());
}
Expand All @@ -23,51 +19,43 @@ describe("Component Creation Plugins", function () {
instance.property = "it worked";
});
});
// VueComponentCreationPlugins.push(function (instance : PluginTest) {
// instance.property = "it worked";
// });
var PluginTest = (function (_super) {
__extends(PluginTest, _super);
function PluginTest() {
_super.apply(this, arguments);
}
PluginTest = __decorate([
vue_ext_1.VueComponent("plugin-test", "#noop")
], PluginTest);
return PluginTest;
})(vue_api_1.VueApi);
let PluginTest = class extends vue_api_1.VueApi {
};
PluginTest = __decorate([
vue_ext_1.VueComponent("plugin-test", "#noop")
], PluginTest);
getVueClass(PluginTest).then(function (type) {
expect(new type().property).toBe("it worked");
done();
});
});
it('should run creation plugins on all instances', function (done) {
var i = 0;
var i = 1;
vue_ext_1.VueComponent.plugin(function (instanceChain) {
instanceChain.push(function (instance) {
instance.property = i++;
});
});
var PluginTest = (function (_super) {
__extends(PluginTest, _super);
function PluginTest() {
_super.apply(this, arguments);
let PluginTest = class extends vue_api_1.VueApi {
constructor() {
super();
}
PluginTest = __decorate([
vue_ext_1.VueComponent("plugin-test", "#noop")
], PluginTest);
return PluginTest;
})(vue_api_1.VueApi);
};
PluginTest = __decorate([
vue_ext_1.VueComponent("plugin-test", "#noop")
], PluginTest);
getVueClass(PluginTest).then(function (type) {
expect(new type().property).toBe(0);
expect(new type().property).toBe(1);
expect(new type().property).toBe(2);
done();
}).catch(function (e) {
console.log(e);
});
});
});
describe("Component Resolution Plugins", function () {
it('should run resolution plugins', function (done) {
var i = 0;
var i = 100;
vue_ext_1.VueComponent.plugin(function (instanceChain, classChain) {
classChain.push(function (type, vueClass) {
return new Promise(function (resolve) {
Expand All @@ -76,42 +64,33 @@ describe("Component Resolution Plugins", function () {
});
});
});
var PluginTest = (function (_super) {
__extends(PluginTest, _super);
function PluginTest() {
_super.apply(this, arguments);
}
PluginTest = __decorate([
vue_ext_1.VueComponent("plugin-test", "#noop")
], PluginTest);
return PluginTest;
})(vue_api_1.VueApi);
let PluginTest = class extends vue_api_1.VueApi {
};
PluginTest = __decorate([
vue_ext_1.VueComponent("plugin-test", "#noop")
], PluginTest);
getVueClass(PluginTest).then(function (type) {
expect(type.someProp).toBe(0);
expect(type.someProp).toBe(100);
done();
});
});
});
describe('Inheritance', function () {
fit('should invoke a base class constructor', function (done) {
var X = (function (_super) {
__extends(X, _super);
function X() {
_super.call(this);
it('should invoke a base class constructor', function (done) {
class X extends vue_api_1.VueApi {
constructor() {
super();
this.x = 1;
}
return X;
})(vue_api_1.VueApi);
var Y = (function (_super) {
__extends(Y, _super);
function Y() {
_super.call(this);
}
let Y = class extends X {
constructor() {
super();
}
Y = __decorate([
vue_ext_1.VueComponent("", "")
], Y);
return Y;
})(X);
};
Y = __decorate([
vue_ext_1.VueComponent("", "")
], Y);
getVueClass(Y).then(function (type) {
var instance = new type();
expect(instance.x).toBe(1);
Expand All @@ -131,31 +110,90 @@ describe('Inheritance', function () {
});
});
});
var PluginTest = (function (_super) {
__extends(PluginTest, _super);
function PluginTest() {
_super.apply(this, arguments);
}
PluginTest.val = 'PARENT';
PluginTest = __decorate([
vue_ext_1.VueComponent('plugin-base', '#no-op')
], PluginTest);
return PluginTest;
})(vue_api_1.VueApi);
var ChildClass = (function (_super) {
__extends(ChildClass, _super);
function ChildClass() {
_super.apply(this, arguments);
}
ChildClass.val = 'CHILD';
ChildClass = __decorate([
vue_ext_1.VueComponent('plugin-sub', '#no-op')
], ChildClass);
return ChildClass;
})(PluginTest);
let PluginTest = class extends vue_api_1.VueApi {
};
PluginTest.val = 'PARENT';
PluginTest = __decorate([
vue_ext_1.VueComponent('plugin-base', '#no-op')
], PluginTest);
let ChildClass = class extends PluginTest {
};
ChildClass.val = 'CHILD';
ChildClass = __decorate([
vue_ext_1.VueComponent('plugin-sub', '#no-op')
], ChildClass);
getVueClass(ChildClass).then(function (type) {
expect(PluginTest.val).toBe('ran parent');
done();
});
});
});
describe("E6ConstructorUtil", function () {
it('should invoke constructor normally', function () {
class C0 {
constructor() {
this.c0Prop = "c0";
}
}
var instance = {};
es6_constructor_util_1.ES6ConstructorUtil.invokeES6Constructor(instance, C0);
expect(instance.c0Prop).toBe("c0");
});
it('should invoke base constructor even if constructor not provided', function () {
class C0 {
constructor() {
this.c0Prop = "c0";
}
}
class C1 extends C0 {
constructor() {
super();
}
}
var instance = {};
es6_constructor_util_1.ES6ConstructorUtil.invokeES6Constructor(instance, C1);
expect(instance.c0Prop).toBe("c0");
});
it('should invoke nested base constructor', function () {
class C0 {
constructor() {
this.c0Prop = "c0";
}
}
class C1 extends C0 {
constructor() {
super();
this.c1Prop = "c1";
}
}
class C2 extends C1 {
constructor() {
super();
this.c2Prop = "c2";
}
}
var instance = {};
es6_constructor_util_1.ES6ConstructorUtil.invokeES6Constructor(instance, C2);
expect(instance.c0Prop).toBe("c0");
expect(instance.c1Prop).toBe("c1");
expect(instance.c2Prop).toBe("c2");
});
it('should be able to invoke a constructor twice', function () {
class C0 {
constructor() {
this.c0Prop = "c0";
}
}
class C1 extends C0 {
constructor() {
super();
}
}
var instance = {};
es6_constructor_util_1.ES6ConstructorUtil.invokeES6Constructor(instance, C1);
expect(instance.c0Prop).toBe("c0");
var instance = {};
es6_constructor_util_1.ES6ConstructorUtil.invokeES6Constructor(instance, C1);
expect(instance.c0Prop).toBe("c0");
});
});
4 changes: 4 additions & 0 deletions built/src/es6_constructor_util.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export declare function buildCtor(classRef: any): void;
export declare var ES6ConstructorUtil: {
invokeES6Constructor: (thisRef: any, classRef: any) => void;
};
120 changes: 120 additions & 0 deletions built/src/es6_constructor_util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
var RE_BLOCKS = new RegExp([
/\/(\*)[^*]*\*+(?:[^*\/][^*]*\*+)*\//.source,
/\/(\/)[^\n]*$/.source,
/"(?:[^"\\]*|\\[\S\s])*"|'(?:[^'\\]*|\\[\S\s])*'/.source,
/(?:[$\w\)\]]|\+\+|--)\s*\/(?![*\/])/.source,
/\/(?=[^*\/])[^[/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[/\\]*)*?\/[gim]*/.source
].join('|'), // - regex
'gm' // note: global+multiline with replace() need test
);
// remove comments, keep other blocks
function stripComments(str) {
return str.replace(RE_BLOCKS, function (match, mlc, slc) {
return mlc ? ' ' :
slc ? '' :
match; // divisor, regex, or string, return as-is
});
}
//grab a substring while culling {} or () as needed
function strip(input, open, close, shouldMatch) {
var endIdx = -1;
var lengthTarget = shouldMatch ? 1 : 0;
var stack = [];
for (var i = 0; i < input.length; i++) {
var char = input[i];
if (char === open) {
stack.push(open);
}
else if (char === close) {
if (stack.length === lengthTarget) {
endIdx = i;
break;
}
else {
stack.pop();
}
}
}
if (endIdx === -1) {
return input;
}
if (input[0] === open) {
return input.substr(1, endIdx);
}
else {
return input.substr(0, endIdx);
}
}
//any function pointer will do here, use buildCtor
//just so we dont re-allocate a blank fn
var fn = buildCtor;
//get the constructor body string from a class reference
function extractConstructorBody(classRef) {
var fnStr = stripComments(classRef.toString());
var start = fnStr.indexOf("constructor");
var ctorStr = "";
if (start !== -1) {
//find constructor and strip away everything after { }
ctorStr = strip(fnStr.substr(start + "constructor".length), '{', '}', true);
start = ctorStr.indexOf('{');
//find the first {, start + 1 to strip it
ctorStr = ctorStr.substr(start + 1);
//blow away the unmatched '}'
ctorStr = strip(ctorStr, '{', '}', false).trim();
if (fn.__proto__ !== classRef.__proto__ && ctorStr.indexOf("super") !== 0) {
return "__$super$__.shift().call(this, __$super$__)" + ctorStr;
}
else {
//replace super() and super.xxxx with special variable
//for super() case invoke with call, leave off last ) on purpose
//todo arguments not supported
return ctorStr.replace(/super\(/g, `
/*arguments not supported yet*/
var parentCtx = __$super$__.shift();
parentCtx.call(this, __$super$__
`);
}
}
else {
//if this classRef doesnt extend anything just return a blank string
if (fn.__proto__ === classRef.__proto__) {
return "";
}
else {
//if it does extend something we need to invoke super before running the
//actual constructor implementation
return "__$super$__.shift().call(this, __$super$__)" + ctorStr;
}
}
}
//build a constructor that can be invoked with .call
function buildCtor(classRef) {
if (classRef.hasOwnProperty("__$ctor$__"))
return;
//save compiled function on a hidden variable on the class
classRef.__$ctor$__ = new Function("__$super$__", extractConstructorBody(classRef));
//build up the class heirarchy array which will store references to all base classes' __$ctor$__ functions
var heirarchy = [];
//this is the end point of our iterator
var fn = function () { };
var fnproto = buildCtor.__proto__;
var ptr = classRef.__proto__;
//while the ptr is not the function prototype, call build on the pointer
//add the built ctor to the heirarchy array, update our pointer
while (ptr && ptr !== fnproto) {
buildCtor(ptr);
heirarchy.push(ptr.__$ctor$__);
ptr = ptr.__proto__;
}
//assign the heirarchy for later use
classRef.__$heirarchy$__ = heirarchy;
}
exports.buildCtor = buildCtor;
//call a constructor function in an es6 compliant way
function invokeES6Constructor(thisRef, classRef) {
buildCtor(classRef);
//clone the heirarchy since calls will shift items off the input array
var heirarchy = classRef.__$heirarchy$__.slice(0);
classRef.__$ctor$__.call(thisRef, heirarchy);
}
exports.ES6ConstructorUtil = { invokeES6Constructor };
Loading