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