Re: libseed-list Hooking into the imports system
- From: "Alan Knowles" <alan akbkhome com>
- To: "Jonatan Liljedahl" <j r liljedahl gmail com>
- Cc: libseed-list gnome org
- Subject: Re: libseed-list Hooking into the imports system
- Date: Sat, 10 Jul 2010 22:28:27 +0800
yes, that does sound good, I guess following the internal API as well makes some sense..
var o = imports.autoprop.defineObject({
getProperty : function (name) {
..
},
setProperty : function (name, value) {
..
},
deleteProperty: function(name) {
..
},
hasProperty: function(name) {
..
},
callAsFunction: function(args) {} ,
callAsConstructor: function(args) {} ,
finalize : function() { }
...
});
/* Parent Class */
NULL, /* Static Values */
NULL, /* Static Functions */
NULL,
NULL, /* Finalize */
NULL, /* Has Property */
NULL, /* Get Property */
NULL, /* Set Property */
NULL, /* Delete Property */
NULL, /* Get Property Names */
NULL, /* Call As Function */
NULL, /* Call As Constructor */
NULL, /* Has Instance */
NULL /* Convert To Type */
Regards
Alan
--- On 10/Jul/2010, Jonatan Liljedahl wrote:
> Sure, defineObject() might be more in line with the current standard,
> even though I think the methods should be named getProperty and
> setProperty or something like that. ('get' and 'set' fields in
> defineProperty() already refers to Property while in this case we define
> an Object, not a property)
>
> But, it's a little bit more work to wrap it in a function like
> defineObject() since I now simply use the existing C-side JS-class
> creation mechanism.. Do you think it would be worth it?
>
> /Jonatan
>
> Alan Knowles wrote:
> > Do you think it would be an idea to copy the nearest standard here for your 'autoprop' Object. ?
> >
> > https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/defineProperty
> >
> > var o = imports.autoprop.defineObject({
> > get : function (name) {
> >
> > },
> > set : function (name, value) {
> >
> > },
> > enumerable: function(name) {
> > ...
> > }
> >
> > });
> >
> > Regards
> > Alan
> >
> >
> >
> > --- On 02/Jul/2010, Jonatan Liljedahl wrote:
> >> Yes, this was a nice solution. See attached 'autoprop' module. (Feel
> >> free to include it in the main distro, I think it can be very useful for
> >> all sorts of special objects. Perhaps one should also add callbacks for
> >> CallAsFunction, CallAsConstructor, GetPropertyNames, etc..)
> >>
> >> With this I could simply do a custom module-importer object like this:
> >>
> >> var make_importer = function(startPath, chain) {
> >> var o = new imports.autoprop.Object;
> >>
> >> o.get_property = function(name) {
> >> if(name==="searchPath") return imports.searchPath;
> >> var searchPath = startPath || imports.searchPath;
> >>
> >> for(var i=0;i<searchPath.length;i++) {
> >> var path = searchPath[i];
> >> var file = path+'/'+name;
> >> var file_als = file+'.als';
> >>
> >> if(_module_imports[file])
> >> return _module_imports[file];
> >>
> >> if(GLib.file_test(file,GLib.FileTest.IS_DIR)) {
> >> return _module_imports[file] =
> >> make_importer([file],chain.concat(name));
> >> } else
> >> if(GLib.file_test(file_als,GLib.FileTest.IS_REGULAR)) {
> >> GLib.file_get_contents(file_als,script={});
> >> ctx = new Context;
> >> ctx.global.__script_path__ = path;
> >> ctx.eval(script.contents);
> >> return _module_imports[file]=ctx.global;
> >> }
> >> }
> >> // fall back to original seed imports
> >> for(var i=0,ns=imports;i<chain.length;i++)
> >> ns = ns[chain[i]];
> >> return ns[name] || null;
> >> }
> >>
> >> o.set_property = function(name, value) {
> >> if(name === "searchPath") {
> >> imports.searchPath = value;
> >> return true;
> >> }
> >> return false; //or true to not allow custom props to be set..
> >> }
> >>
> >> return o;
> >> }
> >>
> >> var module = make_importer(undefined, []);
> >>
> >> // then I can use 'module' instead of 'imports' and it works exactly
> >> // the same except it also handles my algoscript modules:
> >>
> >> var Gtk = module.gi.Gtk;
> >> var foo = module.mydir.mysubdirfoo;
> >>
> >> /Jonatan
> >>
> >> Jonatan Liljedahl wrote:
> >>> I don't see how this would be solved easily..
> >>>
> >>> if 'xxx' is my magic handler, then autoloader can create an object 'xxx'
> >>> that calls my handler on get_property().. so my handler would be called
> >>> with 'zzzz'. Let's say 'zzzz' is a folder, and I want xxx.zzzz.foo to
> >>> load the file foo from that folder.. Nothing I can return from a
> >>> javascript handler would allow 'foo' to be fetched unless it's already
> >>> an existing member of 'zzzz', since there's no
> >>> Object.prototype.__lookupProperty__ hook or similar.
> >>>
> >>> Maybe one could make a generic 'dynamic object' class in C, which could
> >>> be used recursively...
> >>>
> >>> auto = new imports.dynamic.Object;
> >>> auto.get_prop = function(prop) {
> >>> var x = my_lookup(prop,base);
> >>> // if x is dir, return a new dynamic Object with a handler for that
> >>> directory..
> >>> // if x is a file, parse and return namespace..
> >>> // etc...
> >>> };
> >>>
> >>> /Jonatan
> >>>
> >>> Alan Knowles wrote:
> >>>> It sounds alot like the autoload feature that was added to PHP.
> >>>>
> >>>> It was only after the feature was made available that everyone
> >>>> realized that it was a flawed design (by that time people had already
> >>>> started using it...)
> >>>>
> >>>> The partial solution was to add SPL::autoload() which does solve some
> >>>> of the problems..
> >>>>
> >>>> for seed it might be that we have something like
> >>>>
> >>>> imports.autoloader.register('xxx', function(args) {....});
> >>>> or
> >>>> imports.autoloader.register('xxx', imports.xxx.importer);
> >>>>
> >>>> ZZZ = imports.autoloader.xxx.zzzz
> >>>>
> >>>> That should give you the syntax you are after, without making it too
> >>>> confusing, along with enabling multiple handlers to be defined..
> >>>>
> >>>> autoloader could easily be implemented in a very simple module...
> >>>>
> >>>> Regards
> >>>> Alan
> >>>>
> >>>>
> >>>>
> >>>> --- On 30/Jun/2010, Jonatan Liljedahl wrote:
> >>>>> Alan Knowles wrote:
> >>>>>> My concern here is that this would make code very difficult to
> >>>>>> understand.
> >>>>>>
> >>>>>> Is there a way to implement this where it is an explicit behavior
> >>>>>> rather than an implicit,
> >>>>>> Hence, when it is being used, you know from the syntax that it may
> >>>>>> be trying to do
> >>>>> > something magical, rather than overloading the 'reasonably'
> >>>>> > predictable behavior of imports.
> >>>>>
> >>>>> I think that would be up to the developer, to use the notFoundHandler
> >>>>> in a wise way. My plan is mostly very 'reasonable', simply to add
> >>>>> support for modules written in a custom language and not having to
> >>>>> bother if a module is written in C, javascript, algoscript, or
> >>>>> imported from GIR.
> >>>>>
> >>>>> But I can see other (more or less reasonable) use cases too, creating
> >>>>> virtual namespaces under imports to integrate with other stuff, and I
> >>>>> think it would be a very elegant feature.
> >>>>>
> >>>>>> or could this not be done client side?
> >>>>>> eg.
> >>>>>>
> >>>>>> imports.smartloader.load('xxx');
> >>>>> Yes, that's almost what I do now, I have an
> >>>>> imports.algoscript.Importer class with a root instance at
> >>>>> imports.algoscript._root_importer, so that I can do:
> >>>>>
> >>>>> zoo = imports.algoscript._root_importer._import('foo.bar.zoo');
> >>>>>
> >>>>> But it means a lot of not-well-working duplication of the seed
> >>>>> imports object, since I want to use it for both normal seed imports
> >>>>> and also to handle directories the same was as seed imports does.
> >>>>> (above should work if foo is a dir, bar a file and zoo a variable in
> >>>>> that file)...
> >>>>>
> >>>>> Also it looks very ugly, so I have created special syntactic sugar in
> >>>>> algoscript to make it look like "zoo = import foo.bar.zoo".
> >>>>>
> >>>>> The very nice thing with the imports object is that the properties
> >>>>> are virtual (they are created/found on the fly), but that any "real"
> >>>>> JS object in the chain simply takes over from there. You don't need
> >>>>> to care what part is a directory, a file, or a variable in that file,
> >>>>> or a member of an object in that file, etc.. This is not possible on
> >>>>> client side, I'd have to write my own importer class in C for this,
> >>>>> more or less duplicating everything from seed-importer.c...
> >>>>>
> >>>>> But I'd really prefer to just use the existing system that's already
> >>>>> there and does it the right way: then I could just have a single
> >>>>> handler function, something like this:
> >>>>>
> >>>>> imports.__notFoundHandler__ = function(name,dir) {
> >>>>> var dirs = [dir];
> >>>>> var ns;
> >>>>> if(dir!=imports.searchPath[0])
> >>>>> dirs = dirs.concat(imports.searchPath);
> >>>>> dirs.forEach(function(d) {
> >>>>> if (d == '.' && __script_path__)
> >>>>> d = __script_path__;
> >>>>> var f = d+'/'+name+'.as';
> >>>>> if (file_exist(f)) {
> >>>>> var ctx = new algoscript.Context;
> >>>>> ctx.eval_file(f);
> >>>>> ns = ctx.global;
> >>>>> ctx.destroy();
> >>>>> }
> >>>>> });
> >>>>> return ns;
> >>>>> }
> >>>>>
> >>>>>
> >>>>>> For the toString stuff, I guess that's needed only for this patch.
> >>>>>>
> >>>>>>
> >>>>>> BTW i'll be offline tommorow till next week, unless I can get net
> >>>>>> access...
> >>>>> offline, that sounds scary... ;)
> >>>>>
> >>>>> see you later, thanks for the feedback!
> >>>>>
> >>>>> /Jonatan
> >>>>>
> >>>>>> Regards
> >>>>>> Alan
> >>>>>>
> >>>>>>
> >>>>>> --- On 30/Jun/2010, Jonatan Liljedahl wrote:
> >>>>>>> Here is a small patch that adds a feature that I'd be very happy to
> >>>>>>> see.
> >>>>>>> It allows one to hook into the imports system by defining a handler
> >>>>>>> for
> >>>>>>> when a module was not found. Example:
> >>>>>>>
> >>>>>>> imports.__notFoundHandler__ = function(name, dir) {
> >>>>>>> print("making "+name);
> >>>>>>> return {foo:123}
> >>>>>>> }
> >>>>>>> f = imports.foobar;
> >>>>>>> print(f.foo);
> >>>>>>>
> >>>>>>> running above file prints:
> >>>>>>>
> >>>>>>> making foobar
> >>>>>>> 123
> >>>>>>>
> >>>>>>> This can be used to integrate all sorts of cool stuff with the imports
> >>>>>>> object. For example, the handler can iterate over
> >>>>>>> imports.searchPath to
> >>>>>>> find n+".html" and return an object representation of the DOM tree, or
> >>>>>>> parsing a custom language (hmmmm ;)), or perhaps even connect to an
> >>>>>>> online database of modules.. x = imports.seedgems.foo; -> updates foo
> >>>>>>> from an online repository, etc...
> >>>>>>>
> >>>>>>> Currently it only passes the first path from
> >>>>>>> seed_importer_search_dirs() as the second arg, at least this works
> >>>>>>> for the case when the search is done inside a single directory, but
> >>>>>>> I guess it would be better to just send the whole path GSList by
> >>>>>>> converting it to a JS array. One could still work around it on the
> >>>>>>> script side by merging the dir arg with imports.searchPath if dir
> >>>>>>> != searchPath[0].
> >>>>>>>
> >>>>>>> BTW, this patch also adds the toString and toValue hack to
> >>>>>>> seed_importer_dir_get_property() so it doesn't call the handler
> >>>>>>> saying that "toString" module wasn't found, etc..
> >>>>>>>
> >>>>>>> /Jonatan
> >>>>>> _______________________________________________
> >>>>>> libseed-list mailing list
> >>>>>> libseed-list gnome org
> >>>>>> http://mail.gnome.org/mailman/listinfo/libseed-list
> >
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]