@@ -248,4 +248,125 @@ mod tests {
248248 let res = sandbox. get_loaded_sandbox ( ) ;
249249 assert ! ( res. is_ok( ) ) ;
250250 }
251+
252+ // ── Auto-export heuristic tests (issue #39) ──────────────────────────
253+ // The auto-export logic must only detect actual ES export statements,
254+ // not the word "export" inside string literals, comments, or identifiers.
255+
256+ #[ test]
257+ fn handler_with_export_in_string_literal ( ) {
258+ // "export" appears inside a string — auto-export should still fire
259+ let handler = Script :: from_content (
260+ r#"
261+ function handler(event) {
262+ const xml = '<config mode="export">value</config>';
263+ return { result: xml };
264+ }
265+ "# ,
266+ ) ;
267+
268+ let proto = SandboxBuilder :: new ( ) . build ( ) . unwrap ( ) ;
269+ let mut sandbox = proto. load_runtime ( ) . unwrap ( ) ;
270+ sandbox. add_handler ( "handler" , handler) . unwrap ( ) ;
271+ let mut loaded = sandbox. get_loaded_sandbox ( ) . unwrap ( ) ;
272+
273+ let res = loaded
274+ . handle_event ( "handler" , "{}" . to_string ( ) , None )
275+ . unwrap ( ) ;
276+ assert_eq ! (
277+ res,
278+ r#"{"result":"<config mode=\"export\">value</config>"}"#
279+ ) ;
280+ }
281+
282+ #[ test]
283+ fn handler_with_export_in_comment ( ) {
284+ // "export" appears in a comment — auto-export should still fire
285+ let handler = Script :: from_content (
286+ r#"
287+ function handler(event) {
288+ // TODO: export this data to CSV
289+ return { result: 42 };
290+ }
291+ "# ,
292+ ) ;
293+
294+ let proto = SandboxBuilder :: new ( ) . build ( ) . unwrap ( ) ;
295+ let mut sandbox = proto. load_runtime ( ) . unwrap ( ) ;
296+ sandbox. add_handler ( "handler" , handler) . unwrap ( ) ;
297+ let mut loaded = sandbox. get_loaded_sandbox ( ) . unwrap ( ) ;
298+
299+ let res = loaded
300+ . handle_event ( "handler" , "{}" . to_string ( ) , None )
301+ . unwrap ( ) ;
302+ assert_eq ! ( res, r#"{"result":42}"# ) ;
303+ }
304+
305+ #[ test]
306+ fn handler_with_export_in_identifier ( ) {
307+ // "export" is part of an identifier — auto-export should still fire
308+ let handler = Script :: from_content (
309+ r#"
310+ function handler(event) {
311+ const exportPath = "/tmp/out.csv";
312+ return { result: exportPath };
313+ }
314+ "# ,
315+ ) ;
316+
317+ let proto = SandboxBuilder :: new ( ) . build ( ) . unwrap ( ) ;
318+ let mut sandbox = proto. load_runtime ( ) . unwrap ( ) ;
319+ sandbox. add_handler ( "handler" , handler) . unwrap ( ) ;
320+ let mut loaded = sandbox. get_loaded_sandbox ( ) . unwrap ( ) ;
321+
322+ let res = loaded
323+ . handle_event ( "handler" , "{}" . to_string ( ) , None )
324+ . unwrap ( ) ;
325+ assert_eq ! ( res, r#"{"result":"/tmp/out.csv"}"# ) ;
326+ }
327+
328+ #[ test]
329+ fn handler_with_explicit_export_is_not_doubled ( ) {
330+ // Script already has an export statement — auto-export should be skipped
331+ let handler = Script :: from_content (
332+ r#"
333+ function handler(event) {
334+ return { result: "explicit" };
335+ }
336+ export { handler };
337+ "# ,
338+ ) ;
339+
340+ let proto = SandboxBuilder :: new ( ) . build ( ) . unwrap ( ) ;
341+ let mut sandbox = proto. load_runtime ( ) . unwrap ( ) ;
342+ sandbox. add_handler ( "handler" , handler) . unwrap ( ) ;
343+ let mut loaded = sandbox. get_loaded_sandbox ( ) . unwrap ( ) ;
344+
345+ let res = loaded
346+ . handle_event ( "handler" , "{}" . to_string ( ) , None )
347+ . unwrap ( ) ;
348+ assert_eq ! ( res, r#"{"result":"explicit"}"# ) ;
349+ }
350+
351+ #[ test]
352+ fn handler_with_export_default_function ( ) {
353+ // `export function` — auto-export should be skipped
354+ let handler = Script :: from_content (
355+ r#"
356+ export function handler(event) {
357+ return { result: "inline-export" };
358+ }
359+ "# ,
360+ ) ;
361+
362+ let proto = SandboxBuilder :: new ( ) . build ( ) . unwrap ( ) ;
363+ let mut sandbox = proto. load_runtime ( ) . unwrap ( ) ;
364+ sandbox. add_handler ( "handler" , handler) . unwrap ( ) ;
365+ let mut loaded = sandbox. get_loaded_sandbox ( ) . unwrap ( ) ;
366+
367+ let res = loaded
368+ . handle_event ( "handler" , "{}" . to_string ( ) , None )
369+ . unwrap ( ) ;
370+ assert_eq ! ( res, r#"{"result":"inline-export"}"# ) ;
371+ }
251372}
0 commit comments