Skip to content

Commit

Permalink
Merge branch 'dev' into rc
Browse files Browse the repository at this point in the history
  • Loading branch information
C0kkie committed Jul 23, 2023
2 parents 08d1180 + 27b64f1 commit fb9a45a
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 155 deletions.
43 changes: 37 additions & 6 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ jobs:
shell: bash
run: |
TAG=${GITHUB_REF/refs\/tags\//}
echo ::set-output name=BRANCH::${TAG/\/*}
echo ::set-output name=VERSION::${TAG/*\/}
echo "BRANCH=${TAG/\/*}" >> $GITHUB_OUTPUT
echo "VERSION=${TAG/*\/}" >> $GITHUB_OUTPUT
- name: Create release
id: create_release
Expand Down Expand Up @@ -130,19 +130,50 @@ jobs:
- name: Upload windows files to CDN
run: npx alt-upload dist-windows js-bytecode-module/$BRANCH/x64_win32 $VERSION
env:
CI_UPLOAD_URL: ${{ secrets.CI_UPLOAD_URL }}
CI_DEPLOY_TOKEN: ${{ secrets.CI_DEPLOY_TOKEN }}
AWS_KEY_ID: ${{ secrets.AWS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_BUCKET: ${{ secrets.AWS_BUCKET }}
AWS_ENDPOINT: ${{ secrets.AWS_ENDPOINT }}
CF_CACHE_PURGE_TOKEN: ${{ secrets.CF_CACHE_PURGE_TOKEN }}
CF_CACHE_ZONE_ID: ${{ secrets.CF_CACHE_ZONE_ID }}
CF_CACHE_PURGE_URL: ${{ secrets.CF_CACHE_PURGE_URL }}
BRANCH: ${{ steps.version.outputs.BRANCH }}
VERSION: ${{ steps.version.outputs.VERSION }}

- name: Upload linux files to CDN
run: npx alt-upload dist-linux js-bytecode-module/$BRANCH/x64_linux $VERSION
env:
CI_UPLOAD_URL: ${{ secrets.CI_UPLOAD_URL }}
CI_DEPLOY_TOKEN: ${{ secrets.CI_DEPLOY_TOKEN }}
AWS_KEY_ID: ${{ secrets.AWS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_BUCKET: ${{ secrets.AWS_BUCKET }}
AWS_ENDPOINT: ${{ secrets.AWS_ENDPOINT }}
CF_CACHE_PURGE_TOKEN: ${{ secrets.CF_CACHE_PURGE_TOKEN }}
CF_CACHE_ZONE_ID: ${{ secrets.CF_CACHE_ZONE_ID }}
CF_CACHE_PURGE_URL: ${{ secrets.CF_CACHE_PURGE_URL }}
BRANCH: ${{ steps.version.outputs.BRANCH }}
VERSION: ${{ steps.version.outputs.VERSION }}

build-docker:
name: Trigger Docker image build
runs-on: ubuntu-latest
needs: [deploy]
steps:
- name: Get Token
id: get_workflow_token
uses: peter-murray/workflow-application-token-action@v2
with:
application_id: ${{ secrets.CI_APP_ID }}
application_private_key: ${{ secrets.CI_APP_PRIVATE_KEY }}
permissions: "actions:write"
organization: altmp
- name: Trigger Docker build
uses: benc-uk/workflow-dispatch@v1
with:
workflow: build.yml
ref: main
repo: altmp/altv-docker
token: ${{ steps.get_workflow_token.outputs.token }}

delete-artifacts:
name: Delete artifacts
runs-on: ubuntu-20.04
Expand Down
291 changes: 145 additions & 146 deletions compiler/compiler.cpp
Original file line number Diff line number Diff line change
@@ -1,146 +1,145 @@
#include "compiler.h"
#include "helpers.h"

#include <algorithm>

using namespace BytecodeCompiler;

bool Compiler::CompileModule(const std::string& fileName, bool compileDependencies)
{
// Read the file
if(!package->FileExists(fileName))
{
logger->LogError("File not found: " + fileName);
return false;
}
size_t size = package->GetFileSize(fileName);
std::string sourceCode;
sourceCode.resize(size);
if(!package->ReadFile(fileName, sourceCode.data(), sourceCode.size()))
{
logger->LogError("Failed to read file: " + fileName);
return false;
}

v8::TryCatch tryCatch(isolate);
v8::Local<v8::Context> ctx = v8::Context::New(isolate);
v8::Context::Scope ctxScope(ctx);

// Compile the file to a JavaScript module
v8::ScriptOrigin origin(
isolate, v8::String::NewFromUtf8(isolate, fileName.c_str()).ToLocalChecked(), 0, 0, false, -1, v8::Local<v8::Value>(), false, false, true, v8::Local<v8::PrimitiveArray>());
v8::ScriptCompiler::Source source(v8::String::NewFromUtf8(isolate, sourceCode.c_str()).ToLocalChecked(), origin);
v8::MaybeLocal<v8::Module> maybeModule = v8::ScriptCompiler::CompileModule(isolate, &source);
if(maybeModule.IsEmpty() || tryCatch.HasCaught())
{
logger->LogError("Failed to compile module: " + fileName);
Helpers::CheckTryCatch(fileName, logger, tryCatch, ctx);
return false;
}

// Retrieve the bytecode from the module
v8::Local<v8::Module> module = maybeModule.ToLocalChecked();
v8::ScriptCompiler::CachedData* cache = v8::ScriptCompiler::CreateCodeCache(module->GetUnboundModuleScript());
if(cache == nullptr || tryCatch.HasCaught())
{
logger->LogError("Failed to create bytecode: " + fileName);
Helpers::CheckTryCatch(fileName, logger, tryCatch, ctx);
return false;
}

// Write the bytecode to file
std::vector<uint8_t> bytecodeResult = CreateBytecodeBuffer(cache->data, cache->length, sourceCode.size());
bool writeResult = package->WriteFile(fileName, (void*)bytecodeResult.data(), bytecodeResult.size());
if(!writeResult)
{
logger->LogError("Failed to write to file: " + fileName);
return false;
}

// Make sure the byte buffer is deleted with the cached data from V8
cache->buffer_policy = v8::ScriptCompiler::CachedData::BufferPolicy::BufferOwned;
delete cache;

logger->Log("Converted file to bytecode: " + logger->GetHighlightColor() + fileName);
compiledFiles.push_back(fileName);

// Compile all dependencies
if(compileDependencies)
{
v8::Local<v8::Context> ctx = v8::Context::New(isolate);
v8::Local<v8::FixedArray> dependencies = module->GetModuleRequests();
int length = dependencies->Length();
for(int i = 0; i < length; i++)
{
v8::Local<v8::Data> dep = dependencies->Get(ctx, i);
v8::Local<v8::ModuleRequest> request = dep.As<v8::ModuleRequest>();
// Ignore all imports with import assertions, as those are not loaded as
// normal JS files
if(request->GetImportAssertions()->Length() > 0) continue;

v8::Local<v8::String> depStr = request->GetSpecifier();
std::string depPath = *v8::String::Utf8Value(isolate, depStr);
// Ignore the built-in modules
if(std::find(ignoredModules.begin(), ignoredModules.end(), depPath) != ignoredModules.end()) continue;

// Compile the dependency file
std::string fullFileName = package->ResolveFile(depPath, fileName);
if(!package->FileExists(fullFileName))
{
logger->LogError("File not found: " + depPath);
return false;
}

// Check if the file has already been compiled
if(std::find(compiledFiles.begin(), compiledFiles.end(), fullFileName) != compiledFiles.end()) continue;

// Dont compile if the module is ignored
if(std::find(ignoredModules.begin(), ignoredModules.end(), fullFileName) != ignoredModules.end()) continue;

if(!CompileModule(fullFileName, true)) return false;
}
}

return true;
}

bool Compiler::IsBytecodeFile(void* buffer, size_t size)
{
if(size < magicBytes.size()) return false;
if(memcmp(buffer, magicBytes.data(), magicBytes.size()) != 0) return false;
return true;
}

std::vector<uint8_t> Compiler::CreateBytecodeBuffer(const uint8_t* buffer, int length, int sourceLength)
{
// Make necessary changes to the bytecode
FixBytecode(buffer, sourceLength);

// Create our own custom bytecode buffer by appending our magic bytes
// at the front, and then the bytecode itself at the end
std::vector<uint8_t> buf;
size_t bufSize = magicBytes.size() + sizeof(int) + length;
buf.resize(bufSize);

memcpy(buf.data(), magicBytes.data(), magicBytes.size());
memcpy(buf.data() + magicBytes.size(), &sourceLength, sizeof(int));
memcpy(buf.data() + magicBytes.size() + sizeof(int), buffer, length);

return buf;
}

static constexpr int srcHashOffset = 8;

static constexpr uint32_t flagsHash = 243571335;
static constexpr int flagsHashOffset = 12;

void Compiler::FixBytecode(const uint8_t* buffer, int sourceLength)
{
// Copy hash of source into bytecode source hash section
// Needed because V8 compares the bytecode code hash to provided source hash
Helpers::CopyValueToBuffer(buffer, srcHashOffset, Helpers::CreateV8SourceHash(sourceLength + 2));

// Overwrite flags hash with the hash used in client js
// !!! Make sure to update the hash if flags in client js change !!!
Helpers::CopyValueToBuffer(buffer, flagsHashOffset, flagsHash);
}
#include "compiler.h"
#include "helpers.h"

#include <algorithm>

using namespace BytecodeCompiler;

bool Compiler::CompileModule(const std::string& fileName, bool compileDependencies)
{
// Read the file
if(!package->FileExists(fileName))
{
logger->LogError("File not found: " + fileName);
return false;
}
size_t size = package->GetFileSize(fileName);
std::string sourceCode;
sourceCode.resize(size);
if(!package->ReadFile(fileName, sourceCode.data(), sourceCode.size()))
{
logger->LogError("Failed to read file: " + fileName);
return false;
}

v8::TryCatch tryCatch(isolate);
v8::Local<v8::Context> ctx = v8::Context::New(isolate);
v8::Context::Scope ctxScope(ctx);

// Compile the file to a JavaScript module
v8::ScriptOrigin origin(
isolate, v8::String::NewFromUtf8(isolate, fileName.c_str()).ToLocalChecked(), 0, 0, false, -1, v8::Local<v8::Value>(), false, false, true, v8::Local<v8::PrimitiveArray>());
v8::ScriptCompiler::Source source(v8::String::NewFromUtf8(isolate, sourceCode.c_str()).ToLocalChecked(), origin);
v8::MaybeLocal<v8::Module> maybeModule = v8::ScriptCompiler::CompileModule(isolate, &source);
if(maybeModule.IsEmpty() || tryCatch.HasCaught())
{
logger->LogError("Failed to compile module: " + fileName);
Helpers::CheckTryCatch(fileName, logger, tryCatch, ctx);
return false;
}

// Retrieve the bytecode from the module
v8::Local<v8::Module> module = maybeModule.ToLocalChecked();
v8::ScriptCompiler::CachedData* cache = v8::ScriptCompiler::CreateCodeCache(module->GetUnboundModuleScript());
if(cache == nullptr || tryCatch.HasCaught())
{
logger->LogError("Failed to create bytecode: " + fileName);
Helpers::CheckTryCatch(fileName, logger, tryCatch, ctx);
return false;
}

// Write the bytecode to file
std::vector<uint8_t> bytecodeResult = CreateBytecodeBuffer(cache->data, cache->length);
bool writeResult = package->WriteFile(fileName, (void*)bytecodeResult.data(), bytecodeResult.size());
if(!writeResult)
{
logger->LogError("Failed to write to file: " + fileName);
return false;
}

// Make sure the byte buffer is deleted with the cached data from V8
cache->buffer_policy = v8::ScriptCompiler::CachedData::BufferPolicy::BufferOwned;
delete cache;

logger->Log("Converted file to bytecode: " + logger->GetHighlightColor() + fileName);
compiledFiles.push_back(fileName);

// Compile all dependencies
if(compileDependencies)
{
v8::Local<v8::Context> ctx = v8::Context::New(isolate);
v8::Local<v8::FixedArray> dependencies = module->GetModuleRequests();
int length = dependencies->Length();
for(int i = 0; i < length; i++)
{
v8::Local<v8::Data> dep = dependencies->Get(ctx, i);
v8::Local<v8::ModuleRequest> request = dep.As<v8::ModuleRequest>();
// Ignore all imports with import assertions, as those are not loaded as
// normal JS files
if(request->GetImportAssertions()->Length() > 0) continue;

v8::Local<v8::String> depStr = request->GetSpecifier();
std::string depPath = *v8::String::Utf8Value(isolate, depStr);
// Ignore the built-in modules
if(std::find(ignoredModules.begin(), ignoredModules.end(), depPath) != ignoredModules.end()) continue;

// Compile the dependency file
std::string fullFileName = package->ResolveFile(depPath, fileName);
if(!package->FileExists(fullFileName))
{
logger->LogError("File not found: " + depPath);
return false;
}

// Check if the file has already been compiled
if(std::find(compiledFiles.begin(), compiledFiles.end(), fullFileName) != compiledFiles.end()) continue;

// Dont compile if the module is ignored
if(std::find(ignoredModules.begin(), ignoredModules.end(), fullFileName) != ignoredModules.end()) continue;

if(!CompileModule(fullFileName, true)) return false;
}
}

return true;
}

bool Compiler::IsBytecodeFile(void* buffer, size_t size)
{
if(size < magicBytes.size()) return false;
if(memcmp(buffer, magicBytes.data(), magicBytes.size()) != 0) return false;
return true;
}

std::vector<uint8_t> Compiler::CreateBytecodeBuffer(const uint8_t* buffer, int length)
{
// Make necessary changes to the bytecode
FixBytecode(buffer);

// Create our own custom bytecode buffer by appending our magic bytes
// at the front, and then the bytecode itself at the end
std::vector<uint8_t> buf;
size_t bufSize = magicBytes.size() + length;
buf.resize(bufSize);

memcpy(buf.data(), magicBytes.data(), magicBytes.size());
memcpy(buf.data() + magicBytes.size(), buffer, length);

return buf;
}

static constexpr int srcHashOffset = 8;

static constexpr uint32_t flagsHash = 243571335;
static constexpr int flagsHashOffset = 12;

void Compiler::FixBytecode(const uint8_t* buffer)
{
// Copy hash of source into bytecode source hash section
// Needed because V8 compares the bytecode code hash to provided source hash
Helpers::CopyValueToBuffer(buffer, srcHashOffset, Helpers::CreateV8SourceHash(1));

// Overwrite flags hash with the hash used in client js
// !!! Make sure to update the hash if flags in client js change !!!
Helpers::CopyValueToBuffer(buffer, flagsHashOffset, flagsHash);
}
4 changes: 2 additions & 2 deletions compiler/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ namespace BytecodeCompiler
bool IsBytecodeFile(void* buffer, size_t size);

private:
std::vector<uint8_t> CreateBytecodeBuffer(const uint8_t* buffer, int length, int sourceLength);
std::vector<uint8_t> CreateBytecodeBuffer(const uint8_t* buffer, int length);

static void FixBytecode(const uint8_t* buffer, int sourceLength);
static void FixBytecode(const uint8_t* buffer);
};
} // namespace BytecodeCompiler
2 changes: 1 addition & 1 deletion deps/cpp-sdk
Submodule cpp-sdk updated 74 files
+0 −44 IAudioFilter.h
+121 −30 ICore.h
+2 −1 ILocalStorage.h
+17 −12 IResource.h
+1 −1 IScriptRuntime.h
+26 −4 SDK.h
+12 −0 deps/alt-math/alt-math.h
+4 −4 events/CColShapeEvent.h
+1 −1 events/CConnectionQueueAddEvent.h
+1 −1 events/CConnectionQueueRemoveEvent.h
+30 −0 events/CEntityHitEntityEvent.h
+13 −1 events/CEvent.h
+9 −4 events/CFireEvent.h
+4 −4 events/CMetaDataChangeEvent.h
+0 −33 events/CPlayerBeforeConnectEvent.h
+26 −0 events/CPlayerBulletHitEvent.h
+1 −1 events/CPlayerConnectEvent.h
+26 −0 events/CPlayerSpawnEvent.h
+31 −0 events/CPlayerStartEnterVehicleEvent.h
+31 −0 events/CPlayerStartLeaveVehicleEvent.h
+0 −2 events/CPlayerWeaponShootEvent.h
+4 −4 events/CStreamSyncedMetaDataChangeEvent.h
+4 −4 events/CSyncedMetaDataChangeEvent.h
+32 −0 events/CVehicleHornEvent.h
+28 −0 events/CVehicleSirenEvent.h
+31 −0 events/CVoiceConnectionEvent.h
+5 −2 events/CWeaponDamageEvent.h
+32 −0 events/CWorldObjectPositonChangeEvent.h
+29 −0 events/CWorldObjectStreamInEvent.h
+29 −0 events/CWorldObjectStreamOutEvent.h
+33 −1 objects/IBaseObject.h
+6 −10 objects/IEntity.h
+1 −1 objects/ILocalPlayer.h
+25 −0 objects/IObject.h
+30 −0 objects/IPed.h
+43 −2 objects/IPlayer.h
+9 −5 objects/IVehicle.h
+4 −10 script-objects/IAudio.h
+13 −0 script-objects/IAudioAttachedOutput.h
+46 −0 script-objects/IAudioCategory.h
+33 −0 script-objects/IAudioFilter.h
+12 −0 script-objects/IAudioFrontendOutput.h
+26 −0 script-objects/IAudioOutput.h
+13 −0 script-objects/IAudioWorldOutput.h
+37 −16 script-objects/IBlip.h
+19 −0 script-objects/ICheckpoint.h
+5 −29 script-objects/IConnectionInfo.h
+17 −0 script-objects/ICustomTexture.h
+17 −0 script-objects/IFont.h
+2 −1 script-objects/IHttpClient.h
+61 −0 script-objects/ILocalObject.h
+29 −0 script-objects/ILocalPed.h
+29 −0 script-objects/ILocalVehicle.h
+98 −0 script-objects/IMarker.h
+3 −1 script-objects/INative.h
+0 −45 script-objects/IObject.h
+2 −2 script-objects/IRml.h
+37 −0 script-objects/ITextLabel.h
+38 −0 script-objects/IVirtualEntity.h
+16 −0 script-objects/IVirtualEntityGroup.h
+6 −0 script-objects/IVoiceChannel.h
+1 −1 script-objects/IWebSocketClient.h
+1 −0 script-objects/IWebView.h
+12 −0 types/AmmoFlags.h
+17 −0 types/AmmoSpecialType.h
+18 −0 types/Decoration.h
+42 −40 types/MValue.h
+53 −0 types/Metric.h
+1 −0 types/PedModelInfo.h
+14 −24 types/Permissions.h
+3 −3 types/RGBA.h
+2 −0 types/VehicleModelInfo.h
+13 −0 types/VoiceChat.h
+23 −0 types/WeaponModelInfo.h

0 comments on commit fb9a45a

Please sign in to comment.