-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: introduce JavaScript plugin API using V8 (#11)
- Loading branch information
1 parent
52b9a73
commit 3886551
Showing
25 changed files
with
868 additions
and
46 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,9 @@ mod plugins; | |
mod scripts; | ||
mod serve; | ||
|
||
#[cfg(test)] | ||
mod test; | ||
|
||
use crate::build::StuartContext; | ||
use crate::error::StuartError; | ||
use crate::logger::{LogLevel, Logger, Progress, LOGGER}; | ||
|
@@ -24,8 +27,9 @@ use std::fs::{remove_dir_all, remove_file}; | |
use std::path::PathBuf; | ||
use std::sync::atomic::Ordering; | ||
|
||
fn main() { | ||
let matches = App::new("Stuart") | ||
/// Returns the CLI application. | ||
fn app() -> App<'static> { | ||
App::new("Stuart") | ||
.version(env!("CARGO_PKG_VERSION")) | ||
.author("William Henderson <[email protected]>") | ||
.about("A Blazingly-Fast Static Site Generator") | ||
|
@@ -102,7 +106,10 @@ fn main() { | |
Command::new("clean").about("Removes the output directory and generated metadata"), | ||
) | ||
.subcommand_required(true) | ||
.get_matches(); | ||
} | ||
|
||
fn main() { | ||
let matches = app().get_matches(); | ||
|
||
let log_level = if matches.is_present("quiet") { | ||
LogLevel::Quiet | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
//! Enables access to Stuart's execution context from JavaScript running within V8. | ||
use stuart_core::process::Scope; | ||
|
||
/// Makes the Stuart scope accessible to `set_variable` and `get_variable` when they're called from JavaScript code. | ||
pub fn set_stuart_context(scope: &mut v8::HandleScope, context: &mut Scope) { | ||
let stuart_context = v8::Object::new(scope); | ||
|
||
let k_context = v8::String::new(scope, "STUART").unwrap(); | ||
let k_set_variable = v8::String::new(scope, "set").unwrap(); | ||
let k_get_variable = v8::String::new(scope, "get").unwrap(); | ||
let k_external = v8::String::new(scope, "_ptr").unwrap(); | ||
|
||
let set_variable = v8::FunctionTemplate::new(scope, set_variable) | ||
.get_function(scope) | ||
.unwrap(); | ||
let get_variable = v8::FunctionTemplate::new(scope, get_variable) | ||
.get_function(scope) | ||
.unwrap(); | ||
let external = v8::External::new(scope, context as *mut _ as *mut std::ffi::c_void); | ||
|
||
stuart_context.set(scope, k_set_variable.into(), set_variable.into()); | ||
stuart_context.set(scope, k_get_variable.into(), get_variable.into()); | ||
stuart_context.set(scope, k_external.into(), external.into()); | ||
|
||
scope | ||
.get_current_context() | ||
.global(scope) | ||
.set(scope, k_context.into(), stuart_context.into()); | ||
} | ||
|
||
/// Gets the Stuart context from V8. | ||
/// | ||
/// # Safety | ||
/// This function is only safe if `set_stuart_context` has previously been called with the same `scope`. | ||
unsafe fn get_stuart_context<'s>( | ||
scope: &mut v8::HandleScope, | ||
obj: v8::Local<'_, v8::Object>, | ||
) -> &'s mut Scope<'s> { | ||
let k_external = v8::String::new(scope, "_ptr").unwrap(); | ||
|
||
(v8::Local::<v8::External>::try_from(obj.get(scope, k_external.into()).unwrap()) | ||
.unwrap() | ||
.value() as *mut Scope) | ||
.as_mut() | ||
.unwrap() | ||
} | ||
|
||
/// Sets a variable in the current Stuart scope. | ||
pub fn set_variable<'s>( | ||
scope: &mut v8::HandleScope<'s>, | ||
args: v8::FunctionCallbackArguments<'s>, | ||
_ret: v8::ReturnValue, | ||
) { | ||
let stuart_scope = unsafe { get_stuart_context(scope, args.this()) }; | ||
let key = args.get(0).to_rust_string_lossy(scope); | ||
let value = args.get(1); | ||
let json_value = super::json::js_to_json(value, scope); | ||
|
||
if json_value.is_none() { | ||
println!( | ||
"warning(js): attempted to set variable `{}` to `undefined`", | ||
key | ||
); | ||
return; | ||
} | ||
|
||
stuart_scope | ||
.stack | ||
.last_mut() | ||
.unwrap() | ||
.add_variable(key, json_value.unwrap()); | ||
} | ||
|
||
/// Gets a variable from the current Stuart scope. | ||
pub fn get_variable<'s>( | ||
scope: &mut v8::HandleScope<'s>, | ||
args: v8::FunctionCallbackArguments<'s>, | ||
mut ret: v8::ReturnValue, | ||
) { | ||
let stuart_scope = unsafe { get_stuart_context(scope, args.this()) }; | ||
let key = args.get(0).to_rust_string_lossy(scope); | ||
let value = stuart_scope.get_variable(&key); | ||
let v8_value = super::json::json_to_js(value, scope); | ||
|
||
ret.set(v8_value); | ||
} |
Oops, something went wrong.