1 /*
  2  * ilib-qt.js - glue code for qt apps to load local ilib code and data
  3  *
  4  * Copyright © 2015, JEDLSoft
  5  *
  6  * Licensed under the Apache License, Version 2.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at
  9  *
 10  *     http://www.apache.org/licenses/LICENSE-2.0
 11  *
 12  * Unless required by applicable law or agreed to in writing, software
 13  * distributed under the License is distributed on an "AS IS" BASIS,
 14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  *
 16  * See the License for the specific language governing permissions and
 17  * limitations under the License.
 18  */
 19 
 20 var module = {
 21     exports: {},
 22     filename:null
 23 };
 24 
 25 var requireClass = function() {
 26     this.cache = {};
 27     this.loading = {};
 28     this.updateRequire = /require\(("[^/][^"+]*")\)/g;
 29 
 30     this.root = Qt.resolvedUrl(".").toString();
 31     if (this.root.substring(0,7) === "file://") {
 32         this.root = this.root.substring(7);
 33     }
 34     if (this.root[this.root.length-1] === '/') {
 35         this.root = this.normalize(this.root.substring(0,this.root.length-1));
 36     }
 37 };
 38 
 39 requireClass.prototype.dirname = function(pathname) {
 40     pathname = pathname.replace("\\", "/");
 41     var i = pathname.lastIndexOf("/");
 42     return i !== -1 ? pathname.substring(0,i) : pathname;
 43 };
 44 
 45 requireClass.prototype.normalize = function(pathname) {
 46     if (pathname) {
 47         var previousLen;
 48         pathname = pathname.replace(/\\/g, "/");
 49         do {
 50             previousLen = pathname.length;
 51             pathname = pathname.replace(/\/\//g, "/");
 52             pathname = pathname.replace(/\/[^/]*[^\./]\/\.\./g, "/.");
 53             pathname = pathname.replace(/\/\.\//g, "/");
 54             pathname = pathname.replace(/^\.\//, "");
 55             pathname = pathname.replace(/\/\.$/, "/");
 56             if (pathname.length > 1) pathname = pathname.replace(/\/$/, "");
 57             if (pathname.length === 0) pathname = '.';
 58         } while (pathname.length < previousLen);
 59     }
 60     return pathname;
 61 };
 62 
 63 requireClass.prototype.require = function(parent, pathname, absolutePath) {
 64     //console.log("------------------------\nrequire: called with " + pathname);
 65     if (pathname === "./TestSuiteModule.js") {
 66         // special case to redirect to qt instead
 67         pathname = this.root + "/../../qt/NodeunitTest/TestSuiteModule.js";
 68     } else if (pathname === "nodeunit") {
 69         //console.log(" [ilib-qt.js] Loading nodeunit-qml.js ");
 70         pathname = this.root + "/../test/nodeunit/nodeunit-qml.js";
 71     } else if (pathname === "qmltest") {
 72         pathname = this.root + "/../test" + absolutePath;
 73         //console.log("[ilib-qt.js] Loading Test file...  "+ pathname);
 74     } else {
 75 
 76         if (parent && parent.charAt(0) !== '/') {
 77             // take care of relative parents (aren't all parents relatives? haha)
 78             parent = this.root + '/' + parent;
 79         }
 80 
 81         //console.log("this.root is " + this.root + " and pathname before was " + pathname);
 82         //console.log("require: module.filename is " + module.filename);
 83         //console.log("require: parent is " + parent);
 84 
 85         var base = parent || (module.filename && this.dirname(module.filename)) || this.root;
 86 
 87         //console.log("require: base is " + base);
 88 
 89         if (pathname.charAt(0) !== '/') {
 90             pathname = base + "/" + pathname;
 91         }
 92     }
 93 
 94     pathname = this.normalize(pathname);
 95     //console.log(" require: pathname after is " + pathname);
 96 
 97     if (this.cache[pathname]) {
 98         //console.log("require: cache hit");
 99         return this.cache[pathname];
100     }
101 
102     // don't try to load things that are currently in the process of loading
103     if (this.loading[pathname]) {
104         //console.log("require: already loading...");
105         return {};
106     }
107     //console.log("require: loading the file");
108 
109     // communicate the current dir to the included js file
110     var tmp = module.filename;
111     module.filename = pathname;
112     this.loading[pathname] = true;
113     module.require = requireClass.prototype.require.bind(r, this.dirname(pathname));
114 
115     var s = Qt.include(pathname);
116 
117     module.filename = tmp;
118     this.loading[pathname] = undefined;
119 
120     if (s.status === s.OK) {
121         module.exports.module = {
122             filename: pathname,
123             require: requireClass.prototype.require.bind(r, this.dirname(pathname))
124         };
125         this.cache[pathname] = module.exports;
126         return module.exports;
127     }
128 
129     console.log("exception was " + JSON.stringify(s.status, undefined, 4));
130     console.log("Failed loading " + pathname);
131     console.trace();
132     return undefined;
133 };
134 
135 var r = new requireClass();
136 var require = requireClass.prototype.require.bind(r, undefined);
137 
138 var QmlLoader = require("../lib/QMLLoader.js");
139 
140 var ilib = require("../lib/ilib.js");
141 
142 ilib._dyncode = true; // indicate that we are using dynamically loaded code
143 ilib._dyndata = true;
144