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.
Files changed (42) hide show
  1. package/README.md +256 -0
  2. package/bin/cli.js +486 -0
  3. package/bin/vlad.js +539 -0
  4. package/bin/vladpm.js +710 -0
  5. package/bin/vladx.js +491 -0
  6. package/package.json +57 -0
  7. package/src/engine/jit-compiler.js +285 -0
  8. package/src/engine/vladx-engine.js +941 -0
  9. package/src/index.js +44 -0
  10. package/src/interpreter/interpreter.js +2114 -0
  11. package/src/lexer/lexer.js +658 -0
  12. package/src/lexer/optimized-lexer.js +106 -0
  13. package/src/lexer/regex-cache.js +83 -0
  14. package/src/parser/ast-nodes.js +472 -0
  15. package/src/parser/parser.js +1408 -0
  16. package/src/runtime/advanced-type-system.js +209 -0
  17. package/src/runtime/async-manager.js +252 -0
  18. package/src/runtime/builtins.js +143 -0
  19. package/src/runtime/bundler.js +422 -0
  20. package/src/runtime/cache-manager.js +126 -0
  21. package/src/runtime/data-structures.js +612 -0
  22. package/src/runtime/debugger.js +260 -0
  23. package/src/runtime/enhanced-module-system.js +196 -0
  24. package/src/runtime/environment-enhanced.js +272 -0
  25. package/src/runtime/environment.js +140 -0
  26. package/src/runtime/event-emitter.js +232 -0
  27. package/src/runtime/formatter.js +280 -0
  28. package/src/runtime/functional.js +359 -0
  29. package/src/runtime/io-operations.js +390 -0
  30. package/src/runtime/linter.js +374 -0
  31. package/src/runtime/logging.js +314 -0
  32. package/src/runtime/minifier.js +242 -0
  33. package/src/runtime/module-system.js +377 -0
  34. package/src/runtime/network-operations.js +373 -0
  35. package/src/runtime/profiler.js +295 -0
  36. package/src/runtime/repl.js +336 -0
  37. package/src/runtime/security-manager.js +244 -0
  38. package/src/runtime/source-map-generator.js +208 -0
  39. package/src/runtime/test-runner.js +394 -0
  40. package/src/runtime/transformer.js +277 -0
  41. package/src/runtime/type-system.js +244 -0
  42. package/src/runtime/vladx-object.js +250 -0
@@ -0,0 +1,373 @@
1
+ /**
2
+ * NetworkOperations — Сетевые операции
3
+ */
4
+
5
+ import https from 'https';
6
+ import http from 'http';
7
+ import { URL } from 'url';
8
+
9
+ export class NetworkOperations {
10
+ constructor(securityManager) {
11
+ this.securityManager = securityManager;
12
+ this.defaultOptions = {
13
+ timeout: 30000,
14
+ maxRedirects: 5,
15
+ headers: {
16
+ 'User-Agent': 'VladX/1.0'
17
+ }
18
+ };
19
+ }
20
+
21
+ /**
22
+ * HTTP GET запрос
23
+ */
24
+ async get(url, options = {}) {
25
+ return this.request(url, {
26
+ ...options,
27
+ method: 'GET'
28
+ });
29
+ }
30
+
31
+ /**
32
+ * HTTP POST запрос
33
+ */
34
+ async post(url, data, options = {}) {
35
+ return this.request(url, {
36
+ ...options,
37
+ method: 'POST',
38
+ body: data
39
+ });
40
+ }
41
+
42
+ /**
43
+ * HTTP PUT запрос
44
+ */
45
+ async put(url, data, options = {}) {
46
+ return this.request(url, {
47
+ ...options,
48
+ method: 'PUT',
49
+ body: data
50
+ });
51
+ }
52
+
53
+ /**
54
+ * HTTP DELETE запрос
55
+ */
56
+ async delete(url, options = {}) {
57
+ return this.request(url, {
58
+ ...options,
59
+ method: 'DELETE'
60
+ });
61
+ }
62
+
63
+ /**
64
+ * HTTP PATCH запрос
65
+ */
66
+ async patch(url, data, options = {}) {
67
+ return this.request(url, {
68
+ ...options,
69
+ method: 'PATCH',
70
+ body: data
71
+ });
72
+ }
73
+
74
+ /**
75
+ * Общий HTTP запрос
76
+ */
77
+ async request(url, options = {}) {
78
+ if (this.securityManager) {
79
+ this.securityManager.checkURL(url);
80
+ }
81
+
82
+ const mergedOptions = {
83
+ ...this.defaultOptions,
84
+ ...options
85
+ };
86
+
87
+ return new Promise((resolve, reject) => {
88
+ const urlObj = new URL(url);
89
+ const client = urlObj.protocol === 'https:' ? https : http;
90
+
91
+ const reqOptions = {
92
+ method: mergedOptions.method,
93
+ headers: {
94
+ ...mergedOptions.headers
95
+ },
96
+ timeout: mergedOptions.timeout
97
+ };
98
+
99
+ const req = client.request(url, reqOptions, (res) => {
100
+ let data = '';
101
+
102
+ res.on('data', (chunk) => {
103
+ data += chunk;
104
+ });
105
+
106
+ res.on('end', () => {
107
+ const response = {
108
+ status: res.statusCode,
109
+ statusText: res.statusMessage,
110
+ headers: res.headers,
111
+ data: this.parseResponse(data, res.headers['content-type'])
112
+ };
113
+
114
+ // Редиректы
115
+ if ([301, 302, 303, 307, 308].includes(res.statusCode) && res.headers.location) {
116
+ if (mergedOptions.maxRedirects > 0) {
117
+ this.request(res.headers.location, {
118
+ ...mergedOptions,
119
+ maxRedirects: mergedOptions.maxRedirects - 1
120
+ }).then(resolve).catch(reject);
121
+ return;
122
+ }
123
+ }
124
+
125
+ resolve(response);
126
+ });
127
+ });
128
+
129
+ req.on('error', reject);
130
+ req.on('timeout', () => {
131
+ req.destroy();
132
+ reject(new Error(`Request timeout: ${url}`));
133
+ });
134
+
135
+ if (mergedOptions.body) {
136
+ req.write(mergedOptions.body);
137
+ }
138
+
139
+ req.end();
140
+ });
141
+ }
142
+
143
+ /**
144
+ * Парсинг ответа
145
+ */
146
+ parseResponse(data, contentType) {
147
+ if (!contentType) return data;
148
+
149
+ if (contentType.includes('application/json')) {
150
+ try {
151
+ return JSON.parse(data);
152
+ } catch (e) {
153
+ return data;
154
+ }
155
+ }
156
+
157
+ return data;
158
+ }
159
+
160
+ /**
161
+ * Download файла
162
+ */
163
+ async downloadFile(url, destPath) {
164
+ if (this.securityManager) {
165
+ this.securityManager.checkURL(url);
166
+ this.securityManager.checkPath(destPath);
167
+ }
168
+
169
+ return new Promise((resolve, reject) => {
170
+ const urlObj = new URL(url);
171
+ const client = urlObj.protocol === 'https:' ? https : http;
172
+ const fs = require('fs');
173
+ const file = fs.createWriteStream(destPath);
174
+
175
+ client.get(url, (response) => {
176
+ response.pipe(file);
177
+
178
+ file.on('finish', () => {
179
+ file.close();
180
+ resolve(destPath);
181
+ });
182
+ }).on('error', (err) => {
183
+ fs.unlink(destPath, () => {});
184
+ reject(err);
185
+ });
186
+ });
187
+ }
188
+
189
+ /**
190
+ * Upload файла
191
+ */
192
+ async uploadFile(url, filePath, options = {}) {
193
+ if (this.securityManager) {
194
+ this.securityManager.checkURL(url);
195
+ this.securityManager.checkPath(filePath);
196
+ }
197
+
198
+ const fs = require('fs');
199
+ const formData = require('form-data');
200
+
201
+ const form = new FormData();
202
+ const stats = fs.statSync(filePath);
203
+
204
+ form.append('file', fs.createReadStream(filePath), {
205
+ filename: require('path').basename(filePath),
206
+ knownLength: stats.size
207
+ });
208
+
209
+ const formHeaders = form.getHeaders();
210
+
211
+ return this.request(url, {
212
+ ...options,
213
+ method: 'POST',
214
+ headers: {
215
+ ...options.headers,
216
+ ...formHeaders
217
+ },
218
+ body: form
219
+ });
220
+ }
221
+
222
+ /**
223
+ * WebSocket соединение
224
+ */
225
+ createWebSocket(url, options = {}) {
226
+ if (this.securityManager) {
227
+ this.securityManager.checkURL(url);
228
+ }
229
+
230
+ const WebSocket = require('ws');
231
+ return new WebSocket(url, options);
232
+ }
233
+
234
+ /**
235
+ * Создать HTTP сервер
236
+ */
237
+ createServer(port, handler, options = {}) {
238
+ const server = http.createServer((req, res) => {
239
+ // CORS
240
+ if (options.cors) {
241
+ res.setHeader('Access-Control-Allow-Origin', options.cors.origin || '*');
242
+ res.setHeader('Access-Control-Allow-Methods', options.cors.methods || 'GET, POST, PUT, DELETE');
243
+ res.setHeader('Access-Control-Allow-Headers', options.cors.headers || 'Content-Type');
244
+ }
245
+
246
+ // Logging
247
+ if (options.logging) {
248
+ console.log(`${req.method} ${req.url}`);
249
+ }
250
+
251
+ handler(req, res);
252
+ });
253
+
254
+ server.listen(port, () => {
255
+ console.log(`Server running on port ${port}`);
256
+ });
257
+
258
+ return server;
259
+ }
260
+
261
+ /**
262
+ * Создать HTTPS сервер
263
+ */
264
+ createHttpsServer(port, handler, options = {}) {
265
+ const server = https.createServer(options.credentials || {}, (req, res) => {
266
+ // CORS
267
+ if (options.cors) {
268
+ res.setHeader('Access-Control-Allow-Origin', options.cors.origin || '*');
269
+ res.setHeader('Access-Control-Allow-Methods', options.cors.methods || 'GET, POST, PUT, DELETE');
270
+ res.setHeader('Access-Control-Allow-Headers', options.cors.headers || 'Content-Type');
271
+ }
272
+
273
+ handler(req, res);
274
+ });
275
+
276
+ server.listen(port, () => {
277
+ console.log(`HTTPS Server running on port ${port}`);
278
+ });
279
+
280
+ return server;
281
+ }
282
+
283
+ /**
284
+ * Проверить доступность URL
285
+ */
286
+ async checkUrl(url) {
287
+ try {
288
+ const response = await this.head(url);
289
+ return response.status >= 200 && response.status < 400;
290
+ } catch (error) {
291
+ return false;
292
+ }
293
+ }
294
+
295
+ /**
296
+ * HEAD запрос
297
+ */
298
+ async head(url, options = {}) {
299
+ return this.request(url, {
300
+ ...options,
301
+ method: 'HEAD'
302
+ });
303
+ }
304
+
305
+ /**
306
+ * OPTIONS запрос
307
+ */
308
+ async options(url, options = {}) {
309
+ return this.request(url, {
310
+ ...options,
311
+ method: 'OPTIONS'
312
+ });
313
+ }
314
+
315
+ /**
316
+ * Отправить FormData
317
+ */
318
+ async sendForm(url, formData, options = {}) {
319
+ if (typeof formData === 'object') {
320
+ const form = new FormData();
321
+ for (const [key, value] of Object.entries(formData)) {
322
+ form.append(key, value);
323
+ }
324
+ formData = form;
325
+ }
326
+
327
+ const formHeaders = formData.getHeaders();
328
+
329
+ return this.request(url, {
330
+ ...options,
331
+ method: 'POST',
332
+ headers: {
333
+ ...options.headers,
334
+ ...formHeaders
335
+ },
336
+ body: formData
337
+ });
338
+ }
339
+
340
+ /**
341
+ * multipart/form-data
342
+ */
343
+ createMultipartForm() {
344
+ const boundary = `----VladX${Date.now()}`;
345
+ const parts = [];
346
+
347
+ return {
348
+ addField: (name, value) => {
349
+ parts.push(
350
+ `--${boundary}\r\n` +
351
+ `Content-Disposition: form-data; name="${name}"\r\n\r\n` +
352
+ `${value}\r\n`
353
+ );
354
+ },
355
+ addFile: (name, filename, content, contentType) => {
356
+ parts.push(
357
+ `--${boundary}\r\n` +
358
+ `Content-Disposition: form-data; name="${name}"; filename="${filename}"\r\n` +
359
+ `Content-Type: ${contentType || 'application/octet-stream'}\r\n\r\n` +
360
+ `${content}\r\n`
361
+ );
362
+ },
363
+ build: () => {
364
+ return parts.join('') + `--${boundary}--\r\n`;
365
+ },
366
+ getContentType: () => {
367
+ return `multipart/form-data; boundary=${boundary}`;
368
+ }
369
+ };
370
+ }
371
+ }
372
+
373
+ export default NetworkOperations;
@@ -0,0 +1,295 @@
1
+ /**
2
+ * Profiler — Профилировщик производительности
3
+ */
4
+
5
+ export class Profiler {
6
+ constructor() {
7
+ this.records = new Map();
8
+ this.callCounts = new Map();
9
+ this.currentCallStack = [];
10
+ this.startTime = null;
11
+ this.endTime = null;
12
+ this.memorySamples = [];
13
+ this.intervalId = null;
14
+ this.hotspots = new Map();
15
+ }
16
+
17
+ /**
18
+ * Начать профилирование
19
+ */
20
+ start(options = {}) {
21
+ this.records.clear();
22
+ this.callCounts.clear();
23
+ this.currentCallStack = [];
24
+ this.startTime = Date.now();
25
+ this.endTime = null;
26
+ this.memorySamples = [];
27
+ this.hotspots.clear();
28
+
29
+ if (options.sampleMemory) {
30
+ const sampleInterval = options.sampleInterval || 100;
31
+ this.intervalId = setInterval(() => {
32
+ this.memorySamples.push({
33
+ timestamp: Date.now(),
34
+ heapUsed: process.memoryUsage().heapUsed,
35
+ heapTotal: process.memoryUsage().heapTotal
36
+ });
37
+ }, sampleInterval);
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Завершить профилирование
43
+ */
44
+ stop() {
45
+ this.endTime = Date.now();
46
+
47
+ if (this.intervalId) {
48
+ clearInterval(this.intervalId);
49
+ this.intervalId = null;
50
+ }
51
+
52
+ return this.getResults();
53
+ }
54
+
55
+ /**
56
+ * Начать измерение функции
57
+ */
58
+ enterFunction(functionName, filename, line) {
59
+ const key = `${filename}:${functionName}`;
60
+
61
+ this.currentCallStack.push({
62
+ functionName,
63
+ filename,
64
+ line,
65
+ key,
66
+ startTime: Date.now()
67
+ });
68
+
69
+ this.callCounts.set(key, (this.callCounts.get(key) || 0) + 1);
70
+ }
71
+
72
+ /**
73
+ * Завершить измерение функции
74
+ */
75
+ exitFunction() {
76
+ if (this.currentCallStack.length === 0) {
77
+ return;
78
+ }
79
+
80
+ const frame = this.currentCallStack.pop();
81
+ const duration = Date.now() - frame.startTime;
82
+
83
+ if (!this.records.has(frame.key)) {
84
+ this.records.set(frame.key, {
85
+ functionName: frame.functionName,
86
+ filename: frame.filename,
87
+ totalTime: 0,
88
+ minTime: Infinity,
89
+ maxTime: 0,
90
+ avgTime: 0,
91
+ callCount: 0
92
+ });
93
+ }
94
+
95
+ const record = this.records.get(frame.key);
96
+ record.totalTime += duration;
97
+ record.minTime = Math.min(record.minTime, duration);
98
+ record.maxTime = Math.max(record.maxTime, duration);
99
+ record.callCount = this.callCounts.get(frame.key);
100
+ record.avgTime = record.totalTime / record.callCount;
101
+
102
+ // Обновляем hotspots
103
+ const hotspotKey = `${frame.filename}:${frame.line}`;
104
+ this.hotspots.set(hotspotKey, (this.hotspots.get(hotspotKey) || 0) + duration);
105
+ }
106
+
107
+ /**
108
+ * Получить результаты профилирования
109
+ */
110
+ getResults() {
111
+ const totalTime = this.endTime ? this.endTime - this.startTime : 0;
112
+
113
+ // Сортировка по total time
114
+ const sortedRecords = Array.from(this.records.values())
115
+ .sort((a, b) => b.totalTime - a.totalTime)
116
+ .map(record => ({
117
+ ...record,
118
+ percentage: totalTime > 0 ? ((record.totalTime / totalTime) * 100).toFixed(2) + '%' : '0%'
119
+ }));
120
+
121
+ // Сортировка hotspots
122
+ const sortedHotspots = Array.from(this.hotspots.entries())
123
+ .sort(([, a], [, b]) => b - a)
124
+ .slice(0, 10)
125
+ .map(([location, time]) => ({
126
+ location,
127
+ time,
128
+ percentage: totalTime > 0 ? ((time / totalTime) * 100).toFixed(2) + '%' : '0%'
129
+ }));
130
+
131
+ return {
132
+ summary: {
133
+ totalTime: totalTime + 'ms',
134
+ functionCount: this.records.size,
135
+ totalCalls: Array.from(this.callCounts.values()).reduce((a, b) => a + b, 0)
136
+ },
137
+ functions: sortedRecords,
138
+ hotspots: sortedHotspots,
139
+ memory: {
140
+ samples: this.memorySamples,
141
+ initial: this.memorySamples[0] || null,
142
+ final: this.memorySamples[this.memorySamples.length - 1] || null,
143
+ peak: this.memorySamples.reduce((max, sample) =>
144
+ sample.heapUsed > max.heapUsed ? sample : max,
145
+ { heapUsed: 0 }
146
+ )
147
+ }
148
+ };
149
+ }
150
+
151
+ /**
152
+ * Получить данные о функциях в формате flame graph
153
+ */
154
+ getFlameGraphData() {
155
+ return Array.from(this.records.values()).map(record => ({
156
+ name: `${record.functionName} (${record.filename})`,
157
+ value: record.totalTime,
158
+ children: []
159
+ }));
160
+ }
161
+
162
+ /**
163
+ * Экспорт результатов в JSON
164
+ */
165
+ exportJSON() {
166
+ return JSON.stringify(this.getResults(), null, 2);
167
+ }
168
+
169
+ /**
170
+ * Экспорт результатов в формате для Flamegraph
171
+ */
172
+ exportFlamegraph() {
173
+ const lines = [];
174
+
175
+ for (const [key, record] of this.records) {
176
+ lines.push(`${record.functionName} ${record.totalTime}`);
177
+ }
178
+
179
+ return lines.join('\n');
180
+ }
181
+
182
+ /**
183
+ * Получить статистику по памяти
184
+ */
185
+ getMemoryStats() {
186
+ if (this.memorySamples.length === 0) {
187
+ return null;
188
+ }
189
+
190
+ const samples = this.memorySamples.map(s => s.heapUsed);
191
+ const min = Math.min(...samples);
192
+ const max = Math.max(...samples);
193
+ const avg = samples.reduce((a, b) => a + b, 0) / samples.length;
194
+
195
+ return {
196
+ min,
197
+ max,
198
+ avg,
199
+ growth: this.memorySamples[this.memorySamples.length - 1].heapUsed - this.memorySamples[0].heapUsed,
200
+ samples: this.memorySamples
201
+ };
202
+ }
203
+
204
+ /**
205
+ * Найти функции с высокой задержкой
206
+ */
207
+ findSlowFunctions(threshold = 100) {
208
+ return Array.from(this.records.values())
209
+ .filter(record => record.avgTime > threshold)
210
+ .sort((a, b) => b.avgTime - a.avgTime);
211
+ }
212
+
213
+ /**
214
+ * Найти функции с большим количеством вызовов
215
+ */
216
+ findFrequentFunctions(threshold = 100) {
217
+ return Array.from(this.records.values())
218
+ .filter(record => record.callCount > threshold)
219
+ .sort((a, b) => b.callCount - a.callCount);
220
+ }
221
+
222
+ /**
223
+ * Сравнить два профиля
224
+ */
225
+ static compare(profile1, profile2) {
226
+ const results1 = profile1.getResults();
227
+ const results2 = profile2.getResults();
228
+
229
+ const comparison = {
230
+ totalTime: {
231
+ before: results1.summary.totalTime,
232
+ after: results2.summary.totalTime,
233
+ change: this.calculateChange(
234
+ parseInt(results1.summary.totalTime),
235
+ parseInt(results2.summary.totalTime)
236
+ )
237
+ },
238
+ functions: []
239
+ };
240
+
241
+ // Сравнение функций
242
+ const allFunctions = new Set([
243
+ ...results1.functions.map(f => f.functionName),
244
+ ...results2.functions.map(f => f.functionName)
245
+ ]);
246
+
247
+ for (const funcName of allFunctions) {
248
+ const func1 = results1.functions.find(f => f.functionName === funcName);
249
+ const func2 = results2.functions.find(f => f.functionName === funcName);
250
+
251
+ comparison.functions.push({
252
+ name: funcName,
253
+ before: func1 ? func1.totalTime : 0,
254
+ after: func2 ? func2.totalTime : 0,
255
+ change: this.calculateChange(
256
+ func1 ? func1.totalTime : 0,
257
+ func2 ? func2.totalTime : 0
258
+ )
259
+ });
260
+ }
261
+
262
+ comparison.functions.sort((a, b) => b.after - a.after);
263
+
264
+ return comparison;
265
+ }
266
+
267
+ /**
268
+ * Рассчитать изменение
269
+ */
270
+ static calculateChange(before, after) {
271
+ if (before === 0) return after > 0 ? '+∞' : '0%';
272
+ const change = ((after - before) / before * 100).toFixed(2);
273
+ return change > 0 ? `+${change}%` : `${change}%`;
274
+ }
275
+
276
+ /**
277
+ * Очистить данные
278
+ */
279
+ clear() {
280
+ this.records.clear();
281
+ this.callCounts.clear();
282
+ this.currentCallStack = [];
283
+ this.startTime = null;
284
+ this.endTime = null;
285
+ this.memorySamples = [];
286
+ this.hotspots.clear();
287
+
288
+ if (this.intervalId) {
289
+ clearInterval(this.intervalId);
290
+ this.intervalId = null;
291
+ }
292
+ }
293
+ }
294
+
295
+ export default Profiler;