You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Native javascript objects could be represented as userdata
This requires userdata behaviour to actually be respected (in regards to metatables and more)
A few changes I've started making to facilitate this:
diff --git a/vm/moonshine.js b/vm/moonshine.js
index 1b2fc37..94f61ca 100644
--- a/vm/moonshine.js
+++ b/vm/moonshine.js
@@ -1380,6 +1380,18 @@ shine.Closure.prototype.dispose = function (force) {
} else if (typeof b == 'string' && shine.lib.string[c]) {
result = shine.lib.string[c];
+ } else if (b.__shine) {
+ var mt, __index;
+ if ( (mt = b.__shine.metatable) && (__index = mt.getMember("__index"))) {
+ if (__index instanceof shine.Table) {
+ result = __index.getMember(c);
+ } else {
+ result = __index(b, c);
+ }
+ } else {
+ throw new shine.Error('Attempt to index a userdata value');
+ }
+
} else {
result = b[c];
}
@@ -3517,12 +3529,12 @@ var shine = shine || {};
tostring: function (e) {
var mt, mm;
- if (e !== undefined && e instanceof shine.Table && (mt = e.__shine.metatable) && (mm = mt.getMember('__tostring'))) return mm.call(mm, e);
+ if (e !== undefined && typeof e == "object" && (mt = e.__shine.metatable) && (mm = mt.getMember('__tostring'))) return mm.call(mm, e);
if (e instanceof shine.Table || e instanceof shine.Function) return e.toString();
if (typeof e == 'function') return 'function: [host code]';
- return shine.utils.coerce(e, 'string') || 'userdata';
+ return shine.utils.coerce(e, 'string');
},
And a better DOMAPI with consistent metatables
diff --git a/extensions/DOMAPI/DOMAPI.moonshine.js b/extensions/DOMAPI/DOMAPI.moonshine.js
index 1c5867b..b2304ff 100644
--- a/extensions/DOMAPI/DOMAPI.moonshine.js
+++ b/extensions/DOMAPI/DOMAPI.moonshine.js
@@ -21,127 +21,101 @@
*/
(function (shine) {
-
- function jsToLua (obj) {
- var t, mt;
-
- mt = new shine.Table({
-
+ var object_mt = new shine.Table({
__index: function (t, key) {
- var property = obj[key];
-
- // Bind methods to object and convert args and return values
- if (typeof property == 'function' || (property && property.prototype && typeof property.prototype.constructor == 'function')) { // KLUDGE: Safari reports native constructors as objects, not functions :-s
- var f = function () {
- var args = convertArguments(arguments, luaToJS),
- retval = property.apply(args.shift(), args);
-
- if (typeof retval == 'object') return jsToLua(retval);
- return [retval];
- };
-
- // Add a new method for instantiating classes
- f.new = function () {
- var args = convertArguments(arguments, luaToJS),
- argStr,
- obj,
- i, l;
-
- argStr = (l = args.length)? 'args[0]' : '';
- for (i = 1; i < l; i++) argStr += ',args[' + i + ']';
-
- obj = eval('new property(' + argStr + ')');
- return jsToLua(obj);
- };
-
- return f;
- }
-
- // Recurse down properties
- if (typeof property == 'object') return jsToLua(property);
-
- // Return primatives as is
- return property;
+ return jsToLua(t.__native[key]);
},
-
-
__newindex: function (t, key, val) {
- obj[key] = luaToJS(val);
+ t.__native[key] = luaToJS(val);
+ },
+ __tostring: function (t) {
+ console.log(t,t.__native)
+ return "userdata: " + toString(t.__native);
}
-
});
- mt.source = obj;
-
-
- t = new shine.Table();
- shine.gc.incrRef(t);
+ var function_mt = new shine.Table({
+ __call: function(t) {
+ var args = Array.prototype.slice.call(arguments,1).map(luaToJS);
+ return [jsToLua(t.__native.apply(null, args))];
+ },
+ __new: function(t) {
+ var args = Array.prototype.slice.call(arguments,1).map(luaToJS);
+ return [jsToLua(new t._constructor(args))];
+ },
+ __index: object_mt.__index,
+ __newindex: object_mt.__newindex,
+ __tostring: object_mt.__tostring
+ });
- // Return proxy table
- return shine.lib.setmetatable(t, mt);
+ function jsToLua (obj) {
+ switch (typeof obj) {
+ case 'undefined':
+ case 'number':
+ case 'boolean':
+ case 'string':
+ return obj;
+ case 'object':
+ if (obj instanceof Number ||
+ obj instanceof Boolean ||
+ obj instanceof String) {
+ return obj.valueOf();
}
+ return {
+ __shine: {
+ metatable: object_mt
+ },
+ __native: obj
+ };
+ case 'function':
+ function constructor(args) {
+ return obj.apply(this, args);
+ }
+ constructor.prototype = obj.prototype;
-
-
+ return {
+ __shine: {
+ metatable: function_mt
+ },
+ __native: obj,
+ __constructor: constructor
+ };
+ default:
+ throw "Unable to convert to js value to lua";
+ }
+ }
function luaToJS (val) {
- var mt;
-
- // Make shine.Functions invokable
+ switch (typeof val) {
+ case 'undefined':
+ case 'number':
+ case 'boolean':
+ case 'string':
+ case 'function':
+ return val;
+ case 'object':
if (val instanceof shine.Function) {
return function () {
- return jsToLua(val.apply(undefined, convertArguments(arguments, jsToLua)));
+ var args = Array.prototype.slice.call(arguments,0).map(jsToLua);
+ return jsToLua(val.apply(void 0, args));
};
+ } else if (val instanceof shine.Table) {
+ // TODO: reverse proxy
+ return shine.utils.toObject(val);
+ } else {
+ switch(val.__shine) {
+ case function_mt:
+ case object_mt:
+ return val.__native;
+ default:
+ throw "Unable to convert userdata object";
}
-
- if (val instanceof shine.Table) {
- // If object has been wrapped by jsToLua(), use original object instead
- if ((mt = shine.lib.getmetatable(val)) && mt.source) return mt.source;
-
- // Else iterate over table
- var isArr = shine.lib.table.getn(val) > 0,
- result = shine.gc['create' + (isArr? 'Array' : 'Object')](),
- numValues = val.__shine.numValues,
- i,
- l = numValues.length;
-
- for (i = 1; i < l; i++) {
- result[i - 1] = ((numValues[i] || shine.EMPTY_OBJ) instanceof shine.Table)? luaToJS(numValues[i]) : numValues[i];
}
-
- for (i in val) {
- if (val.hasOwnProperty(i) && !(i in shine.Table.prototype) && i !== '__shine') {
- result[i] = ((val[i] || shine.EMPTY_OBJ) instanceof shine.Table)? luaToJS(val[i]) : val[i];
+ default:
+ throw "How did this get in the lua vm?"
}
}
- return result;
- }
-
-
- // Convert tables to objects
- if (typeof val == 'object') return shine.utils.toObject(val);
-
- // return primatives as is
- return val;
- }
-
-
-
-
- function convertArguments (arguments, translateFunc) {
- var args = [], i, l;
-
- for (i = 0, l = arguments.length; i < l; i++) {
- args.push(translateFunc(arguments[i]));
- }
-
- return args;
- };
-
-
-
-
// Create wrapped window API
shine.DOMAPI = { window: jsToLua(window) };
The text was updated successfully, but these errors were encountered:
Native javascript objects could be represented as userdata
This requires userdata behaviour to actually be respected (in regards to metatables and more)
A few changes I've started making to facilitate this:
And a better DOMAPI with consistent metatables
The text was updated successfully, but these errors were encountered: