permet l'ajout des frameworks et des routes

This commit is contained in:
22107988t
2023-09-25 09:41:55 +02:00
parent 0b9f7d4dfb
commit 361112699c
2787 changed files with 864804 additions and 0 deletions

610
app/node_modules/cejs/data/code/thread.js generated vendored Normal file
View File

@@ -0,0 +1,610 @@
/**
* @name CeL function for thread
* @fileoverview 本檔案包含了 thread / process 流程控制的 functions。
* @since 2012/2/3 19:13:49
*/
'use strict';
// 'use asm';
// --------------------------------------------------------------------------------------------
// 不採用 if 陳述式,可以避免 Eclipse JSDoc 與 format 多縮排一層。
typeof CeL === 'function' && CeL.run({
name : 'data.code.thread',
require : 'data.code.compatibility.',
// 設定不匯出的子函式。
// 完全不 export 至 library_namespace.
no_extend : '*',
// 為了方便格式化程式碼,因此將 module 函式主體另外抽出。
code : module_code
});
function module_code(library_namespace) {
/**
* null module constructor
*
* @class thread 的 functions
*/
var _// JSDT:_module_
= function() {
// null module constructor
};
/**
* for JSDT: 有 prototype 才會將之當作 Class
*/
_// JSDT:_module_
.prototype = {
// constructor : _
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------//
var
/**
* const, 不可能為 setTimeout() id.
*/
is_running = [ 'is running' ],
/**
* const, 紀錄 process hook。
*/
Serial_execute_process = {},
/**
* const, Serial_execute core data 中,可被變更的值。
*/
Serial_execute_allow_to_set = {
interval : '{Integer}設定執行之週期間隔(ms)',
thread : '{Function}設定每次 loop 所欲執行之執行緒 (handler thread)。',
// 傳給 handler thread 之 this 與 arguments。
'this' : '在各 thread 間當作 this 傳遞的 data. "this" argument send to thread.',
argument : 'argument : 傳給 handler 之 arguments',
// loop 序號控制。單純輸入數字相當於 {start : 1, length : 自然數序號}
index : '{Integer}index : process to 哪一序號',
start : '{Integer}start from 哪一序號(index)',
// length, last 二選一。
length : '{Integer}執行 length 次',
last : '{Integer}執行至哪一序號(end index)',
// 設定流程控制用 signals。
stopped : '{Boolean}process stopped',
finished : '{Boolean}process finished',
terminated : '{Boolean}process terminated',
// 設定當 handler 產生錯誤時是否繼續執行下去。Or stop on throw error of thread.
skip_throw : '{Boolean}skip throw of thread'
};
/**
* 設定循序執行(serial execution) 程序,並可以作 stop, resume 等流程控制 (inter-process
* communication)。<br />
* 本函數可代替迴圈操作 loop, for, setTimeout / setInterval亦可避免長時間之迴圈操作被 browser
* 判別為耗時 loop 而 hang 住。<br />
* 可視作一種 iterator / forEach()。<br />
* This module use asynchronous method (e.g., setTimeout) to avoid the
* "Script Taking Too Long" message.
*
* TODO:<br />
* .result[], .next() = .step(), input array as option
*
* <code>
// 單 thread
var i=0,s=0;for(;i<100;i++)s+=Math.random();alert(s);
CeL.run('data.code.thread');
// 方法1
new CeL.Serial_execute(function(i, d) {d.s+=Math.random();}, {length: 100, first: function(d) {d.s=0;}, final: function(i, d) {alert(d.s);}});
// 方法2
new CeL.Serial_execute(function() {this.s+=Math.random();}, {length: 100, first: function() {this.s=0;}, final: function() {alert(this.s);}});
* </code>
*
* @param {Function}loop_thread
* loop_thread({Integer}process_to_index) {<br />
* return<br />
* 'SIGABRT': terminated (accident occurred), won't run
* options.final();<br />
* others(!0): all done<br /> }
*
* @param {Object}[options]
* 設定選項。<br /> {<br />
* {String}id : process id (有設定 id 則可以從
* Serial_execute.process(id) 控制。),<br />
* <br />
* {Integer}start : start from 哪一序號(index),<br />
* {Integer}index : process to 哪一序號,<br /> // length, last 二選一。<br />
* {Integer}length : 執行 length 次,<br />
* {Integer}last : 執行至哪一序號(end index),<br />
* <br />
* argument : 傳給 handler 之 arguments,<br />
* {Integer}interval : 週期間隔(ms),<br />
* {Function}first : run first,<br />
* {Function}final : run after all, 結尾, epilogue.<br />
* {Boolean}skip_throw : skip throw of thread(),<br /> }
*
* @returns {Serial_execute}process handler
*
* @constructor
*
* @see http://wiki.ecmascript.org/doku.php?id=strawman:async_functions
* http://support.mozilla.org/en-US/kb/warning-unresponsive-script
* http://support.microsoft.com/kb/175500
*
* @since 2012/2/3 18:38:02 初成。<br />
* 2012/2/4 12:31:53 包裝成物件。<br />
* 2012/11/16 19:30:53 re-write start。<br />
* 2012/11/23 23:51:44 re-write finished。<br />
* 2013/3/3 19:20:52 重新定義 options.length。<br />
*/
function Serial_execute(loop_thread, options) {
if (typeof loop_thread !== 'function')
return;
var tmp,
// (private) 行程間核心 data.
core_data = {
start_time : new Date,
// interval : 0,
thread : loop_thread,
skip_throw : false,
count : 0
};
// public interface.
// 處理初始化必要,且不允許被 loop_thread 改變的 methods/設定/狀態值.
this.get = function(name) {
if (name in core_data)
return core_data[name];
};
this.set = function(name, value) {
if (name in Serial_execute_allow_to_set) {
if (arguments.length > 1)
return core_data[name] = value;
else
delete core_data[name];
}
};
if (library_namespace.is_digits(options))
// 當作執行次數。
options = {
length : options
};
if (Array.isArray(options))
// 當作 Array.prototype.forEach()
options = {
list : options
};
// 處理 options 中與執行相關,且不允許被 loop_thread 改變的設定。
if (library_namespace.is_Object(options)) {
// 將 options 之 digits 設定 copy 到 core_data。
library_namespace.set_method(core_data, options, [ function(key) {
return !library_namespace.is_digits(options[key]);
}, 'start', 'last', 'index', 'interval' ]);
if (false)
library_namespace.extend(
[ 'start', 'last', 'index', 'interval' ], core_data,
options, function(i, v) {
return !library_namespace.is_digits(v);
});
if (!('last' in core_data) && options.length > 0) {
if (!library_namespace.is_digits(core_data.start))
core_data.start = 1;
core_data.last = core_data.start + options.length - 1;
}
// 從這邊起,.last 表示結束之序號。
// 將 options 之 digits 設定 copy 到 core_data。
library_namespace.set_method(core_data, options, [ 'skip_throw',
'final', 'this' ]);
if (false)
library_namespace.extend([ 'skip_throw', 'final', 'this' ],
core_data, options);
if ('argument' in options)
core_data.argument = Array.isArray(tmp = options.argument) ? tmp
: [ tmp ];
// data list.
if ('list' in options)
try {
// check if list is an array-like object, we can use []
// operator and .length.
var last = options.list.length - 1, test = options.list[last];
if (!library_namespace.is_digits(last))
// 確認 test 會被演算。
throw '' + test;
// 這邊不作 Array.prototype.slice.call(),讓 caller 可再作更動。
// 若希望保留 constcaller 需要自己作 Array.prototype.slice.call()。
core_data.list = options.list;
if (!library_namespace.is_digits(options.start))
// 若尚未設定 .start則定為 0。
core_data.start = 0;
if (!library_namespace.is_digits(core_data.last))
core_data.last = last;
// add an item to list.
this.add = function(item) {
// 為確保為 generic method不用 .push()!
core_data.list[++core_data.last] = item;
};
// 取得/設定當前 index。
this.index = function(index) {
if (library_namespace.is_digits(index))
core_data.index = index;
else
return core_data.index;
};
} catch (e) {
if (library_namespace.is_Object(options.list)) {
// TODO
}
}
if (options.record) {
// 執行結果將會依序置於此 Array。
core_data.result = [];
}
// 登記 process id.
if (tmp = options.id) {
if (tmp in Serial_execute_process)
library_namespace.debug('已有相同 id (' + tmp
+ ') 之 process 執行中!');
else
// 作個登記。
Serial_execute_process[core_data.id = tmp] = this;
}
} else
// 還是給予個預設值,省略判斷,簡化流程。
options = {};
// 外包裹執行緒: 可寫在 prototype 中。
this.package_thread = Serial_execute_package_thread.bind(this,
core_data);
// 既然首尾都設定了,自動設定 index。
if (!library_namespace.is_digits(core_data.index)
&& library_namespace.is_digits(core_data.start)
&& library_namespace.is_digits(core_data.last))
// start from 哪一序號。
core_data.index = core_data.start;
// 必須先執行之程序。
tmp = options.first;
if (typeof tmp === 'function')
if (core_data.argument)
tmp.apply(core_data['this'] || this, core_data.argument);
else
tmp.call(core_data['this'] || this, core_data);
// 預設自動開始執行。
if (!('autostart' in options) || options.autostart)
setTimeout(this.package_thread, 0);
}
/**
* 取得指定 id 之控制程序。
*/
Serial_execute.process = function(id) {
if (id in Serial_execute_process)
return Serial_execute_process[id];
};
/**
* signal 定義。
*
* @see <a href="http://en.wikipedia.org/wiki/Unix_signal"
* accessdate="2012/2/4 15:35">Unix signal</a>
*/
Serial_execute.signal = {
// running : 0,
STOP : 1,
// 結束程序。
FINISH : 2,
// abort
TERMINATE : 3
};
/**
* Serial_execute controller.
*
* @param signal
* @param result
* @returns {Serial_execute_controller}
*/
function Serial_execute_controller(signal, result) {
this.signal = signal;
if (arguments.length > 1)
this.result = result;
}
Serial_execute.controller = Serial_execute_controller;
// private: 預設外包裹執行緒。iterator.
function Serial_execute_package_thread(data, force) {
if (data.stopped) {
library_namespace.debug('執行緒已被中止。欲執行請先解除暫停設置。', 1,
'Serial_execute_package_thread');
return;
}
if (data.timer_id !== undefined) {
if (data.timer_id === is_running) {
library_namespace.debug('執行緒正執行中,忽略本次執行要求。', 1,
'Serial_execute_package_thread');
return;
}
clearTimeout(data.timer_id);
}
// lock
data.timer_id = is_running;
var result, list = data.list, to_terminate = data.terminated, argument_array,
// 設定是否已結束。
to_finish = to_terminate || data.finished || data.index > data.last,
// debug 用
id_tag = 'process [' + data.id + '] @ ' + data.index + ' / '
+ data.start + '-' + data.last;
if (!to_finish) {
// 已執行幾次。在 thread 中為從 1而非從 0 開始!
data.count++;
library_namespace.debug('實際執行 loop thread()。', 2,
'Serial_execute_package_thread');
if (list)
list = [ list[data.index], data.index, list ];
if (data.argument) {
// data.argument 應為 Array。
argument_array = data.argument;
if (list)
// 不動到原先的 data.argument。
// 將 data.argument 當作最前面的 arguments之後才填入 list 的部分。
argument_array = argument_array.concat(list);
} else if (list)
// 當作 Array.prototype.forEach()
argument_array = list;
try {
result = argument_array ?
//
data.thread.apply(data['this'] || this, argument_array) :
//
data.thread.call(data['this'] || this, data.index, data.count);
library_namespace.debug('loop thread() 程序執行完畢。', 2,
'Serial_execute_package_thread');
if (data.result)
data.result.push(result);
} catch (e) {
if (e.constructor === Serial_execute_controller) {
// signal cache
var signal = Serial_execute.signal;
switch (e.signal) {
case signal.STOP:
library_namespace.debug('Stop ' + id_tag, 1,
'Serial_execute_package_thread');
data.stopped = true;
break;
case signal.TERMINATE:
library_namespace.debug('Terminate ' + id_tag, 1,
'Serial_execute_package_thread');
to_terminate = true;
// terminate 的同時,也設定 to_finish。
case signal.FINISH:
to_finish = true;
break;
default:
// ignore others.
break;
}
result = e.result;
if (data.result)
data.result.push(result);
} else {
library_namespace.warn(id_tag + ' failed.');
library_namespace.error(e);
if (!data.skip_throw)
data.stopped = true;
}
}
}
data.index++;
if (to_finish) {
library_namespace.debug('執行收尾/收拾工作。', 1,
'Serial_execute_package_thread');
if (!to_terminate && typeof data['final'] === 'function')
try {
argument_array = [ data.result || data.count ];
data['final'].apply(data['this'] || this,
data.argument ? data.argument
.concat(argument_array) : argument_array);
} catch (e) {
library_namespace.error(e);
}
if (data.id in Serial_execute_process)
delete Serial_execute_process[data.id];
data.stopped = data.finished = true;
// TODO: delete all elements in this.
} else if (data.stopped)
delete data.timer_id;
else {
data.timer_id = setTimeout(this.package_thread, data.interval | 0);
}
return result;
}
;
library_namespace.set_method(Serial_execute.prototype, {
// 行程控制。
// run, continue, resume
start : function() {
this.set('stopped', false);
library_namespace.debug('Resume [' + this.get('id') + ']');
return this.package_thread();
},
// pause. 中止/停止執行緒。
stop : function() {
this.set('stopped', true);
},
// next one, step, moveNext.
next : function() {
var result = this.start();
this.stop();
return result;
},
// set position = start.
rewind : function() {
this.set('index', this.get('start') || 0);
},
// 結束程序。
finish : function() {
// gettext_config:{"id":"finished"}
this.set('finished', true);
this.set('stopped', false);
// return this.package_thread();
},
// abort (abnormal termination), remove.
terminate : function() {
this.set('terminated', true);
this.set('stopped', false);
// return this.package_thread();
},
// -----------------------------------------------------------------------------------------------------
// status / property
// 每隔多少 ms 執行一次。
interval : function(interval_ms) {
if (library_namespace.is_digits(interval_ms))
this.set('interval', interval_ms);
},
finished : function() {
// gettext_config:{"id":"finished"}
return this.get('finished');
},
stopped : function() {
return this.get('stopped');
},
argument : function() {
if (arguments.length)
this.set('argument', arguments.length > 1
//
? Array.prototype.slice.call(arguments)
//
: Array.isArray(argument) ? argument : [ argument ]);
return this.get('argument');
},
length : function() {
return this.get('length');
}
});
_.Serial_execute = Serial_execute;
/**
* <code>
// testing for data.code.thread
// adding 0 to 100.
CeL.run('data.code.thread', function() {
if (typeof runCode === 'object')
runCode.setR = 0;
p = new CeL.Serial_execute(function(i) {
CeL.debug(this.sum += i);
}, {
// id : 't',
interval : 800,
length : 100,
first : function() {
this.sum = 0;
CeL.log('Setuped.');
},
final : function(i) {
CeL.log('Done @ ' + i);
}
});
// p.stop();
});
// p.next();
// p.terminate();
// CeL.log(p);
// adding 0 to 100.
CeL.Serial_execute(function(data) {
data[1] += ++data[0];
CeL.debug(data[0]);
}, {
argument : [[ 0, 0 ]],
length : 100,
final : function(data) {
CeL.log('done @ ' + data[0] + ' : ' + data[1]);
}
});
// run 100 times: 0~99.
new CeL.Serial_execute(function(i) {
CeL.log(i + ': ' + (this.s = (this.s || 0) + i));
}, 100);
new CeL.Serial_execute(function(i) {
this.s = (this.s || 0) + i;
if (i === 100) {
CeL.log(i + ':' + this.s);
this.finish();
}
});
// 當作 Array.prototype.forEach()
CeL.run('data.code.thread');
new CeL.Serial_execute(function(item, index) {
CeL.log(item);
}, [2, 1, 3, 6]);
</code>
*/
// ----------------------------------------------------------------------------------------------------------------------------------------------------------//
return (_// JSDT:_module_
);
}