Firefox extension javascript module: what happens to unexported symbols? - firefox-addon

I'm just starting to write my first FF extension using javascript modules (rather than trying an XPCOM component) but I'm fuzzy on what happens when a jsm is loaded.
Q: Does the file scope act as a closure for non-exported symbols, or are unreferenced symbols simply garbage collected?
For an example, could/should a module be written as follows?
//modules/myModule.js
var EXPORTED_SYMBOLS = [ 'foo', 'bar' ];
var data;
function foo(){
return data;
}
function bar(newData){
data = newData;
}
importing it somewhere else as:
var aNS = {};
Components.utils.import("resource://myext/myModule.js", aNS);
aNS.bar('it works?');
alert(aNS.foo()); //alert: 'it works?'
Even if a module can be written this way, is there a good reason not to?

It acts in closure manner, but only if you're referencing it somewhere. In my extension I have something like:
var EXPORTED_SYMBOLS = ['foo'];
let cacheService = Components.classes["#mozilla.org/network/cache-service;1"]
.getService(Components.interfaces.nsICacheService);
let foo = {
svc : cacheService,
dosomethingwithit : function(){this.svc.somemethod();}
}
So because it is referenced by foo.svc my cacheService is well and alive. If I wasn't referencing it anywhere it would've been garbage collected - which is to no surprise since if it's not used who cares.
But now thinking a bit more about it, I'm just wandering why I did it this way. Doesn't really makes much sense, or difference. I could've had something like:
var EXPORTED_SYMBOLS = ['foo'];
function something(){
this.svc = Components.classes["#mozilla.org/network/cache-service;1"]
.getService(Components.interfaces.nsICacheService);
}
let foo = new something();
I think I just liked the looks of the first approach more.

Related

std.json.parse and memory management

I have the following zig code (simplified):
const allocator = ...;
const Entry = struct {
name: []u8,
};
fn list() ![]u8 {
var entries = try std.json.parse([]Entry, ...);
defer std.json.parseFree([]Entry, entries, ...);
return entries[0];
}
fn main() !void {
const e = try list();
...
}
Everything is (de)allocated with allocator.
I'd like to return entries[0] and recycle everything else. The problem is that parseFree here recycles everything including entries[0] so I can't seemingly use this function.
So what's the most effective way to do that without copying? What if Entry is a big structure and I want to return just one its field, say Entry.name (and, again, recycle everything else)?
The quickest way of achieving what you want is to not use parseFree but instead:
const first = entries[0].name;
for (entries[1..entries.len]) |e| alloc.free(e.name); // frees individual strings
alloc.free(entries); // frees the array of structs
return Entry { .name = first };
This is fairly straightforward but relies on understanding how memory is allocated by std.json and the implementation might one day want to allocate things differently, causing the code above to break.
Because of that, my recommendation would be to just copy the string and only resort to this type of extra complexity once you have demonstrated that avoiding that copy brings perceivable benefits.

Scoping classes created in Lua using Luabind

I am aware that Lua classes can be created using the OO system that Luabind exposes to Lua:
http://www.rasterbar.com/products/luabind/docs.html#defining-classes-in-lua
class 'lua_testclass'
function lua_testclass:__init(name)
self.name = name
end
function lua_testclass:print()
print(self.name)
end
a = lua_testclass('example')
a:print()
However I am unable to figure out how to scope the class within another namespace so I can do the following:
a = MyScope.lua_testclass('example')
a:print()
Anyone has a idea. I do not want my classes to pollute the global namespace in Lua.
Luabind's class function will always pollute the global table. However, you can clean up after it:
function newclass(name)
oldglobal = _G[name]
class(name)
cls = _G[name]
_G[name] = oldglobal
return cls
end
Then you would use it like this:
MyScope.lua_testclass = newclass 'lua_testclass'
Analogous to local mod = require 'mod' you have to spell the name of the class twice, but you could easily build another function on top of this that could be used like setclass(MyScope, 'lua_testclass'), automatically putting the class into MyScope:
function setclass(scope, name) scope[name] = newclass(name) end
Disclaimer: All this code is entirely untested.
I did mine a little differently, but it's generally the same concept. Mine doesn't create the class, but rather just moves it. I also implemented it on the C++ side.
To implement what I did in Lua, you would write:
function moveClass(name)
oldGlobal = _G[name]
_G[name] = nil
return oldGlobal
end
To implement it in C++, you would write:
luabind::module(lua) [
luabind::def("moveClass", +[](lua_State * lua, std::string name) {
// In the case the class does not exist, this will just
// remove nil and return nil. That essentially does nothing.
luabind::object oldGlobal = luabind::globals(lua)[name];
luabind::globals(lua)[name] = luabind::nil;
return oldGlobal;
})
];
So now if you were to use that to move a class you created, you would do this:
class 'MyClass'
myTable = {}
myTable.MyClass = moveClass 'MyClass'
As an extra note, if you want the moveClass function to give an error in the case that the class you are trying to move does not exist, use luabind::type(oldGlobal) == LUA_TNIL to determine if the class existed or not.
Example:
luabind::module(lua) [
luabind::def("moveClass", +[](lua_State * lua, std::string name) {
luabind::object oldGlobal = luabind::globals(lua)[name];
if (luabind::type(oldGlobal) == LUA_TNIL) {
throw std::runtime_error("Class does not exist.");
}
luabind::globals(lua)[name] = luabind::nil;
return oldGlobal;
})
];

Accessing <objc/runtime.h> from Cycript

I wan't to be able to use associated objects and ISA swizzle, but I can't figure out how to import objc/runtime.h for use with Cycript. I have tried in both the console and in .js files but no luck.
Ideally I'd like to figure out how to include frameworks as well.
It seems like a subset of runtime.h is included by default in the Cycript environment. For example, class_copyMethodList and objc_getClass work without any added effort.
var count = new new Type(#encode(int));
var methods = class_copyMethodList(objc_getClass("NSObject"), count);
However objc_setAssociatedObject is not referenced:
objc_getAssociatedObject(someVar, "asdf")
#ReferenceError: Can't find variable: objc_getAssociatedObject
After a lot of searching, I realized the answer was right under my nose. limneos's weak_classdump uses the runtime to do it's dump and Cycript's tutorial shows how to grab C functions.
The solution I ended up with is this:
function setAssociatedObject(someObject, someValue, constVoidPointer) {
SetAssociatedObject = #encode(void(id, const void*, id, unsigned long))(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"))
SetAssociatedObject(someObject, constVoidPointer, someValue, 1)
}
function getAssociatedObject(someObject, constVoidPointer) {
GetAssociatedObject = #encode(id(id, const void*))(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"))
return GetAssociatedObject(someObject, constVoidPointer)
}
It is used like this:
# create void pointer (probably should be a global variable for later retrieval)
voidPtr = new new Type(#encode(const void))
someVar = [[NSObject alloc] init]
setAssociatedObject(someVar, #[#"hello", #"world"], voidPtr)
getAssociatedObject(someVar, voidPtr)
# spits out #["Hello", "World"]

Using array notation instead of NSM on functions deeper then js.context.X

Can all objects after js.context be accessed with array notation from Dart? For example, I'd like to convert the following to use array notation:
var request = js.context.gapi.client.request(js.map(requestData));
Will the following array notation work?
var request = js.context['gapi']['client']['request'](js.map(requestData));
Also, should the following be done if trying to access JavaScript builtin methods?
js.context['JSON']['stringify'](jsonResp);
TL;DR : Starting from r24278 use array notation for properties and noSuchMethod for methods.
Using js.context['gapi']['client'] gives the same result as js.context.gapi.client. The main advantage of Array notation is that it avoids noSuchMethod. Until recently it was the only way to work around an issue in dart2js where minified does not work with noSuchMethod. This issue is fixed, and minification should work with Dart-JS interop.
I did a little benchmark some times ago :
For attribute access : array notation is around 10% faster than noSuchMethod. ( js.context.x vs. js.context['x'] )
For method access : array notation is around 50% slower than noSuchMethod. ( js.context.f() vs. js.context['f']() )
This last result is explained by 2 communications between JS and Dart for js.context['f'](). One to retrieve the function reference ( js.context['f'] ) and an other to call this function.
Last concern, using noSuchMethod can increase your dart2js result size (but not so much where I had tested it).
This works for me:
var hug = new js.Proxy(context['Hug']);
var hugDatabase = new js.Proxy(context['HugDatabase']);
hugDatabase['addHug'](hug);
print(hugDatabase['hugs']['length']);
Which interacts with this JavaScript:
function Hug(strength) {
this.strength = strength;
}
Hug.prototype.embrace = function(length) {
return 'Thanks, that was a good hug for ' + length + ' minutes!';
}
Hug.prototype.patBack = function(onDone) {
onDone('All done.');
}
function HugDatabase() {
this.hugs = [];
}
HugDatabase.prototype.addHug = function(hug) {
this.hugs.push(hug);
}
The full example is here: https://github.com/sethladd/dart-example-js-interop/blob/master/web/dart_js_interop_example.dart

Read lua interface

In lua, is there any way to read an interface file to extract name/methods/args?
I have an .idl file like this:
interface
{
name = myInterface,
methods = {
testing = {
resulttype = "double",
args = {{direction = "in",
type = "double"},
}
}
}
This is equal to the code bellow (easier to read):
interface myInterface {
double testing (in double a);
};
I can read file, load as string and parse with gmatch for example to extract information, but is there any easy mode to parse this info?
At the end i want something (a table for example) with the interface name, their methods, result types and args. Just to know the interface that i`m working.
Lua has several facilities to interpret chunks of code. Namely, dofile, loadfile and loadstring. Luckily, your input file is almost valid Lua code (assuming those braces were matched). The only thing that is problematic is interface {.
All of the above functions effectively create a function object with a file's or a string's contents as their code. dofile immediately executes that function, while the others return a function, which you can invoke whenever you like. Therefore, if you're free to change the files, replace interface in the first line with return. Then you can do:
local interface = dofile("input.idl")
And interface will be a nice table, just as you have specified it in the file. If you cannot change those files to your liking, you will have to load the file into the string, perform some string manipulation (specifically, replace the first interface with return) and then use loadstring instead:
io.input("input.idl")
local input = io.read("*all")
input = string.gsub(input, "^interface", "return") -- ^ marks beginning of string
local f = loadstring(input)
local interface = f()
In both cases this is what you will get:
> require"pl.pretty".dump(interface)
{
name = "myInterface",
methods = {
testing = {
args = {
{
type = "double",
direction = "in"
}
},
resulttype = "double"
}
}
}
> print(interface.methods.testing.args[1].type)
double
EDIT:
I just realised, in your example input myInterface is not enclosed in " and therefore not a proper string. Is that also a mistake in your input file or is that what your files actually look like? In the latter case, you would need to change that as well. Lua is not going to complain if it's a name it doesn't know, but you also won't get the field in that case.

Resources