mirror of
https://github.com/gnh1201/welsonjs.git
synced 2024-11-26 15:31:42 +00:00
590 lines
16 KiB
JavaScript
590 lines
16 KiB
JavaScript
//////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// std.js
|
|
//
|
|
// Common routines. Defines LIB object which contains the API, as well as
|
|
// a global DBG function.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
// Polyfills
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
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];
|
|
}
|
|
}
|
|
|
|
// The provided code snippet has been corrected by ChatGPT.
|
|
// https://chat.openai.com/share/eaab056c-d265-4ee3-b355-9f29176a9caa
|
|
// Related issues: #75 #42 #30
|
|
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;
|
|
}
|
|
}
|
|
itemObject[property.name] = arrayValues;
|
|
}
|
|
propertiesEnumerator.moveNext();
|
|
}
|
|
result.push(itemObject);
|
|
this.moveNext();
|
|
}
|
|
return result;
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
// Global APIs
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function GetResource(ResourceName) {
|
|
return arguments.callee.caller.GetResource(ResourceName);
|
|
}
|
|
|
|
// [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, '\\"');
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
// Private APIs / Utility functions
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
// Emulate Server.CreateObject
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function CreateObject(progId, serverName, callback) {
|
|
var progIds = [];
|
|
var _CreateObject = function(p, s) {
|
|
if (typeof WScript !== "undefined") {
|
|
return WScript.CreateObject(p, s);
|
|
} else if (typeof ActiveXObject !== "undefined") {
|
|
return new ActiveXObject(p);
|
|
}
|
|
return null;
|
|
};
|
|
|
|
if (typeof progId == "object") {
|
|
progIds = progId;
|
|
} else {
|
|
progIds.push(progId);
|
|
}
|
|
|
|
for (var i = 0; i < progIds.length; i++) {
|
|
try {
|
|
var obj = _CreateObject(progIds[i], serverName);
|
|
if (typeof callback === "function") {
|
|
callback(obj, progIds[i]);
|
|
}
|
|
return obj;
|
|
} catch (e) {
|
|
console.error(e.message);
|
|
};
|
|
}
|
|
}
|
|
|
|
function alert(message) {
|
|
if (typeof window !== "undefined") {
|
|
window.alert(message);
|
|
} else {
|
|
CreateObject("WScript.Shell").Popup(message);
|
|
}
|
|
}
|
|
|
|
function confirm(message) {
|
|
if (typeof window !== "undefined") {
|
|
return window.confirm(message);
|
|
} else {
|
|
CreateObject("WScript.Shell").Popup(message);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
// Standard Event Object
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// https://developer.mozilla.org/ko/docs/Web/API/Event
|
|
|
|
function StdEvent(type) {
|
|
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() {};
|
|
};
|
|
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
|
|
|
|
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;
|
|
|
|
/*
|
|
var a = new AsyncFunction(function() {
|
|
console.log("calling A");
|
|
});
|
|
|
|
var _async_b = function(function() {
|
|
console.log("calling B");
|
|
});
|
|
|
|
function main(args) {
|
|
AsyncFunction.bind(this, args);
|
|
console.log("welcome");
|
|
}
|
|
|
|
exports.a = a;
|
|
exports._async_b = _async_b;
|
|
*/
|
|
|
|
function AsyncFunction(f, __filename) {
|
|
this.f = f;
|
|
this.__filename = __filename;
|
|
|
|
this.run = function() {
|
|
var args = Array.from(arguments);
|
|
|
|
// increase number of async functions
|
|
AsyncFunction.counter++;
|
|
|
|
// decrease number of async functions
|
|
var _this = this;
|
|
var _f = function() {
|
|
if (typeof _this.f === "function") _this.f();
|
|
AsyncFunction.counter--;
|
|
};
|
|
|
|
// CLI or Window?
|
|
if (typeof WScript !== "undefined") {
|
|
require("lib/shell").show(["cscript", "app.js", this.__filename, f].concat(args));
|
|
} else {
|
|
sleep(1, _f);
|
|
}
|
|
};
|
|
|
|
this.runSynchronously = function() {
|
|
return this.f.apply(null, arguments);
|
|
};
|
|
};
|
|
AsyncFunction.counter = 0;
|
|
AsyncFunction.bind = function(exports, args) {
|
|
var result = false;
|
|
|
|
if (args.length > 0) {
|
|
var targets = [args[0], '_async_' + args[0]];
|
|
|
|
for (var i = 0; (i < targets.length && result == false); i++) {
|
|
var target = targets[i];
|
|
|
|
if (target in exports && (typeof exports[target] === "function" || exports[target] instanceof AsyncFunction)) {
|
|
try {
|
|
exports[target](args);
|
|
result = true;
|
|
} catch (e) {
|
|
console.error("Exception of", target, e.message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
throw new AsyncFunction.TaskDone("AsyncFunction completed");
|
|
};
|
|
AsyncFunction.TaskDone = function(message) {
|
|
this.name = "AsyncFunction.TaskDone";
|
|
this.message = message;
|
|
};
|
|
AsyncFunction.TaskDone.prototype = new Error();
|
|
AsyncFunction.TaskDone.prototype.constructor = AsyncFunction.TaskDone;
|
|
|
|
// [app] Transpiling ES6 generator functions #75
|
|
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;
|
|
|
|
/*
|
|
var a = new GeneratorFunction(function(_yield) {
|
|
_yield("a");
|
|
_yield("b");
|
|
_yield("c");
|
|
});
|
|
console.log(a.next().value);
|
|
console.log(a.next().value);
|
|
console.log(a.next().value);
|
|
*/
|
|
|
|
function StdStorage() {
|
|
var data = {};
|
|
var commit = function() {
|
|
this.length = Object.keys(data).length;
|
|
};
|
|
|
|
this.length = 0;
|
|
this.key = function(idx) {
|
|
var keyName = Object.keys(data)[idx];
|
|
return data[keyName];
|
|
};
|
|
this.setItem = function(keyName, keyValue) {
|
|
data[keyName] = keyValue;
|
|
commit();
|
|
};
|
|
this.getItem = function(keyName) {
|
|
return data[keyName];
|
|
};
|
|
this.removeItem = function(keyName) {
|
|
delete data[keyName];
|
|
commit();
|
|
};
|
|
this.clear = function() {
|
|
data = {};
|
|
commit();
|
|
};
|
|
}
|
|
|
|
/*
|
|
var a = new StdStorage();
|
|
a.setItem("a", "1");
|
|
console.log(a.getItem("a"));
|
|
*/
|
|
|
|
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;
|
|
|
|
exports.Event = StdEvent;
|
|
exports.EventTarget = StdEventTarget;
|
|
exports.Storage = StdStorage;
|
|
|
|
exports.alert = alert;
|
|
exports.confirm = confirm;
|
|
|
|
exports.VERSIONINFO = "Standard Library (std.js) version 0.8.3";
|
|
exports.AUTHOR = "abuse@catswords.net";
|
|
exports.global = global;
|
|
exports.require = global.require;
|