vladx 1.0.0
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/README.md +256 -0
- package/bin/cli.js +486 -0
- package/bin/vlad.js +539 -0
- package/bin/vladpm.js +710 -0
- package/bin/vladx.js +491 -0
- package/package.json +57 -0
- package/src/engine/jit-compiler.js +285 -0
- package/src/engine/vladx-engine.js +941 -0
- package/src/index.js +44 -0
- package/src/interpreter/interpreter.js +2114 -0
- package/src/lexer/lexer.js +658 -0
- package/src/lexer/optimized-lexer.js +106 -0
- package/src/lexer/regex-cache.js +83 -0
- package/src/parser/ast-nodes.js +472 -0
- package/src/parser/parser.js +1408 -0
- package/src/runtime/advanced-type-system.js +209 -0
- package/src/runtime/async-manager.js +252 -0
- package/src/runtime/builtins.js +143 -0
- package/src/runtime/bundler.js +422 -0
- package/src/runtime/cache-manager.js +126 -0
- package/src/runtime/data-structures.js +612 -0
- package/src/runtime/debugger.js +260 -0
- package/src/runtime/enhanced-module-system.js +196 -0
- package/src/runtime/environment-enhanced.js +272 -0
- package/src/runtime/environment.js +140 -0
- package/src/runtime/event-emitter.js +232 -0
- package/src/runtime/formatter.js +280 -0
- package/src/runtime/functional.js +359 -0
- package/src/runtime/io-operations.js +390 -0
- package/src/runtime/linter.js +374 -0
- package/src/runtime/logging.js +314 -0
- package/src/runtime/minifier.js +242 -0
- package/src/runtime/module-system.js +377 -0
- package/src/runtime/network-operations.js +373 -0
- package/src/runtime/profiler.js +295 -0
- package/src/runtime/repl.js +336 -0
- package/src/runtime/security-manager.js +244 -0
- package/src/runtime/source-map-generator.js +208 -0
- package/src/runtime/test-runner.js +394 -0
- package/src/runtime/transformer.js +277 -0
- package/src/runtime/type-system.js +244 -0
- package/src/runtime/vladx-object.js +250 -0
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IOOperations — Ввод/Вывод с поддержкой потоков
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createReadStream, createWriteStream, readFileSync, writeFileSync, existsSync, statSync, readdirSync } from 'fs';
|
|
6
|
+
import { join, basename, dirname, extname, resolve, normalize } from 'path';
|
|
7
|
+
|
|
8
|
+
export class IOOperations {
|
|
9
|
+
constructor(securityManager) {
|
|
10
|
+
this.securityManager = securityManager;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Чтение файла (streaming)
|
|
15
|
+
*/
|
|
16
|
+
async readFileStream(filePath, options = {}) {
|
|
17
|
+
if (this.securityManager) {
|
|
18
|
+
this.securityManager.checkPath(filePath);
|
|
19
|
+
this.securityManager.checkFileSize(filePath);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
const chunks = [];
|
|
24
|
+
const stream = createReadStream(filePath, {
|
|
25
|
+
encoding: options.encoding || 'utf8',
|
|
26
|
+
highWaterMark: options.highWaterMark || 64 * 1024
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
stream.on('data', (chunk) => chunks.push(chunk));
|
|
30
|
+
stream.on('end', () => resolve(chunks.join('')));
|
|
31
|
+
stream.on('error', reject);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Чтение файла (sync)
|
|
37
|
+
*/
|
|
38
|
+
readFile(filePath, options = {}) {
|
|
39
|
+
if (this.securityManager) {
|
|
40
|
+
this.securityManager.checkPath(filePath);
|
|
41
|
+
this.securityManager.checkFileSize(filePath);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return readFileSync(filePath, options.encoding || 'utf-8');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Запись файла (streaming)
|
|
49
|
+
*/
|
|
50
|
+
async writeFileStream(filePath, content, options = {}) {
|
|
51
|
+
if (this.securityManager) {
|
|
52
|
+
this.securityManager.checkPath(filePath);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
const stream = createWriteStream(filePath, {
|
|
57
|
+
encoding: options.encoding || 'utf8'
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
stream.on('finish', resolve);
|
|
61
|
+
stream.on('error', reject);
|
|
62
|
+
stream.write(content);
|
|
63
|
+
stream.end();
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Запись файла (sync)
|
|
69
|
+
*/
|
|
70
|
+
writeFile(filePath, content, options = {}) {
|
|
71
|
+
if (this.securityManager) {
|
|
72
|
+
this.securityManager.checkPath(filePath);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return writeFileSync(filePath, content, options.encoding || 'utf-8');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Проверка существования файла
|
|
80
|
+
*/
|
|
81
|
+
fileExists(filePath) {
|
|
82
|
+
if (this.securityManager) {
|
|
83
|
+
this.securityManager.checkPath(filePath);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return existsSync(filePath);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Получить информацию о файле
|
|
91
|
+
*/
|
|
92
|
+
getFileInfo(filePath) {
|
|
93
|
+
if (this.securityManager) {
|
|
94
|
+
this.securityManager.checkPath(filePath);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const stats = statSync(filePath);
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
size: stats.size,
|
|
101
|
+
created: stats.birthtime,
|
|
102
|
+
modified: stats.mtime,
|
|
103
|
+
accessed: stats.atime,
|
|
104
|
+
isFile: stats.isFile(),
|
|
105
|
+
isDirectory: stats.isDirectory(),
|
|
106
|
+
isSymbolicLink: stats.isSymbolicLink(),
|
|
107
|
+
mode: stats.mode,
|
|
108
|
+
uid: stats.uid,
|
|
109
|
+
gid: stats.gid
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Прочитать директорию
|
|
115
|
+
*/
|
|
116
|
+
readDirectory(dirPath, options = {}) {
|
|
117
|
+
if (this.securityManager) {
|
|
118
|
+
this.securityManager.checkPath(dirPath);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const files = readdirSync(dirPath, {
|
|
122
|
+
withFileTypes: options.withFileTypes || false
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (options.recursive) {
|
|
126
|
+
const result = [];
|
|
127
|
+
|
|
128
|
+
for (const file of files) {
|
|
129
|
+
const filePath = join(dirPath, file.name || file);
|
|
130
|
+
|
|
131
|
+
if (statSync(filePath).isDirectory()) {
|
|
132
|
+
const subDir = this.readDirectory(filePath, options);
|
|
133
|
+
result.push(...subDir.map(f => join(file.name || file, f)));
|
|
134
|
+
} else {
|
|
135
|
+
result.push(file.name || file);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return files;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Создать директорию
|
|
147
|
+
*/
|
|
148
|
+
createDirectory(dirPath, options = {}) {
|
|
149
|
+
if (this.securityManager) {
|
|
150
|
+
this.securityManager.checkPath(dirPath);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const fs = require('fs');
|
|
154
|
+
if (options.recursive) {
|
|
155
|
+
const parentDir = dirname(dirPath);
|
|
156
|
+
if (!existsSync(parentDir)) {
|
|
157
|
+
this.createDirectory(parentDir, options);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!existsSync(dirPath)) {
|
|
162
|
+
fs.mkdirSync(dirPath, { recursive: options.recursive });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Удалить файл
|
|
168
|
+
*/
|
|
169
|
+
deleteFile(filePath) {
|
|
170
|
+
if (this.securityManager) {
|
|
171
|
+
this.securityManager.checkPath(filePath);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const fs = require('fs');
|
|
175
|
+
fs.unlinkSync(filePath);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Удалить директорию
|
|
180
|
+
*/
|
|
181
|
+
deleteDirectory(dirPath, options = {}) {
|
|
182
|
+
if (this.securityManager) {
|
|
183
|
+
this.securityManager.checkPath(dirPath);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const fs = require('fs');
|
|
187
|
+
|
|
188
|
+
if (options.recursive) {
|
|
189
|
+
const files = this.readDirectory(dirPath);
|
|
190
|
+
for (const file of files) {
|
|
191
|
+
const filePath = join(dirPath, file);
|
|
192
|
+
const stats = statSync(filePath);
|
|
193
|
+
|
|
194
|
+
if (stats.isDirectory()) {
|
|
195
|
+
this.deleteDirectory(filePath, options);
|
|
196
|
+
} else {
|
|
197
|
+
fs.unlinkSync(filePath);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
fs.rmdirSync(dirPath);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Копировать файл
|
|
207
|
+
*/
|
|
208
|
+
copyFile(src, dest) {
|
|
209
|
+
if (this.securityManager) {
|
|
210
|
+
this.securityManager.checkPath(src);
|
|
211
|
+
this.securityManager.checkPath(dest);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const fs = require('fs');
|
|
215
|
+
fs.copyFileSync(src, dest);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Переместить файл
|
|
220
|
+
*/
|
|
221
|
+
moveFile(src, dest) {
|
|
222
|
+
if (this.securityManager) {
|
|
223
|
+
this.securityManager.checkPath(src);
|
|
224
|
+
this.securityManager.checkPath(dest);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const fs = require('fs');
|
|
228
|
+
fs.renameSync(src, dest);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Смотреть за изменениями файла (watch)
|
|
233
|
+
*/
|
|
234
|
+
watchFile(filePath, callback, options = {}) {
|
|
235
|
+
if (this.securityManager) {
|
|
236
|
+
this.securityManager.checkPath(filePath);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const fs = require('fs');
|
|
240
|
+
|
|
241
|
+
const watcher = fs.watch(filePath, options, (eventType, filename) => {
|
|
242
|
+
callback({
|
|
243
|
+
event: eventType,
|
|
244
|
+
filename: filename,
|
|
245
|
+
path: filePath
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
close: () => watcher.close()
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Смотреть за изменениями директории
|
|
256
|
+
*/
|
|
257
|
+
watchDirectory(dirPath, callback, options = {}) {
|
|
258
|
+
if (this.securityManager) {
|
|
259
|
+
this.securityManager.checkPath(dirPath);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const fs = require('fs');
|
|
263
|
+
|
|
264
|
+
const watcher = fs.watch(dirPath, options, (eventType, filename) => {
|
|
265
|
+
callback({
|
|
266
|
+
event: eventType,
|
|
267
|
+
filename: filename,
|
|
268
|
+
path: dirPath
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
close: () => watcher.close()
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Поиск файлов по паттерну
|
|
279
|
+
*/
|
|
280
|
+
findFiles(dirPath, pattern, options = {}) {
|
|
281
|
+
const results = [];
|
|
282
|
+
const files = this.readDirectory(dirPath, { recursive: true });
|
|
283
|
+
|
|
284
|
+
for (const file of files) {
|
|
285
|
+
const filePath = join(dirPath, file);
|
|
286
|
+
|
|
287
|
+
if (pattern instanceof RegExp) {
|
|
288
|
+
if (pattern.test(file)) {
|
|
289
|
+
results.push(filePath);
|
|
290
|
+
}
|
|
291
|
+
} else if (typeof pattern === 'string') {
|
|
292
|
+
if (file.includes(pattern)) {
|
|
293
|
+
results.push(filePath);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return results;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Поиск файлов по расширению
|
|
303
|
+
*/
|
|
304
|
+
findByExtension(dirPath, extension, options = {}) {
|
|
305
|
+
return this.findFiles(dirPath, new RegExp(`\\.${extension}$`), options);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Получить размер директории
|
|
310
|
+
*/
|
|
311
|
+
getDirectorySize(dirPath) {
|
|
312
|
+
if (this.securityManager) {
|
|
313
|
+
this.securityManager.checkPath(dirPath);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
let totalSize = 0;
|
|
317
|
+
const files = this.readDirectory(dirPath, { recursive: true });
|
|
318
|
+
|
|
319
|
+
for (const file of files) {
|
|
320
|
+
const filePath = join(dirPath, file);
|
|
321
|
+
totalSize += statSync(filePath).size;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return totalSize;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Получить MIME тип файла
|
|
329
|
+
*/
|
|
330
|
+
getMimeType(filePath) {
|
|
331
|
+
const ext = extname(filePath).toLowerCase();
|
|
332
|
+
|
|
333
|
+
const mimeTypes = {
|
|
334
|
+
'.txt': 'text/plain',
|
|
335
|
+
'.json': 'application/json',
|
|
336
|
+
'.xml': 'application/xml',
|
|
337
|
+
'.html': 'text/html',
|
|
338
|
+
'.css': 'text/css',
|
|
339
|
+
'.js': 'application/javascript',
|
|
340
|
+
'.vx': 'text/plain',
|
|
341
|
+
'.pdf': 'application/pdf',
|
|
342
|
+
'.zip': 'application/zip',
|
|
343
|
+
'.png': 'image/png',
|
|
344
|
+
'.jpg': 'image/jpeg',
|
|
345
|
+
'.jpeg': 'image/jpeg',
|
|
346
|
+
'.gif': 'image/gif',
|
|
347
|
+
'.svg': 'image/svg+xml'
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
return mimeTypes[ext] || 'application/octet-stream';
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Создать символическую ссылку
|
|
355
|
+
*/
|
|
356
|
+
createSymlink(target, linkPath) {
|
|
357
|
+
if (this.securityManager) {
|
|
358
|
+
this.securityManager.checkPath(target);
|
|
359
|
+
this.securityManager.checkPath(linkPath);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const fs = require('fs');
|
|
363
|
+
fs.symlinkSync(target, linkPath);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Прочитать символическую ссылку
|
|
368
|
+
*/
|
|
369
|
+
readSymlink(linkPath) {
|
|
370
|
+
if (this.securityManager) {
|
|
371
|
+
this.securityManager.checkPath(linkPath);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const fs = require('fs');
|
|
375
|
+
return fs.readlinkSync(linkPath);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Проверить, является ли путь символической ссылкой
|
|
380
|
+
*/
|
|
381
|
+
isSymlink(path) {
|
|
382
|
+
if (this.securityManager) {
|
|
383
|
+
this.securityManager.checkPath(path);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return statSync(path).isSymbolicLink();
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export default IOOperations;
|