@makano/rew 1.1.2 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/ui +0 -0
- package/build.sh +6 -0
- package/cpp/ui.cpp +217 -0
- package/cpp/ui1.cpp +101 -0
- package/cpp/ui2.cpp +105 -0
- package/lib/rew/cli/cli.js +75 -3
- package/lib/rew/cli/utils.js +10 -9
- package/lib/rew/const/opt.js +2 -1
- package/lib/rew/functions/exec.js +27 -0
- package/lib/rew/functions/export.js +23 -5
- package/lib/rew/functions/fs.js +7 -2
- package/lib/rew/functions/import.js +28 -19
- package/lib/rew/functions/types.js +19 -3
- package/lib/rew/html/ui.js +12 -2
- package/lib/rew/modules/compiler.js +190 -1
- package/lib/rew/modules/context.js +41 -15
- package/lib/rew/modules/runtime.js +5 -1
- package/lib/rew/pkgs/modules/threads/worker.js +1 -1
- package/lib/rew/pkgs/modules/ui/classes.js +7 -1
- package/lib/rew/pkgs/threads.js +5 -1
- package/lib/rew/pkgs/ui.js +24 -24
- package/package.json +6 -1
@@ -14,17 +14,18 @@ const lookUpInOtherApps = (fullPath) => {
|
|
14
14
|
const name = fullPath.indexOf('/') ? fullPath.split('/')[0] : fullPath;
|
15
15
|
let dpath = fullPath.indexOf('/') ? fullPath.split('/')[1] : '';
|
16
16
|
let ppath = path.join(con.CONFIG_PATH, name, 'app');
|
17
|
-
if(!existsSync(ppath)) return null;
|
18
|
-
if(!dpath){
|
17
|
+
if (!existsSync(ppath)) return null;
|
18
|
+
if (!dpath) {
|
19
19
|
dpath = jsYaml.load(readFileSync(path.join(ppath, 'app.yaml'), 'utf-8')).entry;
|
20
20
|
}
|
21
21
|
ppath = path.join(ppath, dpath);
|
22
|
-
if(existsSync(ppath)) return ppath;
|
22
|
+
if (existsSync(ppath)) return ppath;
|
23
23
|
else return null;
|
24
24
|
}
|
25
25
|
|
26
26
|
module.exports.imp = function (runPath, context) {
|
27
27
|
return function (filename, options = {}) {
|
28
|
+
if (!options) options = {};
|
28
29
|
let type = options.type || "coffee";
|
29
30
|
let exports,
|
30
31
|
ispkg = findPackage(filename);
|
@@ -35,24 +36,24 @@ module.exports.imp = function (runPath, context) {
|
|
35
36
|
|
36
37
|
const lookUp = () => {
|
37
38
|
const otherPath = lookUpInOtherApps(filename);
|
38
|
-
if(!otherPath) throw new Error('Module "'+filename+'" not found');
|
39
|
+
if (!otherPath) throw new Error('Module "' + filename + '" not found');
|
39
40
|
else filepath = otherPath;
|
40
41
|
}
|
41
42
|
|
42
43
|
const foundCache = cachedFiles.find(f => f.filepath == filepath);
|
43
44
|
|
44
|
-
if(!ispkg && foundCache){
|
45
|
+
if (!ispkg && foundCache) {
|
45
46
|
exports = foundCache.exports;
|
46
47
|
}
|
47
48
|
|
48
|
-
if(!ispkg && !existsSync(filepath)){
|
49
|
-
if(Array.isArray(execOptions.resolveExtensions) && execOptions.resolveExtensions.length){
|
50
|
-
const resolve = execOptions.resolveExtensions.find(ext => typeof ext == "string" ? existsSync(filepath+ext) : existsSync(filepath+(ext.ext || '')));
|
51
|
-
if(resolve) {
|
49
|
+
if (!ispkg && !existsSync(filepath)) {
|
50
|
+
if (Array.isArray(execOptions.resolveExtensions) && execOptions.resolveExtensions.length) {
|
51
|
+
const resolve = execOptions.resolveExtensions.find(ext => typeof ext == "string" ? existsSync(filepath + ext) : existsSync(filepath + (ext.ext || '')));
|
52
|
+
if (resolve) {
|
52
53
|
filepath += typeof resolve == "string" ? resolve : resolve.ext;
|
53
|
-
if(typeof resolve == "object" && resolve.options){
|
54
|
-
if(resolve.options.type) type = resolve.options.type;
|
55
|
-
for(let i in resolve.options) options[i] = resolve.options[i];
|
54
|
+
if (typeof resolve == "object" && resolve.options) {
|
55
|
+
if (resolve.options.type) type = resolve.options.type;
|
56
|
+
for (let i in resolve.options) options[i] = resolve.options[i];
|
56
57
|
}
|
57
58
|
} else lookUp();
|
58
59
|
} else lookUp();
|
@@ -60,16 +61,24 @@ module.exports.imp = function (runPath, context) {
|
|
60
61
|
|
61
62
|
const exec = (coptions = {}) => runPath(
|
62
63
|
filepath,
|
63
|
-
{
|
64
|
-
|
64
|
+
{
|
65
|
+
import: options,
|
66
|
+
main: false,
|
67
|
+
useContext: execOptions.sharedContext == false ? false : !(options.context && options.context == 'new'),
|
68
|
+
...coptions,
|
69
|
+
as: options.as == 'main' ? context.module.main ? 'main' : 'parent' : options.as == 'parent' ? 'parent' : 'child',
|
70
|
+
fromMain: context.module.main
|
71
|
+
},
|
72
|
+
execOptions.sharedContext == false ? {} :
|
73
|
+
options.context && options.context == 'new' ? {} : context,
|
65
74
|
).context.module.exports;
|
66
75
|
|
67
76
|
if (ispkg) {
|
68
77
|
exports = getPackage(filename)(context);
|
69
|
-
} else if(foundCache) {
|
70
|
-
|
78
|
+
} else if (foundCache) {
|
79
|
+
|
71
80
|
} else if (type == "coffee") {
|
72
|
-
exports = exec({
|
81
|
+
exports = exec({});
|
73
82
|
} else if (type == "js") {
|
74
83
|
exports = exec({ compile: false });
|
75
84
|
} else if (type == "yaml" || type == "json" || type == "text") {
|
@@ -95,8 +104,8 @@ module.exports.imp = function (runPath, context) {
|
|
95
104
|
}
|
96
105
|
}
|
97
106
|
|
98
|
-
if(!ispkg) context.module.imports.push(filepath);
|
99
|
-
if(!ispkg) cachedFiles.push({ filepath, exports });
|
107
|
+
if (!ispkg) context.module.imports.push(filepath);
|
108
|
+
if (!ispkg) cachedFiles.push({ filepath, exports });
|
100
109
|
|
101
110
|
return exports;
|
102
111
|
};
|
@@ -15,17 +15,21 @@ function getType(value){
|
|
15
15
|
return typeof value === 'object' ? Array.isArray(value) ? 'array' : typeof value : typeof value;
|
16
16
|
}
|
17
17
|
|
18
|
-
function typedef(value) {
|
18
|
+
function typedef(value, strict = false) {
|
19
19
|
return {
|
20
|
+
strict,
|
20
21
|
defaultValue: value,
|
21
22
|
class: typeof value == 'function' ? value : typeof value === 'object' && value !== null && !Array.isArray(value) ? value.constructor : _defaultConstructors[getType(value)],
|
22
23
|
type: getType(value),
|
23
24
|
isConstucted: typeof value === 'object' && value !== null && !Array.isArray(value),
|
24
|
-
isEmpty: typeof value == "object" ? !Object.keys(value).length : typeof value == "string" ? value == "" :
|
25
|
+
isEmpty: typeof value == "object" ? !Object.keys(value).length : typeof value == "string" ? value == "" : typeof value !== "function"
|
25
26
|
};
|
26
27
|
}
|
27
28
|
|
28
29
|
function typeis(obj, typeDef) {
|
30
|
+
// Resolve Type
|
31
|
+
if(typeof typeDef == "function" && typeDef.type) typeDef = typeDef.type;
|
32
|
+
|
29
33
|
if (typeDef.isConstucted && typeDef.class && !(obj instanceof typeDef.class)) {
|
30
34
|
return false;
|
31
35
|
}
|
@@ -41,7 +45,9 @@ function typeis(obj, typeDef) {
|
|
41
45
|
if(!typeDef.isEmpty) {
|
42
46
|
if(typeDef.type == 'object'){
|
43
47
|
for (const key in typeDef.defaultValue) {
|
44
|
-
|
48
|
+
let propTypeDef = typeDef.defaultValue[key];
|
49
|
+
// Resolve type
|
50
|
+
if(typeof propTypeDef == "function" && propTypeDef.type) propTypeDef = propTypeDef.type;
|
45
51
|
|
46
52
|
if (typeof propTypeDef === 'object') {
|
47
53
|
if (!typeis(obj[key], propTypeDef)) {
|
@@ -51,8 +57,13 @@ function typeis(obj, typeDef) {
|
|
51
57
|
return false;
|
52
58
|
}
|
53
59
|
}
|
60
|
+
if(typeDef.strict) {
|
61
|
+
if(Object.keys(obj).some(key => !Object.keys(typeDef.defaultValue).includes(key))) return false;
|
62
|
+
}
|
54
63
|
} else if(typeDef.type == 'string'){
|
55
64
|
return typeDef.defaultValue == obj;
|
65
|
+
} else if(typeDef.type == 'function'){
|
66
|
+
return typeDef.defaultValue == obj;
|
56
67
|
}
|
57
68
|
}
|
58
69
|
|
@@ -70,24 +81,29 @@ function typei(child, parent) {
|
|
70
81
|
function int(str){
|
71
82
|
return parseInt(str);
|
72
83
|
}
|
84
|
+
int.type = typedef(1)
|
73
85
|
|
74
86
|
function float(str){
|
75
87
|
return parseFloat(str);
|
76
88
|
}
|
89
|
+
float.type = typedef(1.0)
|
77
90
|
|
78
91
|
function num(str){
|
79
92
|
return Number(str);
|
80
93
|
}
|
94
|
+
num.type = typedef(1)
|
81
95
|
|
82
96
|
function str(str){
|
83
97
|
return str ? str.toString() : "";
|
84
98
|
}
|
99
|
+
str.type = typedef('')
|
85
100
|
|
86
101
|
function bool(value){
|
87
102
|
return typeof value == 'string' ? (
|
88
103
|
value == 'true' ? true : false
|
89
104
|
) : value !== null && value !== undefined;
|
90
105
|
}
|
106
|
+
bool.type = typedef(true)
|
91
107
|
|
92
108
|
module.exports = {
|
93
109
|
typex,
|
package/lib/rew/html/ui.js
CHANGED
@@ -189,10 +189,20 @@ window.recieveMessage = (data) => {
|
|
189
189
|
} catch (e) {
|
190
190
|
log(e.toString());
|
191
191
|
}
|
192
|
-
}
|
192
|
+
} else if(edata.action == 'message') {
|
193
|
+
window.dispatchEvent(new CustomEvent('message', {
|
194
|
+
detail: edata.data
|
195
|
+
}));
|
196
|
+
}
|
193
197
|
};
|
194
198
|
|
195
199
|
window.addEventListener('load', () => {
|
196
|
-
window.exec(
|
200
|
+
window.exec({
|
201
|
+
...window.execContext,
|
202
|
+
window,
|
203
|
+
log,
|
204
|
+
send: (data) => sendData({ action: 'message', data }),
|
205
|
+
onRecieve: (cb) => window.addEventListener('message', (e) => cb(e.detail || {}))
|
206
|
+
});
|
197
207
|
log('SETUP::READY');
|
198
208
|
});
|
@@ -1,8 +1,197 @@
|
|
1
1
|
const { compile } = require("../../coffeescript/coffeescript");
|
2
|
+
const { execOptions } = require("../const/opt");
|
2
3
|
const { getFile } = require("./fs");
|
4
|
+
const babel = require('@babel/core');
|
5
|
+
const babelReact = require('@babel/preset-react');
|
6
|
+
|
7
|
+
function tokenizeCoffeeScript(code) {
|
8
|
+
const tokens = [];
|
9
|
+
let currentToken = '';
|
10
|
+
|
11
|
+
for (let i = 0; i < code.length; i++) {
|
12
|
+
const char = code[i];
|
13
|
+
const nextChar = code[i + 1];
|
14
|
+
|
15
|
+
if (char === '#') {
|
16
|
+
// Comment
|
17
|
+
tokens.push({ type: 'COMMENT', value: char + code.substring(i + 1).split('\n')[0]+'\n' });
|
18
|
+
i = code.indexOf('\n', i);
|
19
|
+
} else if (char === '"' || char === "'") {
|
20
|
+
// String
|
21
|
+
let string = char;
|
22
|
+
let escaped = false;
|
23
|
+
i++;
|
24
|
+
while (i < code.length && (code[i] !== char || escaped)) {
|
25
|
+
string += code[i];
|
26
|
+
if (code[i] === '\\' && !escaped) {
|
27
|
+
escaped = true;
|
28
|
+
} else {
|
29
|
+
escaped = false;
|
30
|
+
}
|
31
|
+
i++;
|
32
|
+
}
|
33
|
+
string += char; // Include closing quote
|
34
|
+
tokens.push({ type: 'STRING', value: string });
|
35
|
+
} else if (char === '/' && (nextChar === '/' || nextChar === '*')) {
|
36
|
+
// Regular expression
|
37
|
+
let regex = char;
|
38
|
+
i++;
|
39
|
+
while (i < code.length && (code[i] !== '/' || regex.endsWith('\\'))) {
|
40
|
+
regex += code[i];
|
41
|
+
i++;
|
42
|
+
}
|
43
|
+
regex += '/';
|
44
|
+
tokens.push({ type: 'REGEX', value: regex });
|
45
|
+
} else if (/\s/.test(char)) {
|
46
|
+
// Whitespace
|
47
|
+
if(tokens[tokens.length-1]?.type == 'WHITESPACE'
|
48
|
+
&& tokens[tokens.length-1].value[0] == char
|
49
|
+
){
|
50
|
+
tokens[tokens.length-1].value += char;
|
51
|
+
} else {
|
52
|
+
tokens.push({ type: 'WHITESPACE', value: char });
|
53
|
+
}
|
54
|
+
} else if (/[a-zA-Z_$]/.test(char)) {
|
55
|
+
// Identifier
|
56
|
+
let identifier = char;
|
57
|
+
i++;
|
58
|
+
while (i < code.length && /[a-zA-Z0-9_$]/.test(code[i])) {
|
59
|
+
identifier += code[i];
|
60
|
+
i++;
|
61
|
+
}
|
62
|
+
tokens.push({ type: 'IDENTIFIER', value: identifier });
|
63
|
+
i--; // Move back one character to recheck
|
64
|
+
} else {
|
65
|
+
// Other characters
|
66
|
+
tokens.push({ type: 'OTHER', value: char });
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
return tokens;
|
71
|
+
}
|
72
|
+
|
73
|
+
const gnextToken = (i, n, tokens) => {
|
74
|
+
return tokens[i + n] ? tokens[i + n].type == 'WHITESPACE' ? gnextToken(i, n + 1, tokens) : { nextToken: tokens[i + n], n } : null;
|
75
|
+
}
|
76
|
+
|
77
|
+
const fnextToken = (i, tokens, type, value) => {
|
78
|
+
return tokens.map((t, ind) => { t.ti = ind; return t }).slice(i, tokens.length - 1).map((t, ind) => { t.ri = ind; t.index = ind - i; return t }).find(t => t.type == type && (value ? t.value == value : true));
|
79
|
+
}
|
80
|
+
|
81
|
+
function compileRewStuff(content, options) {
|
82
|
+
const tokens = tokenizeCoffeeScript(content);
|
83
|
+
let result = '';
|
84
|
+
|
85
|
+
let hooks = [];
|
86
|
+
|
87
|
+
for (let i = 0; i < tokens.length; i++) {
|
88
|
+
const token = tokens[i];
|
89
|
+
let { nextToken, n } = gnextToken(i, 1, tokens) || {};
|
90
|
+
|
91
|
+
if (token.type === 'IDENTIFIER' && token.value === 'opt') {
|
92
|
+
const { nextToken: nextNextToken } = gnextToken(i, 2, tokens) || {};
|
93
|
+
if(nextNextToken && nextNextToken.value == 'jsxPragma'){
|
94
|
+
const { nextToken: nextLastToken } = gnextToken(i, 5, tokens) || {};
|
95
|
+
execOptions.jsxPragma = nextLastToken.value.slice(1).slice(0, -1);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
if (token.type === 'COMMENT' && token.value.slice(1).trim() === '@jsx') {
|
100
|
+
options.jsx = true;
|
101
|
+
}
|
102
|
+
|
103
|
+
if (token.type === 'IDENTIFIER' && token.value === 'import') {
|
104
|
+
// console.log(nextToken.type);
|
105
|
+
let ind = i + n + 2;
|
106
|
+
|
107
|
+
let defaultName;
|
108
|
+
if (nextToken.type === 'STRING') {
|
109
|
+
result += `inc ${nextToken.value}`;
|
110
|
+
i += n;
|
111
|
+
} else if (nextToken.value === '{') {
|
112
|
+
const closingBraceToken = fnextToken(ind, tokens, 'OTHER', '}');
|
113
|
+
const nameToken = fnextToken(ind, tokens, 'STRING');
|
114
|
+
if (closingBraceToken) {
|
115
|
+
const exportsTokens = tokens.slice(ind, closingBraceToken.ti);
|
116
|
+
const exports = exportsTokens.filter(t => t.type === 'IDENTIFIER').map(t => t.value).join(', ');
|
117
|
+
result += `{ ${exports} } = inc ${nameToken.value}`;
|
118
|
+
i = nameToken.ti;
|
119
|
+
}
|
120
|
+
} else if (nextToken.value === '*') {
|
121
|
+
const asToken = fnextToken(ind, tokens, 'IDENTIFIER', 'as');
|
122
|
+
const nameToken = fnextToken(asToken.ri, tokens, 'STRING');
|
123
|
+
if (asToken) {
|
124
|
+
const nextToken = fnextToken(asToken.ti + 1, tokens, 'IDENTIFIER');
|
125
|
+
defaultName = nextToken.value;
|
126
|
+
result += `${defaultName} = inc ${nameToken.value}`;
|
127
|
+
i = ind + 6;
|
128
|
+
}
|
129
|
+
} else if(nextToken) {
|
130
|
+
const nameToken = fnextToken(ind, tokens, 'STRING');
|
131
|
+
defaultName = nextToken.value;
|
132
|
+
let { nextToken: nextNextToken, n: n2 } = gnextToken(i + 2, 1, tokens) || {};
|
133
|
+
if(nextNextToken?.type == 'OTHER' && nextNextToken?.value == ','){
|
134
|
+
const closingBraceToken = fnextToken(ind, tokens, 'OTHER', '}');
|
135
|
+
if(closingBraceToken){
|
136
|
+
const exportsTokens = tokens.slice(ind, closingBraceToken.ti);
|
137
|
+
const exports = exportsTokens.filter(t => t.type === 'IDENTIFIER').map(t => t.value).join(', ');
|
138
|
+
result += `{ default: ${defaultName}, ${exports} } = inc ${nameToken?.value || ""}`;
|
139
|
+
i = closingBraceToken.ti + 4;
|
140
|
+
}
|
141
|
+
} else {
|
142
|
+
result += `{ default: ${defaultName} } = inc ${nameToken?.value || ""}`;
|
143
|
+
i = ind + 2;
|
144
|
+
}
|
145
|
+
|
146
|
+
}
|
147
|
+
|
148
|
+
const nextLastToken = fnextToken(i, tokens, 'IDENTIFIER');
|
149
|
+
|
150
|
+
if(nextLastToken?.value == 'assert'){
|
151
|
+
result += ', ';
|
152
|
+
i += 3;
|
153
|
+
}
|
154
|
+
|
155
|
+
continue;
|
156
|
+
}
|
157
|
+
|
158
|
+
|
159
|
+
if (token.type === 'IDENTIFIER' && token.value === 'pub' &&
|
160
|
+
nextToken && nextToken.type === 'IDENTIFIER' &&
|
161
|
+
nextToken.value && nextToken.value !== 'undefined') {
|
162
|
+
|
163
|
+
hooks.push({
|
164
|
+
index: i + 1,
|
165
|
+
value: `"${nextToken.value}", `
|
166
|
+
});
|
167
|
+
}
|
168
|
+
|
169
|
+
result += token.value;
|
170
|
+
if (hooks.length) {
|
171
|
+
hooks.forEach((hook, ind) => {
|
172
|
+
if (i == hook.index) {
|
173
|
+
result += hook.value;
|
174
|
+
hooks.splice(ind, 1);
|
175
|
+
}
|
176
|
+
});
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
// console.log(result)
|
181
|
+
|
182
|
+
return result;
|
183
|
+
}
|
184
|
+
|
3
185
|
|
4
186
|
const cpl = (module.exports.compile = function (file, options = {}) {
|
5
|
-
|
187
|
+
let c = compile(compileRewStuff(file.content, options), { ...options, filename: file.path, bare: false, inlineMap: false });
|
188
|
+
if(options.jsx) {
|
189
|
+
c = babel.transformSync(c, {
|
190
|
+
presets: [[babelReact, { pragma: execOptions.jsxPragma }]],
|
191
|
+
plugins: []
|
192
|
+
}).code;
|
193
|
+
}
|
194
|
+
return c;
|
6
195
|
});
|
7
196
|
|
8
197
|
module.exports.compileFile = function (filepath, options = {}) {
|
@@ -1,37 +1,46 @@
|
|
1
1
|
const defaultContext = require("../const/default");
|
2
2
|
const { execOptions } = require("../const/opt");
|
3
3
|
const emitter = require("../functions/emitter");
|
4
|
-
const { exportsFunction } = require("../functions/export");
|
4
|
+
const { exportsFunction, pubFunction } = require("../functions/export");
|
5
5
|
const { imp } = require("../functions/import");
|
6
6
|
const { customRequire } = require("../functions/require");
|
7
7
|
const fsLib = require('../functions/fs');
|
8
8
|
const pathLib = require('../functions/path');
|
9
|
+
const execLib = require('../functions/exec');
|
9
10
|
|
11
|
+
let mainFile = "";
|
12
|
+
const isMainFile = filepath => filepath == mainFile;
|
10
13
|
module.exports.prepareContext = function (
|
11
14
|
custom_context,
|
12
15
|
options,
|
13
16
|
filepath = "",
|
14
17
|
runPath = () => {},
|
15
18
|
) {
|
19
|
+
if(mainFile == "") mainFile = filepath;
|
16
20
|
let context = {
|
17
21
|
module: {
|
18
22
|
exports: null,
|
19
|
-
options,
|
20
23
|
filepath,
|
24
|
+
main: isMainFile(filepath),
|
21
25
|
imports: []
|
22
26
|
},
|
23
|
-
|
27
|
+
imports: {
|
28
|
+
meta: {},
|
29
|
+
assert: options.import ?? {}
|
30
|
+
},
|
31
|
+
...fsLib(filepath),
|
24
32
|
};
|
25
33
|
if (options.useContext) {
|
26
34
|
context = {
|
27
|
-
...context,
|
28
35
|
...custom_context,
|
36
|
+
...context
|
29
37
|
};
|
30
38
|
} else {
|
31
39
|
context = {
|
32
40
|
...context,
|
33
41
|
...defaultContext,
|
34
42
|
...pathLib(filepath),
|
43
|
+
...execLib(filepath),
|
35
44
|
require: (package) => {
|
36
45
|
try {
|
37
46
|
return execOptions.nativeRequire || package.startsWith('node:') ? require(package.startsWith('node:') ? package.split('node:')[1] : package) : customRequire(package, filepath);
|
@@ -39,26 +48,43 @@ module.exports.prepareContext = function (
|
|
39
48
|
throw new Error("Module "+package+" not found");
|
40
49
|
}
|
41
50
|
},
|
42
|
-
opt: {
|
43
|
-
set: (key, value) => execOptions[key] = value,
|
44
|
-
get: (key) => execOptions[key],
|
45
|
-
push: (key, value) => execOptions[key]?.push(value),
|
46
|
-
pop: (key) => execOptions[key]?.pop()
|
47
|
-
},
|
48
51
|
...custom_context,
|
49
52
|
};
|
50
|
-
context.imp = imp(runPath, context);
|
51
|
-
context.exports = exportsFunction(context);
|
52
53
|
}
|
53
|
-
if (!context.global) context.global = context;
|
54
54
|
if (!context.process)
|
55
55
|
context.process = {
|
56
56
|
argv: process.argv,
|
57
|
-
target:
|
57
|
+
target: {
|
58
|
+
on: (event, listener) => process.on(event, listener),
|
59
|
+
off: (event, listener) => process.off(event, listener),
|
60
|
+
emit: (event, code) => process.emit(event, code)
|
61
|
+
},
|
58
62
|
env: process.env,
|
59
63
|
cwd: () => process.cwd(),
|
60
64
|
arch: process.arch
|
61
65
|
};
|
62
|
-
|
66
|
+
|
67
|
+
context.global = context;
|
68
|
+
context.imports.assert = options.import ?? {};
|
69
|
+
context.imp = imp(runPath, context);
|
70
|
+
context.inc = (package, asserts) => {
|
71
|
+
try{
|
72
|
+
if(package.startsWith('node:') || package.startsWith('pkg:')) throw new Error('');
|
73
|
+
return context.imp(package, asserts);
|
74
|
+
} catch(e) {
|
75
|
+
return context.require(package.startsWith('pkg:') ? package.split('pkg:')[1] : package);
|
76
|
+
}
|
77
|
+
};
|
78
|
+
context.pub = pubFunction(context);
|
79
|
+
context.exports = exportsFunction(context);
|
80
|
+
|
81
|
+
if(context.module.main || (options.fromMain == true && options.as == 'main')){
|
82
|
+
context.opt = {
|
83
|
+
set: (key, value) => execOptions[key] = value,
|
84
|
+
get: (key) => execOptions[key],
|
85
|
+
push: (key, value) => execOptions[key]?.push(value),
|
86
|
+
pop: (key) => execOptions[key]?.pop()
|
87
|
+
};
|
88
|
+
} else delete context.opt
|
63
89
|
return context;
|
64
90
|
};
|
@@ -3,7 +3,11 @@ const { compileFile } = require("./compiler");
|
|
3
3
|
const { prepareContext } = require("./context");
|
4
4
|
|
5
5
|
const exec = (module.exports.exec = function (code, context) {
|
6
|
-
return vm.runInNewContext(code, vm.createContext(context)
|
6
|
+
return vm.runInNewContext(code, vm.createContext(context), {
|
7
|
+
filename: context.module.filepath,
|
8
|
+
lineOffset: 0,
|
9
|
+
displayErrors: true
|
10
|
+
});
|
7
11
|
});
|
8
12
|
|
9
13
|
module.exports.runPath = function runPath(
|
@@ -22,7 +22,7 @@ parentPort.on('message', (data) => {
|
|
22
22
|
exec(`(${workerData.cb}).call({ process }, context)`, { print: (...a) => console.log(...a), process: {
|
23
23
|
on: (e, cb) => { target.on(e, cb) },
|
24
24
|
off: (e) => { target.off(e) },
|
25
|
-
emit: (e) => { parentPort.postMessage({ type: 'event', event: e, data }) },
|
25
|
+
emit: (e, data) => { parentPort.postMessage({ type: 'event', event: e, data }) },
|
26
26
|
exit: (code) => process.exit(code),
|
27
27
|
finish: (data) => {
|
28
28
|
parentPort.postMessage({ type: 'result', result: data });
|
@@ -161,11 +161,17 @@ module.exports.uiClasses = (context, options, send, recieve, hook, rmHook) => {
|
|
161
161
|
// }
|
162
162
|
// }, false);
|
163
163
|
|
164
|
+
const Transmitter = {
|
165
|
+
send: (data) => send({ action: 'message', data }),
|
166
|
+
recieve: (cb) => recieve((data) => cb(data.data))
|
167
|
+
}
|
168
|
+
|
164
169
|
return {
|
165
170
|
Widget: RewWidget,
|
166
171
|
Text: RewTextWidget,
|
167
172
|
WidgetOptions: RemWidgetOptions,
|
168
173
|
findElement,
|
169
|
-
StyleSheet: StyleSheet
|
174
|
+
StyleSheet: StyleSheet,
|
175
|
+
Transmitter
|
170
176
|
}
|
171
177
|
}
|
package/lib/rew/pkgs/threads.js
CHANGED
@@ -44,7 +44,10 @@ module.exports = (context) => ({
|
|
44
44
|
stop();
|
45
45
|
});
|
46
46
|
|
47
|
+
let exiting = false;
|
48
|
+
|
47
49
|
worker.on('exit', (code) => {
|
50
|
+
if(exiting) return;
|
48
51
|
stop();
|
49
52
|
if (code !== 0) {
|
50
53
|
throw new Error(`Worker stopped with exit code ${code}`);
|
@@ -57,7 +60,8 @@ module.exports = (context) => ({
|
|
57
60
|
on: (e, cb) => listener.on(e, cb),
|
58
61
|
off: (e, cb) => listener.off(e, cb),
|
59
62
|
emit: (e, data) => worker?.postMessage({ type: 'event', event: e, data }),
|
60
|
-
get: () => dataResult.wait()
|
63
|
+
get: () => dataResult.wait(),
|
64
|
+
stop: () => { exiting = true; stop(); }
|
61
65
|
};
|
62
66
|
}
|
63
67
|
};
|
package/lib/rew/pkgs/ui.js
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
const path = require("path");
|
2
2
|
const { spawn, exec } = require("child_process");
|
3
|
-
const WebSocket = require("ws");
|
4
|
-
const http = require("http");
|
5
3
|
const fs = require("fs");
|
6
4
|
const { uiClasses } = require("./modules/ui/classes");
|
7
5
|
const { generateRandomID } = require("../functions/id");
|
@@ -26,7 +24,7 @@ const defaultOptions = {
|
|
26
24
|
onExit: () => process.exit(),
|
27
25
|
style: '',
|
28
26
|
stylePath: THEME_PATH,
|
29
|
-
exec: () => {},
|
27
|
+
exec: () => { },
|
30
28
|
execContext: {}
|
31
29
|
};
|
32
30
|
|
@@ -44,18 +42,22 @@ module.exports = (context) => ({
|
|
44
42
|
|
45
43
|
options.runId = runId;
|
46
44
|
|
47
|
-
if(fs.existsSync(options.stylePath)) options.style = fs.readFileSync(options.stylePath, { encoding: 'utf-8' }) + '\n' + options.style;
|
45
|
+
if (fs.existsSync(options.stylePath)) options.style = fs.readFileSync(options.stylePath, { encoding: 'utf-8' }) + '\n' + options.style;
|
48
46
|
|
49
|
-
options.style = ' */\n'+options.style+'\n/* ';
|
47
|
+
options.style = ' */\n' + options.style + '\n/* ';
|
50
48
|
|
51
49
|
const HTML = replaceString(HTML_STRING, options);
|
52
50
|
const JS = replaceString(JS_STRING, options);
|
53
51
|
|
52
|
+
/**
|
53
|
+
* Queue for future writes
|
54
|
+
* @type {string[]}
|
55
|
+
* */
|
54
56
|
const queue = [];
|
55
57
|
|
56
58
|
const send = (data) => {
|
57
59
|
const content = fs.readFileSync(tmpFile, { encoding: 'utf-8' });
|
58
|
-
if(content) {
|
60
|
+
if (content) {
|
59
61
|
queue.push(data);
|
60
62
|
} else {
|
61
63
|
fs.writeFileSync(tmpFile, typeof data !== "string" ? JSON.stringify(data) : data);
|
@@ -77,20 +79,18 @@ module.exports = (context) => ({
|
|
77
79
|
output: process.stdout
|
78
80
|
});
|
79
81
|
|
80
|
-
rl.question('', () => {});
|
82
|
+
rl.question('', () => { });
|
81
83
|
|
82
84
|
fs.writeFileSync(tmpFile, '');
|
83
85
|
|
84
86
|
fs.watch(tmpFile, { encoding: 'utf-8' })
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
const p = spawn(BIN_PATH, [runId]);
|
87
|
+
.on('change', () => {
|
88
|
+
if (queue.length) {
|
89
|
+
send(queue.pop());
|
90
|
+
}
|
91
|
+
});
|
92
92
|
|
93
|
-
|
93
|
+
const p = spawn(options.bin || BIN_PATH, [runId]);
|
94
94
|
|
95
95
|
p.on("close", (code) => {
|
96
96
|
rl.close();
|
@@ -103,12 +103,12 @@ module.exports = (context) => ({
|
|
103
103
|
});
|
104
104
|
|
105
105
|
g_emitter.on('recieve', (edata) => {
|
106
|
-
if(edata.action.startsWith('hook:')){
|
106
|
+
if (edata.action.startsWith('hook:')) {
|
107
107
|
const hook = hookedSocketListeners[edata.data.rid];
|
108
108
|
const type = edata.action.split('hook:')[1];
|
109
|
-
if(hook && hook.type == type) {
|
109
|
+
if (hook && hook.type == type) {
|
110
110
|
hookedSocketListeners[edata.data.rid].cb(edata.data.object);
|
111
|
-
if(hook.once) delete hookedSocketListeners[edata.data.rid];
|
111
|
+
if (hook.once) delete hookedSocketListeners[edata.data.rid];
|
112
112
|
}
|
113
113
|
}
|
114
114
|
});
|
@@ -119,7 +119,7 @@ module.exports = (context) => ({
|
|
119
119
|
const d = data.toString().split("RESPONSE::")[1];
|
120
120
|
const jd = JSON.parse(d);
|
121
121
|
recieve(jd);
|
122
|
-
} else if(data.toString().trim().endsWith('SETUP::READY')) {
|
122
|
+
} else if (data.toString().trim().endsWith('SETUP::READY')) {
|
123
123
|
console.log('READY');
|
124
124
|
r(uiClasses(context, options, sendEvent, (cb) => {
|
125
125
|
g_emitter.on('recieve', cb);
|
@@ -128,15 +128,15 @@ module.exports = (context) => ({
|
|
128
128
|
}, (rid) => { // Remove hook
|
129
129
|
delete hookedSocketListeners[rid];
|
130
130
|
}));
|
131
|
-
} else if(data.toString().endsWith('SETUP::HTML')) {
|
132
|
-
send({action: 'JS2', data: JS, isSetup: true});
|
133
|
-
} else if(data.toString() == 'INIT::READY') {
|
134
|
-
send({action: 'HTML', data: HTML});
|
131
|
+
} else if (data.toString().endsWith('SETUP::HTML')) {
|
132
|
+
send({ action: 'JS2', data: JS, isSetup: true });
|
133
|
+
} else if (data.toString() == 'INIT::READY') {
|
134
|
+
send({ action: 'HTML', data: HTML });
|
135
135
|
} else {
|
136
136
|
console.log(data.toString());
|
137
137
|
}
|
138
138
|
});
|
139
|
-
|
139
|
+
|
140
140
|
p.stderr.on("data", (data) => {
|
141
141
|
console.error(data.toString());
|
142
142
|
});
|