diff --git a/backend/parsers/windmill-parser-ts/src/asset_parser.rs b/backend/parsers/windmill-parser-ts/src/asset_parser.rs index 5990360472..8808971486 100644 --- a/backend/parsers/windmill-parser-ts/src/asset_parser.rs +++ b/backend/parsers/windmill-parser-ts/src/asset_parser.rs @@ -1,10 +1,11 @@ use swc_common::{sync::Lrc, FileName, SourceMap}; -use swc_ecma_ast::{CallExpr, Expr, Lit, MemberExpr, MemberProp, Str}; +use swc_ecma_ast::{CallExpr, Expr, Lit, MemberExpr, MemberProp, Str, TsLit}; use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax, TsSyntax}; use swc_ecma_visit::{Visit, VisitWith}; use windmill_parser::asset_parser::{ - merge_assets, parse_resource_syntax, AssetKind, ParseAssetsResult, + merge_assets, parse_asset_syntax, AssetKind, AssetUsageAccessType, ParseAssetsResult, }; +use AssetUsageAccessType::*; pub fn parse_assets<'a>( code: &'a str, @@ -48,39 +49,63 @@ pub fn parse_assets<'a>( struct AssetsFinder<'a> { assets: Vec>, + // We have to store paths separately because of lifetime concerns paths_storage: &'a mut Vec, } impl<'a> Visit for AssetsFinder<'a> { - fn visit_call_expr(&mut self, node: &swc_ecma_ast::CallExpr) { - let kind = match node.callee.as_expr().map(AsRef::as_ref) { - Some(Expr::Ident(ident)) if ident.sym.as_str() == "getResource" => AssetKind::Resource, - Some(Expr::Member(MemberExpr { prop: MemberProp::Ident(ident), .. })) - if ident.sym.as_str() == "getResource" => - { - AssetKind::Resource - } - - _ => { - >::visit_children_with(node, self); - return; - } - }; - if node.args.len() != 1 { - return; - } - match node.args[0].expr.as_ref() { - Expr::Lit(Lit::Str(Str { value, .. })) => { - if let Some(path) = parse_resource_syntax(value.as_str()) { + // visit_call_expr will not recurse if it detects an asset, + // so this will only be called when no further context was found + fn visit_lit(&mut self, node: &swc_ecma_ast::Lit) { + match node { + swc_ecma_ast::Lit::Str(str) => { + if let Some((kind, path)) = parse_asset_syntax(str.value.as_str()) { self.paths_storage.push(path.to_string()); self.assets .push(ParseAssetsResult { kind, path: "", access_type: None }); } } - _ => { - >::visit_children_with(node, self); - return; - } + _ => >::visit_children_with(node, self), + } + } + + fn visit_call_expr(&mut self, node: &swc_ecma_ast::CallExpr) { + match self.visit_call_expr_inner(node) { + Ok(_) => {} + Err(_) => >::visit_children_with(node, self), } } } + +impl<'a> AssetsFinder<'a> { + fn visit_call_expr_inner(&mut self, node: &swc_ecma_ast::CallExpr) -> Result<(), ()> { + let ident = match node.callee.as_expr().map(AsRef::as_ref) { + Some(Expr::Ident(i)) => i.sym.as_str(), + Some(Expr::Member(MemberExpr { prop: MemberProp::Ident(i), .. })) => i.sym.as_str(), + _ => return Err(()), + }; + let (kind, access_type) = match ident { + "getResource" => (AssetKind::Resource, None), + "loadS3File" => (AssetKind::S3Object, Some(R)), + "writeS3File" => (AssetKind::S3Object, Some(W)), + _ => return Err(()), + }; + if node.args.len() < 1 { + return Err(()); + } + match node.args[0].expr.as_ref() { + Expr::Lit(Lit::Str(Str { value, .. })) => { + if let Some((k, path)) = parse_asset_syntax(value.as_str()) { + if k != kind { + return Err(()); + } + self.paths_storage.push(path.to_string()); + self.assets + .push(ParseAssetsResult { kind, path: "", access_type }); + } + } + _ => return Err(()), + } + Ok(()) + } +} diff --git a/backend/parsers/windmill-parser/src/asset_parser.rs b/backend/parsers/windmill-parser/src/asset_parser.rs index 45429586ee..348ffba876 100644 --- a/backend/parsers/windmill-parser/src/asset_parser.rs +++ b/backend/parsers/windmill-parser/src/asset_parser.rs @@ -49,11 +49,13 @@ pub fn merge_assets<'a>(assets: Vec>) -> Vec Option<&str> { - if uri.starts_with("res://") { - Some(&uri[6..]) - } else if uri.starts_with("$res:") { - Some(&uri[5..]) +pub fn parse_asset_syntax(s: &str) -> Option<(AssetKind, &str)> { + if s.starts_with("s3://") { + Some((AssetKind::S3Object, &s[5..])) + } else if s.starts_with("res://") { + Some((AssetKind::Resource, &s[6..])) + } else if s.starts_with("$res:") { + Some((AssetKind::Resource, &s[5..])) } else { None }