Re: libseed-list Hooking into the imports system



imports.DynamicObject.define(....)


could not think of anything else of the top of my head.. 

Regards
Alan

 --- On 11/Jul/2010, Jonatan Liljedahl wrote: 
> Yes, that makes sense. But perhaps the module should be named something 
> else than autoprop. Any ideas? Perhaps it should go into the Seed module 
> (if you guys want to include it) or some other module for similar future 
> stuff?
> 
> /Jonatan
> 
> Alan Knowles wrote:
> > 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]