Update Iot.js
[platform/upstream/iotjs.git] / src / js / module.js
1 /* Copyright 2015-present Samsung Electronics Co., Ltd. and other contributors
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16
17 var Native = require('native');
18 var fs = Native.require('fs');
19
20 function iotjs_module_t(id, parent) {
21   this.id = id;
22   this.exports = {};
23   this.filename = null;
24   this.parent = parent;
25 };
26
27 module.exports = iotjs_module_t;
28
29
30 iotjs_module_t.cache = {};
31 iotjs_module_t.wrapper = Native.wrapper;
32 iotjs_module_t.wrap = Native.wrap;
33
34
35 var cwd;
36 try { cwd = process.cwd(); } catch (e) { }
37
38 var moduledirs = [""]
39 if(cwd){
40   moduledirs.push(cwd + "/");
41   moduledirs.push(cwd + "/node_modules/");
42 }
43 if(process.env.HOME){
44   moduledirs.push(process.env.HOME + "/node_modules/");
45 }
46 if(process.env.NODE_PATH){
47   moduledirs.push(process.env.NODE_PATH + "/node_modules/")
48 }
49
50 iotjs_module_t.concatdir = function(a, b){
51   var rlist = [];
52   for(var i = 0; i< a.length ; i++) {
53     rlist.push(a[i]);
54   }
55
56   for(var i = 0; i< b.length ; i++) {
57     rlist.push(b[i]);
58   }
59
60   return rlist;
61 };
62
63
64 iotjs_module_t.resolveDirectories = function(id, parent) {
65   var dirs = moduledirs;
66   if(parent) {
67     if(!parent.dirs){
68       parent.dirs = [];
69     }
70     dirs = iotjs_module_t.concatdir(parent.dirs, dirs);
71   }
72   return dirs;
73 };
74
75
76 iotjs_module_t.resolveFilepath = function(id, directories) {
77
78   for(var i = 0; i<directories.length ; i++) {
79     var dir = directories[i];
80     // 1. 'id'
81     var filepath = iotjs_module_t.tryPath(dir+id);
82
83     if(filepath){
84       return filepath;
85     }
86
87     // 2. 'id.js'
88     filepath = iotjs_module_t.tryPath(dir+id+'.js');
89
90     if(filepath){
91       return filepath;
92     }
93
94     // 3. package path /node_modules/id
95     var packagepath = dir + id;
96     var jsonpath = packagepath + "/package.json";
97     filepath = iotjs_module_t.tryPath(jsonpath);
98     if(filepath){
99       var pkgSrc = process.readSource(jsonpath);
100       var pkgMainFile = JSON.parse(pkgSrc).main;
101       filepath = iotjs_module_t.tryPath(packagepath + "/" + pkgMainFile);
102       if(filepath){
103         return filepath;
104       }
105       // index.js
106       filepath = iotjs_module_t.tryPath(packagepath + "/" + "index.js");
107       if(filepath){
108         return filepath;
109       }
110     }
111
112   }
113
114   return false;
115 };
116
117
118 iotjs_module_t.resolveModPath = function(id, parent) {
119
120   // 0. resolve Directory for lookup
121   var directories = iotjs_module_t.resolveDirectories(id, parent);
122
123   var filepath = iotjs_module_t.resolveFilepath(id, directories);
124
125   if(filepath){
126     return filepath;
127   }
128
129   return false;
130 };
131
132
133 iotjs_module_t.tryPath = function(path) {
134   var stats = iotjs_module_t.statPath(path);
135   if(stats && !stats.isDirectory()) {
136     return path;
137   }
138   else {
139     return false;
140   }
141 };
142
143
144 iotjs_module_t.statPath = function(path) {
145   try {
146     return fs.statSync(path);
147   } catch (ex) {}
148   return false;
149 };
150
151
152 iotjs_module_t.load = function(id, parent, isMain) {
153   if(process.native_sources[id]){
154     return Native.require(id);
155   }
156   var module = new iotjs_module_t(id, parent);
157
158   var modPath = iotjs_module_t.resolveModPath(module.id, module.parent);
159
160   var cachedModule = iotjs_module_t.cache[modPath];
161   if (cachedModule) {
162     return cachedModule.exports;
163   }
164
165   if (modPath) {
166     module.filename = modPath;
167     module.SetModuleDirs(modPath);
168     module.compile();
169   }
170   else {
171     throw new Error('No module found');
172   }
173
174   iotjs_module_t.cache[modPath] = module;
175
176   return module.exports;
177 };
178
179
180 iotjs_module_t.prototype.compile = function() {
181   var self = this;
182   var requireForThis = function(path) {
183       return self.require(path);
184   };
185
186   var source = process.readSource(self.filename);
187   var fn = process.compile(source);
188   fn.call(self.exports, self.exports, requireForThis, self);
189 };
190
191
192 iotjs_module_t.runMain = function(){
193   iotjs_module_t.load(process.argv[1], null, true);
194   process._onNextTick();
195 };
196
197
198
199 iotjs_module_t.prototype.SetModuleDirs = function(filepath)
200 {
201   // At next require, search module from parent's directory
202   var dir = "";
203   var i;
204   for(i = filepath.length-1;i>=0 ; i--) {
205     if(filepath[i] == '/'){
206       break;
207     }
208   }
209
210   // save filepath[0] to filepath[i]
211   // e.g. /home/foo/main.js ->  /home/foo/
212   for(;i>=0 ; i--) {
213     dir = filepath[i] + dir;
214   }
215   this.dirs = [dir];
216 };
217
218
219 iotjs_module_t.prototype.require = function(id) {
220   return iotjs_module_t.load(id, this);
221 };