read_browser_object: support coroutine functions
[conkeror/arlinius.git] / components / application.js
blobf17f0932cf00c9e5e3f65dc3b193c5b9a8259f40
1 /**
2  * (C) Copyright 2007 John J. Foerch
3  * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
4  *
5  * Use, modification, and distribution are subject to the terms specified in the
6  * COPYING file.
7 **/
9 const Cc = Components.classes;
10 const Ci = Components.interfaces;
11 const Cr = Components.results;
12 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
14 function application () {
15     Components.utils.import("resource://gre/modules/XPCOMUtils.jsm", this);
17     this.wrappedJSObject = this;
18     this.conkeror = this;
20     this.loaded_modules = [];
21     this.loading_modules = [];
22     this.module_after_load_functions = new Object();
23     this.pending_loads = [];
24     this.load_paths = [this.module_uri_prefix];
26     try {
27         this.require("conkeror.js");
28     } catch (e) {
29         this.dumpln("Error initializing.");
30         this.dump_error(e);
31     }
33 application.prototype = {
34     Cc: Cc,
35     Ci: Ci,
36     Cr: Cr,
37     /* Note: resource://app currently doesn't result in xpcnativewrappers=yes */
38     module_uri_prefix: "chrome://conkeror/content/",
39     subscript_loader: Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader),
40     preferences: Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService),
41     dump_error: function (e) {
42         if (e instanceof Error) {
43             this.dumpln(e.name + ": " + e.message);
44             this.dumpln(e.fileName + ":" + e.lineNumber);
45             dump(e.stack);
46         } else if (e instanceof Ci.nsIException) {
47             this.dumpln(e.name + ": " + e.message);
48             var stack_frame = e.location;
49             while (stack_frame) {
50                 this.dumpln(stack_frame.name + "()@" + stack_frame.filename + ":" + stack_frame.lineNumber);
51                 stack_frame = stack_frame.caller;
52             }
53         } else {
54             this.dumpln("Error: " + e);
55         }
56     },
57     loaded: function (module) {
58         return (this.loaded_modules.indexOf(module) != -1);
59     },
60     provide: function(module) {
61         if (this.loaded_modules.indexOf(module) == -1)
62             this.loaded_modules.push(module);
63     },
64     skip_module_load : {},
65     load_module: function(module_name) {
66         if (this.loading_modules.indexOf(module_name) != -1)
67             throw new Error("Circular module dependency detected: "
68                             + this.loading_modules.join(" -> ") + " -> " + module_name);
69         this.loading_modules.push(module_name);
70         try {
71             let j = 0;
72             while (true) {
73                 if (j >= this.load_paths.length)
74                     throw new Error("Module not found: " + module_name);
75                 try {
76                     this.subscript_loader.loadSubScript(this.load_paths[j] + module_name,
77                                                         this);
78                     this.provide(module_name);
79                     let funcs;
80                     if ((funcs = this.module_after_load_functions[module_name]) != null)
81                     {
82                         for (let i = 0; i < funcs.length; ++i)
83                             funcs[i]();
84                         delete this.module_after_load_functions[module_name];
85                     }
86                 }
87                 catch (e if e == this.skip_module_load) {}
88                 catch (e) {
89                     if (!(e instanceof Error) && !(e instanceof Ci.nsIException) &&
90                         (String(e) == "ContentLength not available (not a local URL?)" ||
91                          String(e) == "Error creating channel (invalid URL scheme?)" ||
92                          String(e) == "Error opening input stream (invalid filename?)")) {
93                         ++j;
94                         continue;
95                     }
96                     throw e;
97                 }
98                 break;
99             }
100         }
101         finally {
102             this.loading_modules.pop();
103         }
105         if (this.loading_modules.length == 0)
106         {
107             while (this.pending_loads.length > 0)
108             {
109                 this.require(this.pending_loads.pop());
110             }
111         }
112     },
113     require: function (module) {
114         if (!this.loaded(module))
115             this.load_module(module);
116     },
117     require_later: function (module) {
118         if (!this.loaded(module)
119             && this.pending_loads.indexOf(module) == -1)
120             this.pending_loads.push(module);
121     },
122     call_after_load: function (module, func) {
123         if (this.loaded(module))
124             func();
125         else
126         {
127             var funcs;
128             if (!(funcs = this.module_after_load_functions[module]))
129                 funcs = this.module_after_load_functions[module] = [];
130             funcs.push(func);
131         }
132     },
133     dumpln: function (line) {
134         dump(line + "\n");
135     },
137     get version () {
138         var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"]
139             .getService(Ci.nsIURLFormatter);
140         return formatter.formatURL("%VERSION%");
141     },
143     /* nsISupports */
144     QueryInterface: XPCOMUtils.generateQI([]),
146     /* XPCOM registration */
147     classDescription: "Conkeror global object",
148     classID: Components.ID("{72a7eea7-a894-47ec-93a9-a7bc172cf1ac}"),
149     contractID: "@conkeror.mozdev.org/application;1"
152 function NSGetModule (compMgr, fileSpec) {
153     return XPCOMUtils.generateModule([application]);