From 29260d30aef272d6b959d52a25f9802bdc0ab336 Mon Sep 17 00:00:00 2001 From: "Kevin (Kun) Kassimo Qian" Date: Sat, 26 Oct 2019 16:22:34 -0700 Subject: [PATCH] Support named imports/exports for subset of properties in JSON modules --- cli/compilers/json.rs | 39 +++++++++++++++++++++++++++++---- cli/tests/050_more_jsons.ts | 7 ++++++ cli/tests/050_more_jsons.ts.out | 5 +++++ cli/tests/integration_tests.rs | 5 +++++ cli/tests/subdir/json_1.json | 5 +++++ cli/tests/subdir/json_2.json | 1 + 6 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 cli/tests/050_more_jsons.ts create mode 100644 cli/tests/050_more_jsons.ts.out create mode 100644 cli/tests/subdir/json_1.json create mode 100644 cli/tests/subdir/json_2.json diff --git a/cli/compilers/json.rs b/cli/compilers/json.rs index 57e44d35440586..a839970ae82645 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: code, name: source_file.url.to_string(), }; diff --git a/cli/tests/050_more_jsons.ts b/cli/tests/050_more_jsons.ts new file mode 100644 index 00000000000000..90deabcd164b2b --- /dev/null +++ b/cli/tests/050_more_jsons.ts @@ -0,0 +1,7 @@ +import j1, { $var } from "./subdir/json_1.json"; +import j2 from "./subdir/json_2.json"; +console.log($var); +console.log($var.a); +console.log(j1); +console.log(j1["with space"]); +console.log(j2); diff --git a/cli/tests/050_more_jsons.ts.out b/cli/tests/050_more_jsons.ts.out new file mode 100644 index 00000000000000..0ca014a21491eb --- /dev/null +++ b/cli/tests/050_more_jsons.ts.out @@ -0,0 +1,5 @@ +{ a: 123, b: [ 1, 2, 3 ], c: null } +123 +{ $var: { a: 123, b: [ 1, 2, 3 ], c: null }, with space: "invalid variable name", function: "reserved word" } +invalid variable name +just a string diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index 909acfe04a37e0..ee8f1384c8791a 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -343,6 +343,11 @@ itest!(_049_info_flag_script_jsx { http_server: true, }); +itest!(_050_more_jsons { + args: "run --reload 050_more_jsons.ts", + output: "050_more_jsons.ts.out", +}); + itest!(async_error { exit_code: 1, args: "run --reload async_error.ts", diff --git a/cli/tests/subdir/json_1.json b/cli/tests/subdir/json_1.json new file mode 100644 index 00000000000000..754d16b842fe10 --- /dev/null +++ b/cli/tests/subdir/json_1.json @@ -0,0 +1,5 @@ +{ + "$var": { "a": 123, "b": [1, 2, 3], "c": null }, + "with space": "invalid variable name", + "function": "reserved word" +} diff --git a/cli/tests/subdir/json_2.json b/cli/tests/subdir/json_2.json new file mode 100644 index 00000000000000..7deb8b173227be --- /dev/null +++ b/cli/tests/subdir/json_2.json @@ -0,0 +1 @@ +"just a string"