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 === "./normdata.js") {
 66         return;
 67     }
 68     else if (pathname === "./TestSuiteModule.js") {
 69         // special case to redirect to qt instead
 70         pathname = this.root + "/../../qt/NodeunitTest/TestSuiteModule.js";
 71     } else if (pathname === "nodeunit") {
 72         //console.log(" [ilib-qt.js] Loading nodeunit-qml.js ");
 73         pathname = this.root + "/../test/nodeunit/nodeunit-qml.js";
 74     } else if (pathname === "qmltest") {
 75         pathname = this.root + "/../test" + absolutePath;
 76         //console.log("[ilib-qt.js] Loading Test file...  "+ pathname);
 77     } else {
 78         if (parent && parent.charAt(0) !== '/') {
 79             // take care of relative parents (aren't all parents relatives? haha)
 80             parent = this.root + '/' + parent;
 81         }
 82 
 83         //console.log("this.root is " + this.root + " and pathname before was " + pathname);
 84         //console.log("require: module.filename is " + module.filename);
 85         //console.log("require: parent is " + parent);
 86 
 87         var base = parent || (module.filename && this.dirname(module.filename)) || this.root;
 88 
 89         //console.log("******** require: base is " + base);
 90 
 91         if (pathname.charAt(0) !== '/') {
 92             pathname = base + "/" + pathname;
 93         }
 94     }
 95 
 96     pathname = this.normalize(pathname);
 97     //console.log(" require: pathname after is " + pathname);
 98 
 99     if (this.cache[pathname]) {
100         //console.log("require: cache hit");
101         return this.cache[pathname];
102     }
103 
104     // don't try to load things that are currently in the process of loading
105     if (this.loading[pathname]) {
106         //console.log("require: already loading...");
107         return {};
108     }
109     //console.log("require: loading the file");
110 
111     // communicate the current dir to the included js file
112     var tmp = module.filename;
113     module.filename = pathname;
114     this.loading[pathname] = true;
115     module.require = requireClass.prototype.require.bind(r, this.dirname(pathname));
116 
117     var s = Qt.include(pathname);
118 
119     module.filename = tmp;
120     this.loading[pathname] = undefined;
121 
122     if (s.status === s.OK) {
123         module.exports.module = {
124             filename: pathname,
125             require: requireClass.prototype.require.bind(r, this.dirname(pathname))
126         };
127         this.cache[pathname] = module.exports;
128         return module.exports;
129     }
130 
131     console.log("exception was " + JSON.stringify(s.status, undefined, 4));
132     console.log("Failed loading " + pathname);
133     console.trace();
134     return undefined;
135 };
136 
137 var r = new requireClass();
138 var require = requireClass.prototype.require.bind(r, undefined);
139 
140 var QmlLoader = require("../lib/QMLLoader.js");
141 
142 var ilib = require("../lib/ilib.js");
143 
144 ilib._dyncode = true; // indicate that we are using dynamically loaded code
145 ilib._dyndata = true;
146 ilib._cacheMerged = true; // cache merged locale data for performance
147