diff --git a/tests/api/test-eval-this-binding.c b/tests/api/test-eval-this-binding.c new file mode 100644 index 00000000..78165c0c --- /dev/null +++ b/tests/api/test-eval-this-binding.c @@ -0,0 +1,52 @@ +/* + * Test 'this' binding for eval code: https://github.com/svaarala/duktape/issues/164 + */ + +/*=== +*** test_1 (duk_safe_call) +non-strict eval from C +not an error in non-strict mode +object +object +strict eval from C +ReferenceError +object +object +final top: 0 +==> rc=0, result='undefined' +===*/ + +static duk_ret_t test_1(duk_context *ctx) { + /* For non-strict eval code the 'this' binding was effectively + * the global object even before fixing GH-164: an undefined + * 'this' binding gets promoted to the global object by the + * usual Ecmascript call handling semantics. + */ + duk_eval_string(ctx, + "print('non-strict eval from C');\n" + "try { dummy1 = 1; print('not an error in non-strict mode'); } catch (e) { print(e.name); }\n" + "print(typeof this);\n" + "print(typeof (this || {}).Math);\n" + ); + duk_pop(ctx); + + /* For strict eval code the 'this' binding was undefined when + * eval was being done from C code (but was the global object + * when done from Ecmascript code). With GH-164 fixed the + * 'this' binding is global object for strict eval code too. + */ + + duk_eval_string_noresult(ctx, + "'use strict'\n" + "print('strict eval from C');\n" + "try { dummy2 = 1; print('error in strict mode'); } catch (e) { print(e.name); }\n" + "print(typeof this);\n" + "print(typeof (this || {}).Math);\n" + ); + printf("final top: %ld\n", (long) duk_get_top(ctx)); + return 0; +} + +void test(duk_context *ctx) { + TEST_SAFE_CALL(test_1); +} diff --git a/tests/ecmascript/test-dev-eval-this-binding.js b/tests/ecmascript/test-dev-eval-this-binding.js new file mode 100644 index 00000000..544f1b72 --- /dev/null +++ b/tests/ecmascript/test-dev-eval-this-binding.js @@ -0,0 +1,48 @@ +/* + * Demonstrate 'this' binding behavior for "direct calls to eval" made + * from Ecmascript code. The behavior for both strict and non-strict is + * the same: the 'this' binding is inherited from the calling context, + * see E5.1 Section 10.4.2: + * + * - Step 2 will match (direct call) and establish a 'this' binding + * in step 2.a, independent of target code strictness. + * + * - Step 3 will match for strict code only and will update the lexical + * environment, but the 'this' binding is not affected. + * + * The C API eval behavior (duk_(p)eval_*) was different prior to Duktape 1.3: + * eval code 'this' binding was the global object for non-strict eval code, + * but undefined for strict eval code. This was fixed as part of GH-164: + * + * https://github.com/svaarala/duktape/issues/164 + */ + +/*=== +non-strict eval code +not an error in non-strict code +object +object +strict eval code +ReferenceError +object +object +===*/ + +function test() { + eval("print('non-strict eval code');\n" + + "try { dummy1 = 1; print('not an error in non-strict code'); } catch (e) { print(e.name); }\n" + + "print(typeof this);\n" + + "print(typeof (this || {}).Math);\n"); + + eval("'use strict';\n" + + "print('strict eval code');\n" + + "try { dummy2 = 1; print('error in non-strict code'); } catch (e) { print(e.name); }\n" + + "print(typeof this);\n" + + "print(typeof (this || {}).Math);\n"); +} + +try { + test(); +} catch (e) { + print(e.stack || e); +}