@@ -335,6 +335,8 @@ static duk_uint8_t *duk__dump_func(duk_context *ctx, duk_hcompfunc *func, duk_bu
335335 fn ++ ;
336336 }
337337
338+ /* Lexenv and varenv are not dumped. */
339+
338340 /* Object extra properties.
339341 *
340342 * There are some difference between function templates and functions.
@@ -382,6 +384,8 @@ static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t
382384 duk_idx_t idx_base ;
383385 duk_tval * tv1 ;
384386 duk_uarridx_t arr_idx ;
387+ duk_hobject * func_env ;
388+ duk_bool_t need_pop ;
385389
386390 /* XXX: There's some overlap with duk_js_closure() here, but
387391 * seems difficult to share code. Ensure that the final function
@@ -416,8 +420,8 @@ static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t
416420 /* Push function object, init flags etc. This must match
417421 * duk_js_push_closure() quite carefully.
418422 */
419- duk_push_compiledfunction (ctx );
420- h_fun = duk_known_hcompfunc ( ctx , -1 );
423+ h_fun = duk_push_compiledfunction (ctx );
424+ DUK_ASSERT ( h_fun != NULL );
421425 DUK_ASSERT (DUK_HOBJECT_IS_COMPFUNC ((duk_hobject * ) h_fun ));
422426 DUK_ASSERT (DUK_HCOMPFUNC_GET_DATA (thr -> heap , h_fun ) == NULL );
423427 DUK_ASSERT (DUK_HCOMPFUNC_GET_FUNCS (thr -> heap , h_fun ) == NULL );
@@ -560,26 +564,37 @@ static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t
560564 duk_push_u32 (ctx , tmp32 );
561565 duk_xdef_prop_stridx (ctx , -2 , DUK_STRIDX_LENGTH , DUK_PROPDESC_FLAGS_NONE );
562566
563- p = duk__load_string_raw (ctx , p );
567+ p = duk__load_string_raw (ctx , p ); /* -> [ func funcname ] */
568+ func_env = thr -> builtins [DUK_BIDX_GLOBAL_ENV ];
569+ DUK_ASSERT (func_env != NULL );
570+ need_pop = 0 ;
564571 if (DUK_HOBJECT_HAS_NAMEBINDING ((duk_hobject * ) h_fun )) {
565572 /* Original function instance/template had NAMEBINDING.
566573 * Must create a lexical environment on loading to allow
567574 * recursive functions like 'function foo() { foo(); }'.
568575 */
569- duk_hobject * proto ;
576+ duk_hobject * new_env ;
577+
578+ new_env = duk_push_object_helper_proto (ctx ,
579+ DUK_HOBJECT_FLAG_EXTENSIBLE |
580+ DUK_HOBJECT_CLASS_AS_FLAGS (DUK_HOBJECT_CLASS_DECENV ),
581+ func_env );
582+ DUK_ASSERT (new_env != NULL );
583+ func_env = new_env ;
570584
571- proto = thr -> builtins [DUK_BIDX_GLOBAL_ENV ];
572- (void ) duk_push_object_helper_proto (ctx ,
573- DUK_HOBJECT_FLAG_EXTENSIBLE |
574- DUK_HOBJECT_CLASS_AS_FLAGS (DUK_HOBJECT_CLASS_DECENV ),
575- proto );
576585 duk_dup_m2 (ctx ); /* -> [ func funcname env funcname ] */
577586 duk_dup (ctx , idx_base ); /* -> [ func funcname env funcname func ] */
578587 duk_xdef_prop (ctx , -3 , DUK_PROPDESC_FLAGS_NONE ); /* -> [ func funcname env ] */
579- duk_xdef_prop_stridx (ctx , idx_base , DUK_STRIDX_INT_LEXENV , DUK_PROPDESC_FLAGS_WC );
580- /* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
581- * will be ignored anyway
582- */
588+
589+ need_pop = 1 ; /* Need to pop env, but -after- updating h_fun and increfs. */
590+ }
591+ DUK_ASSERT (func_env != NULL );
592+ DUK_HCOMPFUNC_SET_LEXENV (thr -> heap , h_fun , func_env );
593+ DUK_HCOMPFUNC_SET_VARENV (thr -> heap , h_fun , func_env );
594+ DUK_HOBJECT_INCREF (thr , func_env );
595+ DUK_HOBJECT_INCREF (thr , func_env );
596+ if (need_pop ) {
597+ duk_pop (ctx );
583598 }
584599 duk_xdef_prop_stridx (ctx , -2 , DUK_STRIDX_NAME , DUK_PROPDESC_FLAGS_NONE );
585600
0 commit comments