IgdrasilJavaScriptScripting - JavaScript для Igdrasil Engine
IgdrasilJavaScriptScripting — это реализация системы скриптинга на основе JavaScript через библиотеку ClearScript V8. Предоставляет полную поддержку современного JavaScript (ES6+) для Igdrasil Engine.
Основные возможности
✅ Современный JavaScript (ES6+)
✅ Интеграция через ClearScript V8
✅ Поддержка ES6 модулей (import/export)
✅ Поддержка Promise и async/await
✅ Модульная система
✅ Асинхронное выполнение скриптов
✅ Компиляция скриптов для повторного использования
✅ Двусторонняя передача данных между C# и JavaScript
✅ Поддержка C# классов и перечислений в JavaScript
✅ Встроенная отладка через Chrome DevTools
Быстрый старт
using IgdrasilEngine.Engine.Scripting.JS;
// Создать движок
var engine = new JavaScriptEngine("MyGame");
// Выполнить скрипт
var result = engine.Evaluate("2 + 2");
Console.WriteLine(result); // 4
// Работа с переменными
engine.SetValue("playerHealth", 100);
var health = engine.GetValue<int>("playerHealth");
Архитектура
IgdrasilJavaScriptScripting
├── JavaScriptEngine - Основной движок скриптов
├── JavaScriptExecutable - Скомпилированный JS-скрипт
├── JavaScriptModuleInterface - Регистрация функций/классов
└── PropertyBagTree - Дерево объектов для модулей
Конструкторы JavaScriptEngine
// Базовый
var engine = new JavaScriptEngine("MyGame");
// С ограничениями ресурсов
var constraints = new V8RuntimeConstraints
{
MaxNewSpaceSize = 16,
MaxOldSpaceSize = 512
};
var engine = new JavaScriptEngine("MyGame", constraints);
// С флагами
var flags = V8ScriptEngineFlags.EnableDebugging |
V8ScriptEngineFlags.EnableRemoteDebugging;
var engine = new JavaScriptEngine("MyGame", flags, debugPort: 9222);
// Полный контроль
var engine = new JavaScriptEngine("MyGame", constraints, flags, debugPort: 9222);
Отладка
// Включить отладку на порту 9222
var engine = new JavaScriptEngine(
"MyGame",
V8ScriptEngineFlags.EnableDebugging | V8ScriptEngineFlags.EnableRemoteDebugging,
debugPort: 9222
);
// Проверить, включена ли отладка
if (engine.IsDebug)
{
Console.WriteLine("Откройте chrome://inspect в Chrome");
}
Chrome DevTools
- Запустите движок с отладкой
- Откройте Chrome и перейдите на
chrome://inspect - Найдите ваш процесс в списке Remote Target
- Нажмите "inspect" для открытия DevTools
Возвращаемые значения
JavaScript возвращает одно значение, поэтому все методы возвращают object:
// Примитивы
var num = engine.Evaluate("42");
var str = engine.Evaluate("'hello'");
var flag = engine.Evaluate("true");
// Объекты и массивы
var obj = engine.Evaluate("({ x: 10, y: 20 })");
var arr = engine.Evaluate("[1, 2, 3]");
// Приведение типов
var number = engine.GetValue<int>("myNumber");
var text = engine.GetValue<string>("myString");
Типы данных
C# → JavaScript
| C# | JavaScript |
|---|---|
int, long, float, double |
number |
string |
string |
bool |
boolean |
null |
null |
Dictionary<,> |
Object |
List<>, Array |
Array |
| C# класс | Object (host object) |
Delegate, Action, Func |
function |
JavaScript → C#
// Числа
var num = engine.GetValue<double>("myNumber");
// Строки
var str = engine.GetValue<string>("myString");
// Булевы значения
var flag = engine.GetValue<bool>("myFlag");
// Объекты
var obj = engine.GetValue<dynamic>("myObject");
Console.WriteLine(obj.property);
// Массивы
var arr = engine.GetValue<object[]>("myArray");
ES6 Модули
Регистрация модуля
public class MathModule : Module<JavaScriptModuleInterface>
{
public override string Name => "mymath";
public override void Initialize(JavaScriptModuleInterface moduleInterface)
{
moduleInterface.RegisterFunction("square", (double x) => x * x);
moduleInterface.RegisterValue("PI", Math.PI);
}
}
// Использование
engine.RegisterModule(new MathModule());
Использование в JavaScript
import mymath from 'mymath';
console.log(mymath.square(5)); // 25
console.log(mymath.PI); // 3.14159...
// Деструктуризация
import { square, PI } from 'mymath';
console.log(square(5));
Современный JavaScript
Arrow Functions
const double = x => x * 2;
const add = (a, b) => a + b;
console.log(double(5)); // 10
console.log(add(3, 7)); // 10
Template Literals
const name = 'Player';
const level = 10;
const message = `${name} reached level ${level}!`;
console.log(message);
Destructuring
const player = { name: 'Hero', health: 100, mana: 50 };
const { name, health } = player;
const items = ['sword', 'shield', 'potion'];
const [weapon, armor] = items;
Spread Operator
const base = { health: 100, mana: 50 };
const player = { ...base, name: 'Hero', level: 10 };
const numbers = [1, 2, 3];
const all = [...numbers, 4, 5, 6];
Classes
class Player {
constructor(name, health) {
this.name = name;
this.health = health;
}
attack(target) {
console.log(`${this.name} attacks ${target}`);
}
}
const player = new Player('Hero', 100);
player.attack('Dragon');
Async/Await
async function loadData() {
const response = await fetch('data.json');
const data = await response.json();
return data;
}
loadData().then(data => console.log(data));
Компиляция скриптов
// Скомпилировать скрипт
var script = engine.Compile("x * x");
// Установить параметры
script.SetValue("x", 5);
// Выполнить много раз
for (int i = 0; i < 1000; i++)
{
script.SetValue("x", i);
var result = script.Evaluate();
Console.WriteLine(result);
}
Обработка ошибок
using IgdrasilEngine.Engine.Scripting.Exceptions;
try
{
engine.Execute("invalid javascript code");
}
catch (ScriptCompilationException ex)
{
Console.WriteLine($"Синтаксическая ошибка: {ex.Message}");
Console.WriteLine($"Строка: {ex.LineNumber}");
}
try
{
engine.Execute("throw new Error('Something went wrong')");
}
catch (ScriptExecutionException ex)
{
Console.WriteLine($"Ошибка выполнения: {ex.Message}");
Console.WriteLine($"Stack Trace:\n{engine.StackTrace}");
}
Работа с Promise
// Создание Promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('Done!'), 1000);
});
promise.then(result => console.log(result));
// Async/Await
async function asyncOperation() {
try {
const result = await promise;
console.log(result);
} catch (error) {
console.error(error);
}
}
Интеграция C# классов
public class Player
{
public string Name { get; set; }
public int Health { get; set; }
public void Attack(string target)
{
Console.WriteLine($"{Name} attacks {target}");
}
}
var module = new Module<JavaScriptModuleInterface>
{
Name = "game",
Initialize = mi =>
{
mi.RegisterClass("Player", typeof(Player));
mi.RegisterFunction("createPlayer", (string name, int health) =>
new Player { Name = name, Health = health });
}
};
engine.RegisterModule(module);
В JavaScript:
import { Player, createPlayer } from 'game';
const player = createPlayer("Hero", 100);
player.Name = "Super Hero";
player.Attack("Dragon");
console.log(player.Health);
Global Object
Доступ к глобальному объекту JavaScript:
// Установить глобальную функцию
engine.Global.myFunction = new Action<string>(msg => Console.WriteLine(msg));
// Установить глобальный объект
engine.Global.config = new { debug = true, version = "1.0" };
// Получить значение
var debug = engine.Global.config.debug;
DocumentSettings
// Настройка доступа к файлам
engine.DocumentSettings.AccessFlags = DocumentAccessFlags.EnableAllLoading;
engine.DocumentSettings.SearchPath = "./scripts;./modules";
// Загрузка внешних скриптов
engine.Execute(new DocumentInfo { Category = ModuleCategory.Standard },
"import utils from 'utils.js'");
Производительность
Рекомендации
- Компилируйте часто используемые скрипты - избегайте повторной компиляции
- Используйте const/let вместо var - лучше для оптимизации V8
- Кешируйте обращения к host objects - они дороже обычных объектов
- Используйте TypedArray для больших массивов чисел
Ограничения ресурсов
var constraints = new V8RuntimeConstraints
{
MaxNewSpaceSize = 16, // MB для нового поколения
MaxOldSpaceSize = 512, // MB для старого поколения
MaxExecutableSize = 128 // MB для исполняемого кода
};
var engine = new JavaScriptEngine("MyGame", constraints);
Безопасность
Ограничение доступа к файлам
engine.DocumentSettings.AccessFlags = DocumentAccessFlags.None; // Запретить загрузку файлов
Таймауты выполнения
// Установить лимит CPU
engine.CpuProfileSampleInterval = 1; // ms
// Прервать долгое выполнение
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
await engine.EvaluateAsync("while(true) {}", cts.Token);
Ограничения
- Worker threads: Не поддерживаются
- WebAssembly: Не поддерживается
- Некоторые Web APIs: Отсутствуют (fetch, XMLHttpRequest, DOM)
- Node.js modules: Требуют отдельной реализации
Ссылки
- ClearScript Documentation
- V8 JavaScript Engine
- ECMAScript 6 Features
- IgdrasilScripting Documentation
Проект: Igdrasil Engine
Автор: Alexander Izmailov
Собственность: Igdrasil Project
Версия: 1.0
Лицензия: Proprietary License
© 2026 Alexander Izmailov. Все права защищены.
Этот программный продукт является собственностью студии Igdrasil Project.