mirror of
				https://github.com/gnh1201/welsonjs.git
				synced 2025-10-31 04:51:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			637 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			637 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // std.js
 | |
| // Copyright 2019-2025, Namhyeon Go <gnh1201@catswords.re.kr> and the WelsonJS contributors.
 | |
| // SPDX-License-Identifier: GPL-3.0-or-later
 | |
| // https://github.com/gnh1201/welsonjs
 | |
| // 
 | |
| // WelsonJS Standard Library (Polyfills and shared functions)
 | |
| // 
 | |
| if (!Function.prototype.GetResource) {
 | |
|     Function.prototype.GetResource = function(ResourceName) {
 | |
|         if (!this.Resources) {
 | |
|             var UnNamedResourceIndex = 0,
 | |
|                 _this = this;
 | |
|             this.Resources = {};
 | |
| 
 | |
|             function f(match, resType, Content) {
 | |
|                 _this.Resources[(resType == "[[") ? UnNamedResourceIndex++ : resType.slice(1, -1)] = Content;
 | |
|             }
 | |
|             this.toString().replace(/\/\*(\[(?:[^\[]+)?\[)((?:[\r\n]|.)*?)\]\]\*\//gi, f);
 | |
|         }
 | |
| 
 | |
|         return this.Resources[ResourceName];
 | |
|     }
 | |
| }
 | |
| 
 | |
| function GetResource(ResourceName) {
 | |
|     return arguments.callee.caller.GetResource(ResourceName);
 | |
| }
 | |
| 
 | |
| (function() {
 | |
|     var originalFrom = Array.from;
 | |
| 
 | |
|     function convertToArray(v) {
 | |
|         var result = [];
 | |
|         while (!v.atEnd()) {
 | |
|             var item = v.item();
 | |
|             result.push(typeof item === "unknown" ? Array.from(item) : item);
 | |
|             v.moveNext();
 | |
|         }
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     function convertToObject(v) {
 | |
|         var obj = {};
 | |
|         var props = new Enumerator(v.Properties_);
 | |
|         while (!props.atEnd()) {
 | |
|             var prop = props.item();
 | |
|             obj[prop.name] = typeof prop.value === "unknown" ?
 | |
|                 Array.from(prop.value) :
 | |
|                 prop.value;
 | |
|             props.moveNext();
 | |
|         }
 | |
|         return obj;
 | |
|     }
 | |
| 
 | |
|     Array.from = function(value) {
 | |
|         if (value && typeof value.item === "unknown") {
 | |
|             value = new Enumerator(value);
 | |
|         }
 | |
| 
 | |
|         if (value instanceof Enumerator) {
 | |
|             return value && value.Properties_ ?
 | |
|                 convertToObject(value) :
 | |
|                 convertToArray(value);
 | |
|         }
 | |
| 
 | |
|         return originalFrom ? originalFrom(value) : Array.prototype.slice.call(value);
 | |
|     };
 | |
| 
 | |
|     Array.from.toString = function() {
 | |
|         return originalFrom.toString();
 | |
|     };
 | |
| 
 | |
|     // compatible under version 0.2.7.55
 | |
|     Enumerator.prototype.toArray = Array.from;
 | |
| })();
 | |
| 
 | |
| // [lib/std] the time of `sleep()' function is not accuracy #34
 | |
| function sleep(ms, callback) {
 | |
|     var handler = null;
 | |
| 
 | |
|     var cur = Date.now();
 | |
|     var end = cur + ms;
 | |
| 
 | |
|     if (typeof WScript !== "undefined") {
 | |
|         while (cur < end) {
 | |
|             WScript.Sleep(1);
 | |
|             cur = Date.now();
 | |
|         }
 | |
|         end = Date.now();
 | |
|         //WScript.Sleep(ms);
 | |
| 
 | |
|         if (typeof callback === "function") {
 | |
|             callback();
 | |
|         }
 | |
|     } else if (typeof window !== "undefined") {
 | |
|         if (typeof callback === "function") {
 | |
|             handler = setTimeout(callback, ms);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return {
 | |
|         'ms': end,
 | |
|         'handler': handler
 | |
|     };
 | |
| };
 | |
| 
 | |
| function repeat(target, callback, onError, onNextInterval, onNext) {
 | |
|     switch (typeof target) {
 | |
|         case "number":
 | |
|         case "boolean":
 | |
|             var ms = target;
 | |
| 
 | |
|             var i = 0;
 | |
|             var result = null;
 | |
|             var handler = null;
 | |
|             var cur = Date.now();
 | |
|             var end = cur + ms;
 | |
| 
 | |
|             if (typeof WScript !== "undefined") {
 | |
|                 while (ms === true ? true : (cur < end)) {
 | |
|                     try {
 | |
|                         if (typeof callback === "function") {
 | |
|                             var result = callback(i);
 | |
|                             if (typeof result === "number") {
 | |
|                                 i += result;
 | |
|                             } else if (result === false) {
 | |
|                                 break;
 | |
|                             } else if (result === true) {
 | |
|                                 i += 1;
 | |
|                             }
 | |
|                         }
 | |
|                     } catch (e) {
 | |
|                         if (typeof onError === "function") {
 | |
|                             if (onError(e, i) === false) {
 | |
|                                 break;
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     // if use onNextInterval method
 | |
|                     if (typeof onNextInterval === "function") {
 | |
|                         var nextInterval = onNextInterval();
 | |
|                         if (typeof nextInterval === "number") {
 | |
|                             var nextEnd = cur + nextInterval;
 | |
|                             while (cur < nextEnd) {
 | |
|                                 WScript.Sleep(1);
 | |
|                                 cur = Date.now();
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     // if use onNext method
 | |
|                     if (typeof onNext === "function") {
 | |
|                         try {
 | |
|                             onNext();
 | |
|                         } catch (e) {}
 | |
|                     }
 | |
| 
 | |
|                     // set the last time
 | |
|                     cur = Date.now();
 | |
|                 }
 | |
|                 end = Date.now();
 | |
|             } else if (typeof window !== "undefined") {
 | |
|                 if (typeof callback === "function") {
 | |
|                     handler = setInterval(callback, ms);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return {
 | |
|                 'ms': end, 'handler': handler
 | |
|             };
 | |
| 
 | |
|         case "object":
 | |
|             var arr = target;
 | |
|             if (arr.length > 0) {
 | |
|                 for (var i = 0; i < arr.length; i++) {
 | |
|                     try {
 | |
|                         if (typeof callback === "function")
 | |
|                             if (callback(i, arr[i]) === false)
 | |
|                                 break;;
 | |
|                     } catch (e) {
 | |
|                         if (typeof onError === "function")
 | |
|                             if (onError(e, i, arr[i]) === false)
 | |
|                                 break;;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             break;
 | |
|     }
 | |
| };
 | |
| 
 | |
| function rotate(target, callback, onError) {
 | |
|     var arr = target;
 | |
|     var i = 0;
 | |
|     var stop = false;
 | |
| 
 | |
|     while (!stop) {
 | |
|         try {
 | |
|             if (typeof callback === "function") {
 | |
|                 stop = callback(i, arr[i]);
 | |
|             } else {
 | |
|                 stop = true;
 | |
|             }
 | |
|         } catch (e) {
 | |
|             if (typeof onError === "function")
 | |
|                 stop = onError(e, i, arr[i]);;
 | |
|         }
 | |
| 
 | |
|         i++;
 | |
|         i = i % target.length;
 | |
|     }
 | |
| };
 | |
| 
 | |
| function range() {
 | |
|     var args = arguments;
 | |
|     var N = [],
 | |
|         start, end, step;
 | |
| 
 | |
|     switch (args.length) {
 | |
|         case 3:
 | |
|             start = args[0];
 | |
|             end = args[1];
 | |
|             step = args[2];
 | |
|             break;
 | |
| 
 | |
|         case 2:
 | |
|             start = args[0];
 | |
|             end = args[1];
 | |
|             step = 1;
 | |
|             break;
 | |
| 
 | |
|         case 1:
 | |
|             start = 0;
 | |
|             end = args[0];
 | |
|             step = 1;
 | |
|             break;
 | |
|     }
 | |
| 
 | |
|     for (var i = start; i < end; i = i + step)
 | |
|         N.push(i);
 | |
| 
 | |
|     return N;
 | |
| };
 | |
| 
 | |
| function CHR(ord) {
 | |
|     return String.fromCharCode(ord);
 | |
| };
 | |
| 
 | |
| function splitLn(s) {
 | |
|     return s.split(/\r?\n/);
 | |
| };
 | |
| 
 | |
| function addslashes(s) {
 | |
|     return s.toString().replace(/\\/g, '\\\\').
 | |
|     replace(/\u0008/g, '\\b').
 | |
|     replace(/\t/g, '\\t').
 | |
|     replace(/\n/g, '\\n').
 | |
|     replace(/\f/g, '\\f').
 | |
|     replace(/\r/g, '\\r').
 | |
|     replace(/'/g, '\\\'').
 | |
|     replace(/"/g, '\\"');
 | |
| };
 | |
| 
 | |
| function alert(message) {
 | |
|     if (typeof window !== "undefined") {
 | |
|         window.alert(message);
 | |
|     } else {
 | |
|         try {
 | |
|             CreateObject("WScript.Shell").Popup(message, 0, "WelsonJS", 0);
 | |
|         } catch (e) {
 | |
|             console.error(e.message);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| function confirm(message) {
 | |
|     var result;
 | |
|     
 | |
|     if (typeof window !== "undefined") {
 | |
|         result = window.confirm(message);
 | |
|     } else {
 | |
|         try {
 | |
|             result = (CreateObject("WScript.Shell").Popup(message, 0, "WelsonJS", 4) == 6);
 | |
|         } catch (e) {
 | |
|             console.error(e.message);
 | |
|             result = false;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| function prompt(message, _default) {
 | |
|     var result;
 | |
|     
 | |
|     if (typeof window !== "undefined") {
 | |
|         result = window.prompt(message);
 | |
|     } else {
 | |
|         try {
 | |
|             result = CreateObject("WelsonJS.Toolkit").Prompt(message);
 | |
|         } catch (e) {
 | |
|             console.error(e.message);
 | |
|             if (typeof _default !== "undefined") {
 | |
|                 result = _default;
 | |
|                 console.warn("Use default value:", _default);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| function parseEnv(s) {
 | |
|     var envConfig = {};
 | |
|     var lines = s.split('\n');
 | |
| 
 | |
|     for (var i = 0; i < lines.length; i++) {
 | |
|         var line = lines[i].replace(/^\s+|\s+$/g, '');
 | |
|         if (line && line.indexOf('=') !== -1 && line.charAt(0) !== '#') {
 | |
|             var parts = line.split('=');
 | |
|             var key = parts[0].replace(/^\s+|\s+$/g, '');
 | |
|             var value = parts[1].replace(/^\s+|\s+$/g, '').replace(/^"(.*)"$/, '$1');
 | |
|             envConfig[key] = value;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return envConfig;
 | |
| };
 | |
| 
 | |
| // Standard Event Object
 | |
| function StdEvent(type, options) {
 | |
|     this.defaultPrevented = false;
 | |
|     this.timeStamp = new Date();
 | |
|     this.type = type;
 | |
|     this.isTrusted = true;
 | |
|     this.cancelable = true;
 | |
|     this.target = null;
 | |
|     this.currentTarget = null;
 | |
|     this.eventPhase = StdEvent.NONE;
 | |
|     this.bubbles = false; // Not used but to be compatible
 | |
|     this.composed = false; // Not used but to be compatible
 | |
| 
 | |
|     this.preventDefault = function() {
 | |
|         this.defaultPrevented = true;
 | |
|     };
 | |
| 
 | |
|     // Not used but to be compatible
 | |
|     this.initEvent = function(type, bubbles, cancelable) {
 | |
|         this.type = type;
 | |
|         this.bubbles = bubbles;
 | |
|         this.cancelable = cancelable;
 | |
|     };
 | |
| 
 | |
|     // Not used but to be compatible
 | |
|     this.stopImmediatePropagation = function() {};
 | |
| 
 | |
|     // Not used but to be compatible
 | |
|     this.stopPropagation = function() {};
 | |
| 
 | |
|     // Apply the options
 | |
|     for (var optionKey in options) {
 | |
|         if (!(optionKey in this)) {
 | |
|             this[optionKey] = options[optionKey];
 | |
|         }
 | |
|     }
 | |
| };
 | |
| StdEvent.NONE = 0;
 | |
| StdEvent.CAPTURING_PHASE = 1; // Not used but to be compatible
 | |
| StdEvent.AT_TARGET = 2;
 | |
| StdEvent.BUBBLING_PHASE = 3; // Not used but to be compatible
 | |
| 
 | |
| // Standard EventTarget Object
 | |
| function StdEventTarget() {
 | |
|     this.__events__ = [];
 | |
| 
 | |
|     this.dispatchEvent = function(event, __exception__) {
 | |
|         event.target = this;
 | |
|         event.isTrusted = false;
 | |
|         event.eventPhase = StdEvent.AT_TARGET;
 | |
|         event.currentTarget = event.target;
 | |
|         for (var i = 0; i < this.__events__.length; i++) {
 | |
|             var e = this.__events__[i];
 | |
|             if (e.type == event.type && typeof(e.listener) === "function") {
 | |
|                 try {
 | |
|                     e.listener(event, __exception__);
 | |
|                 } catch (ex) {
 | |
|                     this.dispatchEvent(new StdEvent("error"), ex);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     this.addEventListener = function(type, listener) {
 | |
|         if (typeof listener === "function") {
 | |
|             this.__events__.push({
 | |
|                 "type": type,
 | |
|                 "listener": listener,
 | |
|                 "counter": StdEventTarget.__counter__
 | |
|             });
 | |
|             StdEventTarget.__counter__++;
 | |
|         } else {
 | |
|             throw new TypeError("EventListener must be a function");
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     this.removeEventListener = function(type, listener) {
 | |
|         if (typeof listener === "function") {
 | |
|             for (var i = 0; i < this.__events__.length; i++) {
 | |
|                 var e = this.__events__[i];
 | |
|                 if (e.type == type && typeof(e.listener) === "function" && e.listener.toString() == listener.toString()) {
 | |
|                     delete this.__events__[i];
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
|             throw new TypeError("EventListener must be a function");
 | |
|         }
 | |
|     };
 | |
| };
 | |
| StdEventTarget.__counter__ = 0;
 | |
| 
 | |
| function AsyncFunction(f) {
 | |
|     this.f = f;
 | |
|     this.__filename = AsyncFunction.__filename__;
 | |
| 
 | |
|     this.run = function() {
 | |
|         var args = Array.from(arguments);
 | |
| 
 | |
|         // increase number of async functions
 | |
|         AsyncFunction.__counter__++;
 | |
| 
 | |
|         // decrease number of async functions
 | |
|         var dispatch = function(_args, _f) {
 | |
|             if (typeof _f === "function") _f.apply(null, _args);
 | |
|             AsyncFunction._counter--;
 | |
|         };
 | |
| 
 | |
|         // CLI or Window?
 | |
|         if (typeof WScript !== "undefined") {
 | |
|             (function(_args, SHELL) {
 | |
|                 SHELL.show(["cscript", "app.js", this.__filename, "/async", f].concat(_args));
 | |
|             })(args, require("lib/shell"));
 | |
|         } else if (typeof window !== "undefined") {
 | |
|             (function(_args, _f) {
 | |
|                 window.setTimeout(function() {
 | |
|                     dispatch(_args, _f);
 | |
|                 }, 1);
 | |
|             })(args, this.f);
 | |
|         } else {
 | |
|             dispatch(args, this.f);
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     this.runSynchronously = function() {
 | |
|         return this.f.apply(null, arguments);
 | |
|     };
 | |
| 
 | |
|     if (typeof this.__filename === "string") {
 | |
|         this.__filename = __filename;
 | |
|     } else if (typeof WScript !== "undefined") {
 | |
|         this.__filename = (function(path) {
 | |
|             var pos = Math.max.apply(null, [path.lastIndexOf("\\"), path.lastIndexOf("/")]);
 | |
|             return (pos > -1 ? path.substring(pos + 1) : "");
 | |
|         })(WScript.ScriptFullName);
 | |
|     }
 | |
|     
 | |
|     if (typeof this.__filename === "string") {
 | |
|         this.__filename = __filename;
 | |
|     } else if (typeof WScript !== "undefined") {
 | |
|         this.__filename = (function(path) {
 | |
|             var pos = Math.max.apply(null, [path.lastIndexOf("\\"), path.lastIndexOf("/")]);
 | |
|             return (pos > -1 ? path.substring(pos + 1) : "");
 | |
|         })(WScript.ScriptFullName);
 | |
|     }
 | |
| 
 | |
|     AsyncFunction.__counter__++;
 | |
| };
 | |
| AsyncFunction.__counter__ = 0;
 | |
| AsyncFunction.__filename__ = "bootstrap.js";
 | |
| AsyncFunction.Initialize = function(exports, args) {
 | |
|     if (args.length < 2)
 | |
|         return;
 | |
| 
 | |
|     if (args[0] != "/async")
 | |
|         return;
 | |
| 
 | |
|     var target = args[1];
 | |
|     if (target in exports && exports[target] instanceof AsyncFunction) {
 | |
|         try {
 | |
|             exports[target].f(args.slice(2));
 | |
|         } catch (e) {
 | |
|             console.error("Exception on", target, e.message);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     throw new AsyncFunction.Initialized("Initialized");
 | |
| };
 | |
| AsyncFunction.bind = function(exports, args) {    // compatible under 0.2.7.31
 | |
|     console.warn("AsyncFunction.bind() is deprecated. Use AsyncFunction.Initialize()");
 | |
|     return AsyncFunction.Initialize(exports, args); 
 | |
| };
 | |
| AsyncFunction.Initialized = function(message) {
 | |
|     this.name = "AsyncFunction.Initialized";
 | |
|     this.message = message;
 | |
| };
 | |
| AsyncFunction.Initialized.prototype = new Error();
 | |
| AsyncFunction.Initialized.prototype.constructor = AsyncFunction.Initialized;
 | |
| 
 | |
| function GeneratorFunction(f) {
 | |
|     var _lastState = 0;
 | |
|     var _state = 0;
 | |
|     var _yield = function(value) {
 | |
|         _state++;
 | |
|         if (_state > _lastState) {
 | |
|             throw new GeneratorFunction.Yield(value);
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     this.next = function() {
 | |
|         var go = true;
 | |
|         var value = undefined;
 | |
| 
 | |
|         _state = 0;
 | |
| 
 | |
|         while (go) {
 | |
|             try {
 | |
|                 f(_yield);
 | |
|             } catch (e) {
 | |
|                 if (e instanceof GeneratorFunction.Yield) {
 | |
|                     value = e.message;
 | |
|                     go = false;
 | |
|                     _lastState = _state;
 | |
|                 } else {
 | |
|                     console.error(e.message);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return {
 | |
|             "value": value,
 | |
|             "done": false
 | |
|         }
 | |
|     };
 | |
| }
 | |
| GeneratorFunction.Yield = function(message) {
 | |
|     this.name = "GeneratorFunction.Yield";
 | |
|     this.message = message;
 | |
| };
 | |
| GeneratorFunction.Yield.prototype = new Error();
 | |
| GeneratorFunction.Yield.prototype.constructor = GeneratorFunction.Yield;
 | |
| 
 | |
| function StdAccessor(initialValue) {
 | |
|     var value = initialValue;
 | |
| 
 | |
|     this.get = function() {
 | |
|         return value;
 | |
|     };
 | |
| 
 | |
|     this.set = function(v) {
 | |
|         value = v;
 | |
|     };
 | |
| }
 | |
| StdAccessor.isAccessor = function(obj) {
 | |
|     return obj instanceof StdAccessor;
 | |
| };
 | |
| 
 | |
| function StdStorage() {
 | |
|     var data = new StdAccessor({});
 | |
|     var length = new StdAccessor(0);
 | |
| 
 | |
|     function commit() {
 | |
|         length.set(Object.keys(data.get()).length);
 | |
|     }
 | |
| 
 | |
|     this.setItem = function(keyName, keyValue) {
 | |
|         var d = data.get();
 | |
|         d[keyName] = keyValue;
 | |
|         data.set(d);
 | |
|         commit();
 | |
|     };
 | |
| 
 | |
|     this.getItem = function(keyName) {
 | |
|         return data.get()[keyName];
 | |
|     };
 | |
| 
 | |
|     this.removeItem = function(keyName) {
 | |
|         var d = data.get();
 | |
|         delete d[keyName];
 | |
|         data.set(d);
 | |
|         commit();
 | |
|     };
 | |
| 
 | |
|     this.clear = function() {
 | |
|         data.set({});
 | |
|         commit();
 | |
|     };
 | |
| 
 | |
|     this.key = function(idx) {
 | |
|         var d = data.get();
 | |
|         return Object.keys(d)[idx];
 | |
|     };
 | |
| 
 | |
|     this.length = function() {
 | |
|         return length.get();
 | |
|     };
 | |
| }
 | |
| 
 | |
| global.GetResource = GetResource;
 | |
| global.sleep = sleep;
 | |
| global.repeat = repeat;
 | |
| global.rotate = rotate;
 | |
| global.range = range;
 | |
| global.CHR = CHR;
 | |
| global.splitLn = splitLn;
 | |
| global.addslashes = addslashes;
 | |
| global.AsyncFunction = AsyncFunction;
 | |
| global.GeneratorFunction = GeneratorFunction;
 | |
| global.parseEnv = parseEnv;
 | |
| 
 | |
| exports.Event = StdEvent;
 | |
| exports.EventTarget = StdEventTarget;
 | |
| exports.Accessor = StdAccessor;
 | |
| exports.Storage = StdStorage;
 | |
| 
 | |
| /**
 | |
|  * @deprecated Use STD.EventTarget instead of STD.EventableObject
 | |
|  */
 | |
| exports.EventableObject = StdEventTarget;
 | |
| 
 | |
| exports.alert = alert;
 | |
| exports.confirm = confirm;
 | |
| exports.prompt = prompt;
 | |
| 
 | |
| exports.VERSIONINFO = "WelsonJS Standard Library (std.js) version 0.8.19";
 | |
| exports.AUTHOR = "gnh1201@catswords.re.kr";
 | |
| exports.global = global;
 | |
| exports.require = global.require;
 |