Closed McTwist closed 6 years ago
yeah they also have proxy support like this
// Underlying plain object.
var target = { foo: 'bar' };
// Handler table, provides traps for interaction (can be modified on-the-fly).
var handler = {
has: function (targ, key) {
print('has called for key=' + key);
return key in targ; // return unmodified existence status
},
get: function (targ, key, recv) {
print('get called for key=' + key);
return targ[key]; // return unmodified value
},
set: function (targ, key, val, recv) {
print('set called for key=' + key + ', val=' + val);
targ[key] = val; // must perform write to target manually if 'set' defined
return true; // true: indicate that property write was allowed
},
deleteProperty: function (targ, key) {
print('deleteProperty called for key=' + key);
delete targ[key]; // must perform delete to target manually if 'deleteProperty' defined
return true; // true: indicate that property delete was allowed
}
};
// Create proxy object.
var proxy = new Proxy(target, handler);
// Proxy object is then accessed normally.
print('foo' in proxy);
proxy.foo = 321;
print(proxy.foo);
I found it problematic to create this as there is no general way to allow creation of an object through a function and still put a proxy on it to handle all getter and setters. If it would be possible to handle them like PHP's __get
and __set
, then it would solve everything.
So if we really want such a feature, we need to either add a Proxy on it within a function that is called after the object is created, or we remove the previous functor and instead make it just a function that returns an object.
https://tc39.github.io/ecma262/#sec-additional-properties-of-the-object.prototype-object We forgot about this!!
It should work. If I ever come around fixing this, it is really easy to do.
That, or, I wrote some prototype code that works for now using proxies.
var blocklandJS_objhandler = {
get: function(tar, name) {
if(name == "_id") {
return ts_call(tar.type, "getID", tar.obj);
}
return ts_getObjectField(tar.obj, name);
},
set: function(tar, name, val) {
ts_setObjectField(tar.obj, name, val);
}
};
// Link a namespace to a function that will create an object
function ts_linkClass(type) {
// Create a new method
function _createMethod(that, obj, name, func) {
that[name] = function() {
var args = [obj];
args.push.apply(args, arguments);
return func.apply(null, args);
};
}
var kk = function(args) {
var _type = type;
var _obj = ts_newObj(_type);
// Apply all methods
var _functions = ts_getMethods(_type);
for (var i = 0; i < _functions.length; ++i) {
var _func_name = _functions[i];
var _func = ts_func(_type, _func_name);
// Create method
_createMethod(this, _obj, _func_name, _func);
}
// Setter
this.obj = _obj;
this.type = _type;
this.set = function(name, value) {
ts_setObjectField(_obj, name, value);
};
//this.prototype.__defineGetter__(function(name) {
// return ts_getObjectField(_obj, name);
// });
// Getter
this.get = function(name) {
return ts_getObjectField(_obj, name);
};
// Add arguments
for (var i in args) {
// Workaround
if (i === 'datablock' && this.setDatablock)
this.setDatablock(args[i]);
this.set(i, args[i]);
}
// Make it visible from TS
ts_registerObject(_obj);
};
return kk;
}
function ts_nbj(type){
var q = ts_linkClass(type);
var kk = new q();
var proxy = new Proxy(kk, blocklandJS_objhandler);
return proxy;
}
function ts_globalVariables() {
var h = {
get: function(tar, name) {
return ts_getVariable(name);
},
set: function(tar, name, val) {
ts_setVariable(name, val);
}
}
return new Proxy({}, h);
}
Thoughts?
Actually, I finished a rework of the entire thing.
var blocklandJS_objhandler = {
construct: function(target, argumentsList, newT) {
newT.apply(target, argumentsList);
return new Proxy(target, blocklandJS_funcHandler);
}
};
var blocklandJS_funcHandler = {
get: function(tar, name) {
if(ts_getMethods(tar.type).some(function(e, i) {
if(name.toLowerCase() === e.toLowerCase()){
return true;
}
}))
{
return function() {
var args = [tar.type, name, tar.obj];
args.push.apply(args, arguments);
return ts_call.apply(null, args);
}
} //Handle function calls.
return ts_getObjectField(tar.obj, name);
},
set: function(tar, name, val) {
ts_setObjectField(tar.obj, name, val);
}
};
// Link a namespace to a function that will create an object
function ts_linkClass(type) {
var kk = function(args) {
var _type = type;
var _obj = ts_newObj(_type);
this.obj = _obj;
this.type = _type;
// Add arguments
for (var i in args) {
// Workaround
if (i === 'datablock' && ts_func(_type, "setDatablock"))
ts_func(_type, "setDatablock")(args[i]);
ts_setObjectField(_obj, i, args[i]);
}
print("Registered " + _type);
// Make it visible from TS
ts_registerObject(_obj);
};
return new Proxy(kk, blocklandJS_objhandler);
}
Not entirely working correctly as the duktape is still v1.8.0.
With the SpiderMonkey version, this has been fixed. The Duktape version should have a compatible init.js script.
According to following sites ECMAScript added getter/setter support for 5.1 and duktape supports ECMAScript 5.1. Therefore, make sure to implement this into
ts_linkClass
to make setting and getting properties a lot easier. Of course, issues may raise if the function and property have the same name, but I suggest that we ignore such thing as it is the issue of the user, not us.