welsonjs/lib/std.js

541 lines
15 KiB
JavaScript
Raw Normal View History

2024-08-06 11:59:29 +00:00
// std.js
2024-08-07 02:55:09 +00:00
// Common routines
2024-08-06 11:59:29 +00:00
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
2020-06-28 14:22:57 +00:00
// Polyfills
if (!Function.prototype.GetResource) {
2020-06-28 16:37:15 +00:00
Function.prototype.GetResource = function(ResourceName) {
2020-07-03 09:15:23 +00:00
if (!this.Resources) {
var UnNamedResourceIndex = 0,
_this = this;
2020-06-28 16:37:15 +00:00
this.Resources = {};
2020-07-03 09:15:23 +00:00
function f(match, resType, Content) {
_this.Resources[(resType == "[[") ? UnNamedResourceIndex++ : resType.slice(1, -1)] = Content;
2020-06-28 16:37:15 +00:00
}
this.toString().replace(/\/\*(\[(?:[^\[]+)?\[)((?:[\r\n]|.)*?)\]\]\*\//gi, f);
2020-06-28 14:22:57 +00:00
}
2020-07-03 09:15:23 +00:00
2020-06-28 16:37:15 +00:00
return this.Resources[ResourceName];
2020-06-28 14:22:57 +00:00
}
}
// The provided code snippet has been corrected by ChatGPT.
// https://chat.openai.com/share/eaab056c-d265-4ee3-b355-9f29176a9caa
// Related issues: #75 #42 #30
2024-01-08 06:42:54 +00:00
if (typeof Enumerator !== "undefined") {
Enumerator.prototype.toArray = function() {
var result = [];
while (!this.atEnd()) {
var currentItem = this.item();
var currentItemProperties = currentItem.Properties_;
var itemObject = {};
var propertiesEnumerator = new Enumerator(currentItemProperties);
while (!propertiesEnumerator.atEnd()) {
var property = propertiesEnumerator.item();
if (typeof property.value !== "unknown") { // The type "Unknown" is Array
itemObject[property.name] = property.value;
} else {
var arrayValues = [];
var index = 0;
while (true) {
try {
arrayValues.push(property.value(index));
index++;
} catch (e) {
break;
}
2022-02-10 06:25:19 +00:00
}
2024-01-08 06:42:54 +00:00
itemObject[property.name] = arrayValues;
2022-02-10 06:25:19 +00:00
}
2024-01-08 06:42:54 +00:00
propertiesEnumerator.moveNext();
2022-02-10 06:25:19 +00:00
}
2024-01-08 06:42:54 +00:00
result.push(itemObject);
this.moveNext();
2020-11-13 08:44:58 +00:00
}
2024-01-08 06:42:54 +00:00
return result;
};
}
2020-11-13 08:44:58 +00:00
// Global APIs
2022-02-10 06:25:19 +00:00
function GetResource(ResourceName) {
2020-06-28 14:22:57 +00:00
return arguments.callee.caller.GetResource(ResourceName);
}
2022-02-10 06:25:19 +00:00
// [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) {
2022-10-10 18:01:24 +00:00
WScript.Sleep(1);
2022-02-10 06:25:19 +00:00
cur = Date.now();
}
2022-02-10 06:25:19 +00:00
end = Date.now();
2022-10-10 18:01:24 +00:00
//WScript.Sleep(ms);
2023-12-20 08:01:24 +00:00
if (typeof callback === "function") {
2023-03-14 04:41:49 +00:00
callback();
2024-01-08 06:42:54 +00:00
}
2022-02-10 06:25:19 +00:00
} else if (typeof window !== "undefined") {
2023-12-20 08:01:24 +00:00
if (typeof callback === "function") {
handler = setTimeout(callback, ms);
2024-01-08 06:42:54 +00:00
}
2022-02-10 06:25:19 +00:00
}
2023-03-14 04:41:49 +00:00
return {
'ms': end,
'handler': handler
};
2022-02-10 06:25:19 +00:00
};
2022-10-21 01:46:30 +00:00
function repeat(target, callback, onError, onNextInterval, onNext) {
2022-02-10 06:25:19 +00:00
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 {
2022-02-20 22:17:48 +00:00
if (typeof callback === "function") {
2022-02-10 06:25:19 +00:00
var result = callback(i);
if (typeof result === "number") {
i += result;
} else if (result === false) {
break;
2022-02-20 22:17:48 +00:00
} else if (result === true) {
i += 1;
2022-02-10 06:25:19 +00:00
}
2022-02-20 22:17:48 +00:00
}
2022-02-10 06:25:19 +00:00
} catch (e) {
2022-02-20 22:17:48 +00:00
if (typeof onError === "function") {
2022-03-03 05:41:20 +00:00
if (onError(e, i) === false) {
2022-02-20 22:17:48 +00:00
break;
}
}
2022-02-10 06:25:19 +00:00
}
2022-10-10 18:01:24 +00:00
2022-10-21 01:46:30 +00:00
// if use onNextInterval method
2022-10-10 18:01:24 +00:00
if (typeof onNextInterval === "function") {
var nextInterval = onNextInterval();
if (typeof nextInterval === "number") {
var nextEnd = cur + nextInterval;
while (cur < nextEnd) {
WScript.Sleep(1);
cur = Date.now();
}
}
}
2022-10-21 01:46:30 +00:00
// if use onNext method
if (typeof onNext === "function") {
try {
onNext();
} catch (e) {}
}
// set the last time
2022-02-10 06:25:19 +00:00
cur = Date.now();
}
end = Date.now();
} else if (typeof window !== "undefined") {
2022-02-20 22:18:28 +00:00
if (typeof callback === "function") {
2022-02-10 06:25:19 +00:00
handler = setInterval(callback, ms);
2022-02-20 22:18:28 +00:00
}
2022-02-10 06:25:19 +00:00
}
2023-03-14 04:41:49 +00:00
return {
'ms': end, 'handler': handler
};
2022-02-10 06:25:19 +00:00
case "object":
var arr = target;
2022-02-10 08:16:59 +00:00
if (arr.length > 0) {
for (var i = 0; i < arr.length; i++) {
try {
if (typeof callback === "function")
if (callback(i, arr[i]) === false)
2023-03-14 04:41:49 +00:00
break;;
2022-02-10 08:16:59 +00:00
} catch (e) {
if (typeof onError === "function")
2022-03-03 05:41:20 +00:00
if (onError(e, i, arr[i]) === false)
2023-03-14 04:41:49 +00:00
break;;
2022-02-10 08:16:59 +00:00
}
2022-02-10 06:25:19 +00:00
}
}
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")
2023-03-14 04:41:49 +00:00
stop = onError(e, i, arr[i]);;
2022-02-08 09:10:10 +00:00
}
2022-02-10 06:25:19 +00:00
i++;
2022-02-14 06:09:01 +00:00
i = i % target.length;
2022-02-10 06:25:19 +00:00
}
};
function range() {
var args = arguments;
2023-03-14 04:41:49 +00:00
var N = [],
start, end, step;
2022-02-10 06:25:19 +00:00
2023-03-14 04:41:49 +00:00
switch (args.length) {
2022-02-10 06:25:19 +00:00
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;
2022-02-08 09:55:29 +00:00
}
2022-02-10 06:25:19 +00:00
for (var i = start; i < end; i = i + step)
2023-03-14 04:41:49 +00:00
N.push(i);
2022-02-10 06:25:19 +00:00
return N;
2022-02-08 09:55:29 +00:00
};
2022-02-10 06:25:19 +00:00
function CHR(ord) {
2020-11-04 07:30:52 +00:00
return String.fromCharCode(ord);
2022-01-08 14:12:59 +00:00
};
2020-10-26 12:01:05 +00:00
2022-02-10 06:25:19 +00:00
function splitLn(s) {
return s.split(/\r?\n/);
};
function addslashes(s) {
return s.toString().replace(/\\/g, '\\\\').
2023-03-14 04:41:49 +00:00
replace(/\u0008/g, '\\b').
replace(/\t/g, '\\t').
replace(/\n/g, '\\n').
replace(/\f/g, '\\f').
replace(/\r/g, '\\r').
replace(/'/g, '\\\'').
replace(/"/g, '\\"');
2022-02-10 06:25:19 +00:00
};
2023-12-20 08:01:24 +00:00
function alert(message) {
if (typeof window !== "undefined") {
window.alert(message);
} else {
CreateObject("WScript.Shell").Popup(message);
}
}
2020-06-28 14:22:57 +00:00
2023-12-20 08:01:24 +00:00
function confirm(message) {
if (typeof window !== "undefined") {
return window.confirm(message);
} else {
CreateObject("WScript.Shell").Popup(message);
}
2022-04-28 04:11:26 +00:00
}
2022-02-10 06:25:19 +00:00
// Standard Event Object
2024-09-18 05:33:15 +00:00
function StdEvent(type, options) {
2022-01-08 14:12:59 +00:00
this.defaultPrevented = false;
this.timeStamp = new Date();
2022-05-10 02:45:02 +00:00
this.type = type;
2022-05-10 02:46:12 +00:00
this.isTrusted = true;
this.cancelable = true;
2022-01-08 14:12:59 +00:00
this.target = null;
2022-05-10 02:46:12 +00:00
this.currentTarget = null;
this.eventPhase = StdEvent.NONE;
2023-03-14 04:41:49 +00:00
this.bubbles = false; // Not used but to be compatible
this.composed = false; // Not used but to be compatible
2022-01-08 14:12:59 +00:00
this.preventDefault = function() {
this.defaultPrevented = true;
};
2022-05-10 02:45:02 +00:00
// Not used but to be compatible
2022-05-10 04:40:46 +00:00
this.initEvent = function(type, bubbles, cancelable) {
2022-05-10 02:45:02 +00:00
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() {};
2024-09-18 05:33:15 +00:00
// Apply the options
for (var optionKey in options) {
if (!(optionKey in this)) {
this[optionKey] = options[optionKey];
}
}
2022-01-08 14:12:59 +00:00
};
2022-05-10 02:45:02 +00:00
StdEvent.NONE = 0;
2023-03-14 04:41:49 +00:00
StdEvent.CAPTURING_PHASE = 1; // Not used but to be compatible
2022-05-10 02:45:02 +00:00
StdEvent.AT_TARGET = 2;
2023-03-14 04:41:49 +00:00
StdEvent.BUBBLING_PHASE = 3; // Not used but to be compatible
2022-01-08 14:12:59 +00:00
2024-08-14 05:00:02 +00:00
// Standard EventTarget Object
2023-02-01 01:50:15 +00:00
function StdEventTarget() {
this.__events__ = [];
2022-09-18 19:44:58 +00:00
this.dispatchEvent = function(event, __exception__) {
2022-01-08 14:12:59 +00:00
event.target = this;
2022-05-10 02:45:02 +00:00
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];
2022-09-18 19:44:58 +00:00
if (e.type == event.type && typeof(e.listener) === "function") {
2022-09-18 20:12:38 +00:00
try {
e.listener(event, __exception__);
2022-09-18 20:12:38 +00:00
} catch (ex) {
this.dispatchEvent(new StdEvent("error"), ex);
}
2022-09-18 19:44:58 +00:00
}
}
2022-01-08 14:12:59 +00:00
};
2022-09-18 19:44:58 +00:00
this.addEventListener = function(type, listener) {
2022-09-18 19:45:32 +00:00
if (typeof listener === "function") {
this.__events__.push({
2022-09-18 19:44:58 +00:00
"type": type,
"listener": listener,
"counter": StdEventTarget.__counter__
2022-09-18 19:44:58 +00:00
});
StdEventTarget.__counter__++;
2022-09-18 19:44:58 +00:00
} else {
throw new TypeError("EventListener must be a function");
}
};
this.removeEventListener = function(type, listener) {
2022-09-18 19:45:32 +00:00
if (typeof listener === "function") {
for (var i = 0; i < this.__events__.length; i++) {
var e = this.__events__[i];
2022-09-18 20:16:05 +00:00
if (e.type == type && typeof(e.listener) === "function" && e.listener.toString() == listener.toString()) {
delete this.__events__[i];
2022-09-18 19:44:58 +00:00
}
}
2022-01-08 14:12:59 +00:00
} else {
throw new TypeError("EventListener must be a function");
}
};
};
StdEventTarget.__counter__ = 0;
2024-08-14 05:00:02 +00:00
function AsyncFunction(f) {
2022-02-24 08:13:31 +00:00
this.f = f;
2024-08-14 05:00:02 +00:00
this.__filename = AsyncFunction.__filename__;
2022-02-25 05:42:17 +00:00
2022-02-24 08:13:31 +00:00
this.run = function() {
2022-06-05 10:50:37 +00:00
var args = Array.from(arguments);
2022-05-09 08:55:47 +00:00
2022-06-05 10:50:37 +00:00
// increase number of async functions
2024-08-14 05:00:02 +00:00
AsyncFunction.__counter__++;
2023-03-14 04:41:49 +00:00
2022-06-05 10:50:37 +00:00
// decrease number of async functions
2024-08-14 05:00:02 +00:00
var dispatch = function(_args, _f) {
if (typeof _f === "function") _f.apply(null, _args);
AsyncFunction._counter--;
2022-05-09 08:55:47 +00:00
};
2022-06-05 10:50:37 +00:00
// CLI or Window?
if (typeof WScript !== "undefined") {
2024-08-14 05:00:02 +00:00
(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);
2022-02-25 05:42:17 +00:00
} else {
2024-08-14 05:00:02 +00:00
dispatch(args, this.f);
2022-02-25 05:42:17 +00:00
}
2022-02-24 08:13:31 +00:00
};
2022-04-11 06:35:53 +00:00
2022-02-24 08:13:31 +00:00
this.runSynchronously = function() {
2022-02-25 05:42:17 +00:00
return this.f.apply(null, arguments);
2022-02-24 08:13:31 +00:00
};
2024-08-14 05:00:02 +00:00
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__++;
2022-06-05 10:50:37 +00:00
};
AsyncFunction.__counter__ = 0;
2024-08-14 05:00:02 +00:00
AsyncFunction.__filename__ = "bootstrap.js";
2024-08-06 12:37:00 +00:00
AsyncFunction.Initialize = function(exports, args) {
2024-08-06 12:15:59 +00:00
if (args.length < 2)
return;
2022-06-05 10:50:37 +00:00
2024-08-06 12:15:59 +00:00
if (args[0] != "/async")
return;
2022-06-05 10:50:37 +00:00
2024-08-06 12:15:59 +00:00
var target = args[1];
if (target in exports && exports[target] instanceof AsyncFunction) {
try {
2024-08-06 13:03:24 +00:00
exports[target].f(args.slice(2));
2024-08-06 12:15:59 +00:00
} catch (e) {
console.error("Exception on", target, e.message);
2022-02-25 05:42:17 +00:00
}
}
2022-06-05 10:50:37 +00:00
2024-08-14 05:00:02 +00:00
throw new AsyncFunction.Initialized("Initialized");
2022-02-24 08:13:31 +00:00
};
2024-08-06 12:49:10 +00:00
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);
};
2024-08-14 05:00:02 +00:00
AsyncFunction.Initialized = function(message) {
this.name = "AsyncFunction.Initialized";
2023-12-20 08:01:24 +00:00
this.message = message;
};
2024-08-14 05:00:02 +00:00
AsyncFunction.Initialized.prototype = new Error();
AsyncFunction.Initialized.prototype.constructor = AsyncFunction.Initialized;
2023-12-20 08:01:24 +00:00
function GeneratorFunction(f) {
var _lastState = 0;
var _state = 0;
var _yield = function(value) {
_state++;
if (_state > _lastState) {
throw new GeneratorFunction.Yield(value);
2023-03-10 08:46:50 +00:00
}
};
this.next = function() {
var go = true;
2023-12-20 08:01:24 +00:00
var value = undefined;
_state = 0;
2023-03-10 08:46:50 +00:00
while (go) {
try {
2023-12-20 08:01:24 +00:00
f(_yield);
2023-03-10 08:46:50 +00:00
} catch (e) {
2023-12-20 08:01:24 +00:00
if (e instanceof GeneratorFunction.Yield) {
value = e.message;
go = false;
_lastState = _state;
} else {
console.error(e.message);
}
2023-03-10 08:46:50 +00:00
}
}
2023-03-14 04:41:49 +00:00
2023-03-10 08:46:50 +00:00
return {
2023-12-20 08:01:24 +00:00
"value": value,
"done": false
}
2023-03-10 08:46:50 +00:00
};
2023-12-20 08:01:24 +00:00
}
GeneratorFunction.Yield = function(message) {
this.name = "GeneratorFunction.Yield";
this.message = message;
};
GeneratorFunction.Yield.prototype = new Error();
GeneratorFunction.Yield.prototype.constructor = GeneratorFunction.Yield;
2023-03-10 08:46:50 +00:00
function StdStorage() {
2024-08-14 05:00:02 +00:00
this.data = {};
this.length = 0;
this.commit = function() {
this.length = Object.keys(data).length;
};
this.key = function(idx) {
var keyName = Object.keys(data)[idx];
return data[keyName];
};
this.setItem = function(keyName, keyValue) {
data[keyName] = keyValue;
2024-08-14 05:00:02 +00:00
this.commit();
};
this.getItem = function(keyName) {
return data[keyName];
};
this.removeItem = function(keyName) {
delete data[keyName];
2024-08-14 05:00:02 +00:00
this.commit();
};
this.clear = function() {
2024-08-14 05:00:02 +00:00
this.data = {};
this.commit();
};
}
2022-02-10 06:25:19 +00:00
global.GetResource = GetResource;
global.sleep = sleep;
global.repeat = repeat;
global.rotate = rotate;
global.range = range;
global.CHR = CHR;
global.splitLn = splitLn;
global.addslashes = addslashes;
2022-02-24 08:13:31 +00:00
global.AsyncFunction = AsyncFunction;
2024-08-14 05:00:02 +00:00
global.GeneratorFunction = GeneratorFunction;
2022-02-10 06:25:19 +00:00
2022-01-08 14:35:07 +00:00
exports.Event = StdEvent;
2023-02-01 01:50:15 +00:00
exports.EventTarget = StdEventTarget;
2024-08-14 05:05:02 +00:00
exports.Storage = StdStorage;
2022-04-29 07:11:49 +00:00
2022-04-28 04:11:26 +00:00
exports.alert = alert;
2023-12-20 08:01:24 +00:00
exports.confirm = confirm;
2024-08-14 05:05:02 +00:00
exports.VERSIONINFO = "WelsonJS Standard Library (std.js) version 0.8.10";
2023-12-20 08:01:24 +00:00
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;