///
///
export interface HandlerIF {
// Spec indicated define should return something but does not state what
defineProperty(name: string, desc: PropertyDescriptor): void;
delete (name: string): bool;
getPropertyNames(name: string): string[];
getOwnPropertyNames(name: string): string[];
getOwnPropertyDescriptor(name: string): PropertyDescriptor;
getPropertyDescriptor(name: string): PropertyDescriptor;
// Returns object containing name,PropertyDescriptor pairs
fix(): any;
// Properties must always be configuable, the reasoning is obscure
}
export interface ProxyIF {
create(handler : HandlerIF, proto?: any);
createFunction(handler, callTrap, constructTrap);
}
declare var Proxy: ProxyIF;
class VirtualHandler implements HandlerIF {
private delegate : any= {};
private props: any = {};
constructor (obj?: any = {}) {
this.delegate = obj;
}
addProperty(name: string, writeCB: (any) => void ) {
var that = this;
var desc: PropertyDescriptor = {
get: function () {
return that.props[name].value;
},
set: function(value) {
writeCB(value);
that.props[name].value = value;
}
}
this.props[name] = { value: null, pd: desc };
}
defineProperty(name: string, desc: PropertyDescriptor): void {
Object.defineProperty(this.delegate, name, desc);
}
delete (name: string): bool {
return delete this.delegate[name];
}
getOwnPropertyNames() : string[] {
return Object.getOwnPropertyNames(this.delegate);
}
getPropertyNames() : string[] {
var getPropertyNames = function (obj, name) {
if (obj === null) return [];
return Object.getOwnPropertyNames(obj).concat(
getPropertyNames(Object.getPrototypeOf(obj)));
}
return getPropertyNames(this.delegate);
}
getOwnPropertyDescriptor(name: string) : PropertyDescriptor {
var that = this;
if (this.props[name] !== undefined) {
return that.props[name].pd;
} else {
var desc = Object.getOwnPropertyDescriptor(this.delegate, name);
if (desc !== undefined) desc.configurable = true;
return desc;
}
}
getPropertyDescriptor(name: string) : PropertyDescriptor {
var getPropertyDescriptor = function (obj, name) {
if (obj === null) return undefined;
var desc = Object.getOwnPropertyDescriptor(obj, name);
if (desc !== undefined)
return desc;
return getPropertyDescriptor(Object.getPrototypeOf(obj));
}
var desc = getPropertyDescriptor(this.delegate, name);
if (desc !== undefined) desc.configurable = true;
return desc;
}
fix() {
var result = {};
Object.getOwnPropertyNames(this.delegate).forEach(function(name) {
result[name] = Object.getOwnPropertyDescriptor(this.delegate, name);
});
return result;
}
}
/* ==================================================================== */
class Tester {
private handler : VirtualHandler;
constructor () {
this.handler = new VirtualHandler(this);
this.handler.addProperty("foo", function (value) {
console.log('New foo: ' + value);
});
return Proxy.create(this.handler,this);
}
}
var tester = new Tester()
tester.foo = 1;