Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allowing access of global variables inside ftd functions #1432

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions fastn-core/src/package/package_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ pub(crate) async fn read_ftd_2023(
let ssr_body = fastn_js::ssr_with_js_string(
&config.package.name,
format!("{js_ftd_script}\n{js_document_script}").as_str(),
main.id.as_str(),
);

all_packages.extend(lib.config.all_packages.into_inner());
Expand Down
2 changes: 1 addition & 1 deletion fastn-js/js/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -958,7 +958,7 @@ class Node2 {
attachCss(property, value, createClass, className) {
let propertyShort = fastn_dom.propertyMap[property] || property;
propertyShort = `__${propertyShort}`;
let cls = `${propertyShort}-${JSON.stringify(fastn_dom.class_count)}`;
let cls = `${propertyShort}-${fastn_dom.class_count}`;
if (!!className) {
cls = className;
} else {
Expand Down
2 changes: 1 addition & 1 deletion fastn-js/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
fn main() {
let start = std::time::Instant::now();
println!("{}", fastn_js::ssr_str(js()));
println!("{}", fastn_js::ssr_str(js(), "foo"));
println!("elapsed: {:?}", start.elapsed());

let start = std::time::Instant::now();
Expand Down
13 changes: 8 additions & 5 deletions fastn-js/src/ssr.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub fn ssr_str(js: &str) -> String {
pub fn ssr_str(js: &str, doc_name: &str) -> String {
let all_js = fastn_js::all_js_with_test();
let js = format!("{all_js}{js}");

Expand All @@ -19,7 +19,10 @@ pub fn ssr_str(js: &str) -> String {
)
.build()
.unwrap();
context.eval_as::<String>(js.as_str()).unwrap()
context
.eval_as::<String>(js.as_str())
.map_err(|e| panic!("SSR Error: {}, doc_id: {}", e, doc_name))
.unwrap()
}
}

Expand All @@ -32,10 +35,10 @@ pub fn ssr(ast: &[fastn_js::Ast]) -> String {
}};
fastn_virtual.ssr(main_wrapper);", fastn_js::to_js(ast,
"foo"));
ssr_str(&js)
ssr_str(&js, "foo")
}

pub fn ssr_with_js_string(package_name: &str, js: &str) -> String {
pub fn ssr_with_js_string(package_name: &str, js: &str, doc_name: &str) -> String {
let js = format!("
let __fastn_package_name__ = \"{}\";\n{}
let main_wrapper = function(parent) {{
Expand All @@ -46,5 +49,5 @@ pub fn ssr_with_js_string(package_name: &str, js: &str) -> String {
}};
fastn_virtual.ssr(main_wrapper);", package_name, js);

ssr_str(&js)
ssr_str(&js, doc_name)
}
43 changes: 37 additions & 6 deletions fastn-js/src/to_js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1035,17 +1035,48 @@ impl ExpressionGenerator {

if node.operator().get_variable_identifier_read().is_some() && !no_getter {
let chain_dot_operator_count = value.matches('.').count();
// When there are chained dot operator value
// like person.name, person.meta.address
if chain_dot_operator_count > 1 {
let is_local_argument = value.starts_with(fastn_js::LOCAL_VARIABLE_MAP);
let is_global_value = value.contains(fastn_js::GLOBAL_VARIABLE_MAP);

// If value is internal looping index variable or global value or ftd variable
if value.eq("index") || is_global_value || value.starts_with("ftd") {
return format!("fastn_utils.getter({})", value);
}

// When there is dot chaining on local argument values
// like __args__.person.name, __args__.person.meta.address
if is_local_argument {
if chain_dot_operator_count > 1 {
return format!(
"fastn_utils.getter({})",
get_chained_getter_string(value.as_str())
);
}

// If the value is local argument variable with no dot chaining
// like __args__.name, __args__.address
return format!("fastn_utils.getter({})", value);
}

// Otherwise consider the value as global variable
// If dot chaining on global variable
// like person.name, places.0
if chain_dot_operator_count > 0 {
let global_variable_name =
format!("{}.foo__{}", fastn_js::GLOBAL_VARIABLE_MAP, value.as_str());
return format!(
"fastn_utils.getter({})",
get_chained_getter_string(value.as_str())
get_chained_getter_string(global_variable_name.as_str())
);
}

// When there is no chained dot operator value
format!("fastn_utils.getter({})", value)
// If no dot chaining on global variable
// like x, y (globally defined)
format!(
"fastn_utils.getter({}.foo__{})",
fastn_js::GLOBAL_VARIABLE_MAP,
value
)
} else {
value
}
Expand Down
21 changes: 17 additions & 4 deletions fastn-js/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,25 @@ pub fn reference_to_js(s: &str) -> String {

let (mut p1, mut p2) = get_doc_name_and_remaining(s.as_str());
p1 = fastn_js::utils::name_to_js_(p1.as_str());
let mut prefix_attached = false;
let mut wrapper_function = None;
let is_asset_reference = p1.contains("assets");
while let Some(ref remaining) = p2 {
let (p21, p22) = get_doc_name_and_remaining(remaining);
match p21.parse::<i64>() {
Ok(num) if p22.is_none() => {
p1 = format!("{}.get({})", p1, num);
wrapper_function = Some("fastn_utils.getListItem");
}
Ok(num) if p22.is_some() && !prefix_attached && !is_asset_reference => {
p1 = format!(
"fastn_utils.getListItem({}{}.get({}))",
prefix.map(|v| format!("{v}.")).unwrap_or_default(),
p1,
num
);
prefix_attached = true;
}
_ => {
p1 = format!(
"{}.get(\"{}\")",
Expand All @@ -33,10 +44,12 @@ pub fn reference_to_js(s: &str) -> String {
}
p2 = p22;
}
let p1 = format!(
"{}{p1}",
prefix.map(|v| format!("{v}.")).unwrap_or_default()
);
if !prefix_attached {
p1 = format!(
"{}{p1}",
prefix.map(|v| format!("{v}.")).unwrap_or_default()
);
}
if let Some(func) = wrapper_function {
return format!("{}({})", func, p1);
}
Expand Down
2 changes: 2 additions & 0 deletions ftd/src/js/ftd_test_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ fn get_dummy_package_data() -> String {
#[track_caller]
fn p(s: &str, t: &str, fix: bool, manual: bool, script: bool, file_location: &std::path::PathBuf) {
let i = interpret_helper("foo", s).unwrap_or_else(|e| panic!("{:?}", e));
let doc_name = i.name.clone();
let js_ast_data = ftd::js::document_into_js_ast(i);
let js_document_script = fastn_js::to_js(js_ast_data.asts.as_slice(), "foo");
let js_ftd_script = fastn_js::to_js(ftd::js::default_bag_into_js_ast().as_slice(), "foo");
Expand Down Expand Up @@ -126,6 +127,7 @@ fn p(s: &str, t: &str, fix: bool, manual: bool, script: bool, file_location: &st
let ssr_body = fastn_js::ssr_with_js_string(
"foo",
format!("{js_ftd_script}\n{js_document_script}").as_str(),
doc_name.as_str(),
);

ftd::ftd_js_html()
Expand Down
28 changes: 14 additions & 14 deletions ftd/t/js/69-chained-dot-value-in-functions.ftd
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
-- record Person:
-- record person:
caption name:
integer age:
Metadata meta:
metadata meta:

-- record Metadata:
-- record metadata:
string address:
string phone-number:

-- string list places: Bangalore, Mumbai, Chennai, Kolkata

-- Person list people:
-- person list people:

-- Person: Sam Ather
-- person: Sam Ather
age: 30

-- Person.meta:
-- person.meta:
address: Sam Ather City at Some Other House
phone-number: +987-654321

-- Person: $r
-- person: $r

-- end: people

-- Metadata meta:
-- metadata meta:
address: Sam City in Some House
phone-number: +1234-56789

-- Person r: Sam Wan
-- person r: Sam Wan
age: 23
meta: $meta

Expand All @@ -37,19 +37,19 @@ meta: $meta
-- ftd.text: $first-person-details(people = $people)

-- string more-details(p):
Person p:
person p:

"Person " + p.name + " lives at " + p.meta.address + ". His contact number is " + p.meta.phone-number

-- string some-details(person, places):
Person person:
person person:
string list places:
string date:

"This person named " + person.name + " has first visited " + places.0 + " on " + date
"The person named " + person.name + " has first visited " + places.0 + " on " + date

-- string first-person-details(people):
Person list people:
person list people:

"First Person is " + people.0.name + " lives at " + people.0.meta.address + ". His contact number is " + people.0.meta.phone-number
"First person is " + people.0.name + " lives at " + people.0.meta.address + ". His contact number is " + people.0.meta.phone-number

6 changes: 3 additions & 3 deletions ftd/t/js/69-chained-dot-value-in-functions.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions ftd/t/js/70-global-variables-in-functions.ftd
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
-- record person:
caption name:
integer age:

-- person p: Sam Wan
age: 30

-- person list people:

-- person: Sam Ather
age: 23

-- person: $p

-- end: people






-- ftd.text: $p.name
color: green

-- ftd.text: $people.0.name
color: green

-- ftd.text: $get-details(company = FifthTry)
color: blue

-- ftd.text: $get-first-person-details(company = FifthTry)
color: blue

-- string get-details(company):
string company:

"Person " + p.name + " works for " + company + " whose age is " + p.age

-- string get-first-person-details(company):
string company:

"Person " + people.0.name + " works for " + company + " whose age is " + people.0.age
Loading
Loading