From 6869bfa4c63121f60284c7a2e48c5db1ce86f9cc Mon Sep 17 00:00:00 2001 From: "Kevin (Kun) \"Kassimo\" Qian" Date: Sat, 26 Oct 2019 18:04:34 -0700 Subject: Support named imports/exports for subset of properties in JSON modules (#3210) --- cli/compilers/json.rs | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) (limited to 'cli/compilers/json.rs') diff --git a/cli/compilers/json.rs b/cli/compilers/json.rs index 57e44d354..e61b38649 100644 --- a/cli/compilers/json.rs +++ b/cli/compilers/json.rs @@ -3,8 +3,13 @@ use crate::compilers::CompiledModule; use crate::compilers::CompiledModuleFuture; use crate::file_fetcher::SourceFile; use crate::state::ThreadSafeState; +use deno::ErrBox; +use regex::Regex; use std::str; +// From https://github.com/mathiasbynens/mothereff.in/blob/master/js-variables/eff.js +static JS_RESERVED_WORDS: &str = r"^(?:do|if|in|for|let|new|try|var|case|else|enum|eval|false|null|this|true|void|with|await|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|default|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$"; + pub struct JsonCompiler {} impl JsonCompiler { @@ -13,11 +18,37 @@ impl JsonCompiler { _state: ThreadSafeState, source_file: &SourceFile, ) -> Box { + let maybe_json_value: serde_json::Result = + serde_json::from_str(&str::from_utf8(&source_file.source_code).unwrap()); + if let Err(err) = maybe_json_value { + return Box::new(futures::future::err(ErrBox::from(err))); + } + + let mut code = format!( + "export default {};\n", + str::from_utf8(&source_file.source_code).unwrap() + ); + + if let serde_json::Value::Object(m) = maybe_json_value.unwrap() { + // Best effort variable name exports + // Actual all allowed JS variable names are way tricker. + // We only handle a subset of alphanumeric names. + let js_var_regex = Regex::new(r"^[a-zA-Z_$][0-9a-zA-Z_$]*$").unwrap(); + // Also avoid collision with reserved words. + let reserved_words = Regex::new(JS_RESERVED_WORDS).unwrap(); + for (key, value) in m.iter() { + if js_var_regex.is_match(&key) && !reserved_words.is_match(&key) { + code.push_str(&format!( + "export const {} = {};\n", + key, + value.to_string() + )); + } + } + } + let module = CompiledModule { - code: format!( - "export default {};", - str::from_utf8(&source_file.source_code).unwrap() - ), + code, name: source_file.url.to_string(), }; -- cgit v1.2.3