1 /*! 2 * 3 * JavaLikeScript 4 * 5 */ 6 7 // Add default option variable 8 if (typeof jlsOptions == 'undefined') { 9 jlsOptions = {}; 10 } 11 12 // Native namespace 13 var _native = {}; 14 15 /* 16 * Library boot 17 */ 18 _native.boot = {}; 19 _native.boot.emptyFunction = function() {}; 20 _native.boot.unsupportedFunction = function() { 21 throw 'Unsupported native operation'; 22 }; 23 _native.boot.unsupportedClass = function() { 24 throw 'Unsupported native class'; 25 }; 26 _native.boot.log = _native.boot.emptyFunction; 27 if ((typeof console != 'undefined') && ('log' in console)) { 28 _native.boot.log = console.log; 29 } 30 // Find the default script path 31 (function() { 32 var bootstrap = 'bootstrap.js'; 33 var path = '.'; // default 34 var scriptTags = document.getElementsByTagName('script'); 35 for ( var i = 0; i < scriptTags.length; i++) { 36 var src = scriptTags[i].getAttribute('src'); 37 if (!src) { 38 continue; 39 } 40 var i = src.lastIndexOf('/' + bootstrap); 41 if ((i >= 0) && (i == src.length - bootstrap.length - 1)) { 42 path = src.substring(0, src.length - bootstrap.length - 1); 43 break; 44 } else if (src == bootstrap) { 45 path = '.'; 46 break; 47 } 48 } 49 _native.boot.defaultScriptPath = path; 50 })(); 51 52 53 _native.boot.httpRequest = function(url, options) { 54 this._url = url; 55 this._options = { 56 method : 'post', 57 asynchronous : true, 58 contentType : 'application/x-www-form-urlencoded', 59 encoding : 'UTF-8', 60 parameters : '', 61 user : null, 62 password : null, 63 onException : _native.boot.emptyFunction, 64 onFailure : _native.boot.emptyFunction, 65 onSuccess : _native.boot.emptyFunction 66 }; 67 if (options) { 68 for (var key in options) { 69 this._options[key] = options[key]; 70 } 71 } 72 this._xhr = _native.boot.httpRequest.newXHR(); 73 }; 74 _native.boot.httpRequest.newXHR = function() { 75 try { 76 return new XMLHttpRequest() 77 } 78 catch (e) { 79 try { 80 return new ActiveXObject('Msxml2.XMLHTTP') 81 } 82 catch (e) { 83 try { 84 return new ActiveXObject('Microsoft.XMLHTTP') 85 } 86 catch (e) { 87 return false; 88 } 89 } 90 } 91 }; 92 _native.boot.httpRequest.prototype.getXHR = function() { 93 return this._xhr; 94 }; 95 _native.boot.httpRequest.prototype.getStatus = function() { 96 return this._xhr.status || 0; 97 }; 98 _native.boot.httpRequest.prototype.onStateChange = function() { 99 var readyState = this._xhr.readyState; 100 _native.core.log(0, '_native.boot.xmlHttpRequest.onStateChange(' + readyState + ')'); 101 if (readyState != 4) { // Not completed 102 return; 103 } 104 var status = this.getStatus(); 105 try { 106 if (((status >= 200) && (status < 300)) || (status == 304)) { 107 this._options.onSuccess.call(this); 108 } else { 109 this._options.onFailure.call(this); 110 } 111 } 112 catch (e) { 113 this._options.onException.call(this, e); 114 } 115 finally { 116 this._xhr.onreadystatechange = _native.boot.emptyFunction; 117 } 118 }; 119 _native.boot.httpRequest.prototype.send = function() { 120 _native.core.log(0, '_native.boot.xmlHttpRequest.send(), ' + this._options.method + ': "' + this._url + '"'); 121 if ((this._options.user != null) && (this._options.password != null)) { 122 this._xhr.open(this._options.method.toUpperCase(), this._url, 123 this._options.asynchronous, this._options.user, 124 this._options.password); 125 } else { 126 this._xhr.open(this._options.method.toUpperCase(), this._url, 127 this._options.asynchronous); 128 } 129 var self = this; 130 this._xhr.onreadystatechange = function () { 131 _native.core.log(0, 'onreadystatechange'); 132 self.onStateChange(); 133 }; 134 var headers = { 135 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 136 }; 137 if (this._options.method == 'post') { 138 headers['Content-type'] = this._options.contentType + (this._options.encoding ? '; charset=' + this._options.encoding : ''); 139 } 140 for (var name in headers) { 141 this._xhr.setRequestHeader(name, headers[name]); 142 } 143 var params = (typeof this._options.parameters == 'string') ? this._options.parameters : Object.toQueryString(this._options.parameters); 144 var body = (this._options.method == 'post') ? (this._options.postBody || params) : null; 145 this._xhr.send(body); 146 /* Force Firefox to handle ready state 4 for synchronous requests */ 147 if (!this._options.asynchronous && this._xhr.overrideMimeType) { 148 this.onStateChange(); 149 } 150 return this; 151 }; 152 153 154 /* 155 * Library core From "jls generateNativeLibraryAPI.js" 156 */ 157 _native.core = {}; 158 _native.core.log = function(level, msg) { 159 _native.boot.log(msg); 160 }; 161 _native.core.logLevel = _native.boot.emptyFunction; 162 _native.core.exceptionHandler = _native.boot.emptyFunction; 163 _native.core.sleep = _native.boot.emptyFunction; 164 _native.core._scriptPath = []; 165 _native.core.getResourceAsString = function(path) { 166 _native.core.log(0, '_native.core.getResourceAsString("' + path + '")'); 167 var text = null; 168 for (var i = 0; i < _native.core._scriptPath.length; i++) { 169 var url = _native.core._scriptPath[i] + '/' + path; 170 _native.core.log(0, 'try url "' + url + '"'); 171 var exception = null; 172 var status = 0; 173 new _native.boot.httpRequest(url, { 174 method :'get', 175 asynchronous :false, 176 onException : function(e) { 177 exception = e; 178 }, 179 onFailure : function() { 180 status = this.getStatus(); 181 }, 182 onSuccess : function() { 183 text = this.getXHR().responseText; 184 } 185 }).send(); 186 if (exception != null) { 187 throw exception; 188 } else if (status == 0) { 189 break; 190 } else if (status != 404) { 191 throw 'Unsupported status ' + status + ' for script path "' + _native.core._scriptPath[i] + '"'; 192 } 193 } 194 if (text == null) { 195 throw 'Script not found "' + path + '"'; 196 } 197 return text; 198 }; 199 _native.core.getResourceAsByteArray = _native.boot.emptyFunction; 200 _native.core.evalScript = function(path) { 201 _native.core.log(0, '_native.core.evalScript("' + path + '")'); 202 eval(_native.core.getResourceAsString(path)); 203 }; 204 _native.core.loadLibrary = _native.boot.unsupportedFunction; 205 _native.core.visitPaths = _native.boot.emptyFunction; 206 _native.core.gc = _native.boot.unsupportedFunction; 207 _native.core.dumpHead = _native.boot.unsupportedFunction; 208 _native.core.exit = _native.boot.unsupportedFunction; 209 _native.core.halt = _native.boot.unsupportedFunction; 210 _native.core.system = _native.boot.unsupportedFunction; 211 _native.core.signal = _native.boot.unsupportedFunction; 212 _native.core.raise = _native.boot.unsupportedFunction; 213 _native.core.getSignalCounters = _native.boot.unsupportedFunction; 214 _native.core.registerSignalMonitor = _native.boot.unsupportedFunction; 215 _native.core.handleSignal = _native.boot.unsupportedFunction; 216 _native.core.getEnv = _native.boot.unsupportedFunction; 217 _native.core.boot = _native.boot.unsupportedFunction; 218 _native.core.addPath = function(path) { 219 // Check for duplicate 220 var i = _native.core._scriptPath.length; 221 while (--i >= 0) { 222 if (_native.core._scriptPath[i] == path) { 223 break; 224 } 225 } 226 if (i < 0) { 227 _native.core._scriptPath.push(path); 228 } 229 }; 230 _native.core.arguments = null; 231 _native.core.properties = { // From "jls systemProperties.js json" 232 'cpu.endian' : 'little', 233 'cpu.pointer.size' : '4', 234 'file.encoding' : 'UTF-8', 235 'file.separator' : '/', 236 'javascript.engine' : '?', 237 'javascript.version' : '180', 238 'jls.bootstrap.filename' : 'bootstrap.js', 239 'jls.extension.path' : '', 240 'jls.home' : '.', 241 'jls.library.path' : '.', 242 'jls.logger.logLevel' : 'warn', 243 'jls.programname' : 'jls', 244 'jls.script.path' : _native.boot.defaultScriptPath, 245 'jls.vendor' : 'spyl', 246 'jls.vendor.url' : 'http://javalikescript.free.fr/', 247 'jls.version' : '0.1', 248 'line.separator' : '\n', 249 'path.separator' : ';', 250 'user.dir' : '.', 251 'user.home' : '.', 252 'user.name' : '?' 253 }; 254 _native.core.SIGINT = 2; 255 _native.core.SIGILL = 4; 256 _native.core.SIGFPE = 8; 257 _native.core.SIGSEGV = 11; 258 _native.core.SIGTERM = 15; 259 _native.core.SIGBREAK = 21; 260 _native.core.SIGABRT = 22; 261 _native.core.SIG_ERR = -1; 262 _native.core.SIG_DFL = 0; 263 _native.core.SIG_IGN = 1; 264 _native.core.SIG_USR = 2; 265 /* 266 * Class _native.core.ByteArray 267 */ 268 _native.core.ByteArray = function(capacity, adoptable) { 269 this._array = null; 270 this._readOnly = false; 271 if (typeof capacity == 'number') { 272 if (typeof adoptable == 'number') { 273 throw 'Unsupported native operation (new ByteArray from pointer)'; 274 } 275 this._array = new Array(capacity); 276 } else if (typeof capacity == 'string') { 277 this._array = new Array(/*capacity.length * 2*/); 278 for (var i = 0; i < capacity.length; i++) { 279 var c = capacity.charCodeAt(i); 280 this._array.push(c & 0xff); 281 this._array.push((c >>> 8) & 0xff); 282 } 283 _native.core.log(0, 'ByteArray.construct(), this._array.length: ' + this._array.length); 284 this._readOnly = ! adoptable; 285 } else { 286 throw 'Illegal argument type ' + (typeof capacity); 287 } 288 }; 289 _native.core.ByteArray.prototype.free = function() { 290 this._array = null; 291 }; 292 _native.core.ByteArray.prototype.size = function() { 293 return this._array.length; 294 }; 295 _native.core.ByteArray.prototype.put = function(offset, value) { 296 this._array[offset] = value & 0xff; 297 }; 298 _native.core.ByteArray.prototype.get = function(offset) { 299 return this._array[offset]; 300 }; 301 _native.core.ByteArray.prototype.putString = _native.boot.unsupportedFunction; // TODO 302 _native.core.ByteArray.prototype.getString = _native.boot.unsupportedFunction; // TODO 303 _native.core.ByteArray.prototype.putChars = _native.boot.unsupportedFunction; // TODO 304 _native.core.ByteArray.prototype.getChars = function(at, length) { 305 var s = ''; 306 for (var i = at; i < length; i++) { 307 var c = this._array[i * 2] | (this._array[i * 2 + 1] << 8); 308 s += String.fromCharCode(c); 309 } 310 return s; 311 }; 312 _native.core.ByteArray.prototype.toNewChars = function(length) { 313 return this.getChars(0, length); 314 }; 315 _native.core.ByteArray.prototype.pointer = _native.boot.unsupportedFunction; 316 _native.core.ByteArray.prototype.memcpy = function(offset, byteArray, at, length) { 317 _native.core.log(0, 'ByteArray.memcpy(' + offset + ', ?, ' + at + ', ' + length + ')'); 318 for (var i = 0; i < length; i++) { 319 this._array[offset + i] = byteArray._array[at + i]; 320 } 321 }; 322 _native.core.ByteArray.prototype.setPointer = _native.boot.unsupportedFunction; 323 _native.core.ByteArray.prototype.resetPointer = _native.boot.unsupportedFunction; 324 _native.core.ByteArray.prototype.isReadOnly = function() { 325 return this._readOnly; 326 }; 327 /* 328 * Unsupported classes 329 */ 330 _native.core.Thread = _native.boot.unsupportedClass; 331 _native.core.Lock = _native.boot.unsupportedClass; 332 _native.core.Monitor = _native.boot.unsupportedClass; 333 _native.core.Process = _native.boot.unsupportedClass; 334 _native.core.ProcessAttr = _native.boot.unsupportedClass; 335 336 // Update script path 337 if ('arguments' in jlsOptions) { 338 _native.core.arguments = jlsOptions.arguments; 339 } 340 // Update properties 341 if ('properties' in jlsOptions) { 342 for (var name in jlsOptions.properties) { 343 _native.core.properties[name] = jlsOptions.properties[name]; 344 } 345 } 346 // Update script path 347 _native.core._scriptPath = _native.core.properties['jls.script.path'].split(/[;:]/); 348 349 350 /** 351 * jls Base framework. 352 * All the framework objects are created under the jls namespace. 353 * The default objects are extended using prototype like behaviors. 354 * 355 * @namespace 356 * @see jls.lang 357 */ 358 var jls = {}; 359 360 /** 361 * @namespace Provides base classes for the jls language. 362 * @see jls.lang.Exception 363 * @see jls.lang.Logger 364 * @see jls.lang.ClassLoader 365 */ 366 jls.lang = {}; 367 368 // Load prototype light 369 _native.core.evalScript('plight.js'); 370 371 // Load base classes 372 _native.core.evalScript('jls/lang/Exception.js'); 373 _native.core.evalScript('jls/lang/Logger.js'); 374 375 /** 376 * Logger. 377 * 378 * @type jls.lang.Logger 379 * @memberOf jls 380 */ 381 jls.logger = new jls.lang.Logger(jls.lang.Logger.WARN); 382 if ('jls.logger.logLevel' in _native.core.properties) { 383 jls.logger.setLogLevel(_native.core.properties['jls.logger.logLevel']); 384 } 385 386 _native.core.evalScript('jls/lang/ClassLoader.js'); 387 388 /** 389 * ClassLoader. 390 * 391 * @type jls.lang.ClassLoader 392 * @memberOf jls 393 */ 394 jls.loader = new jls.lang.ClassLoader(); 395 396 // Register base classes 397 jls.loader.provide('jls.lang.Exception', true); 398 jls.loader.provide('jls.lang.Logger', true); 399 jls.loader.provide('jls.lang.ClassLoader', true); 400 401