diff --git a/source/texk/web2c/luatexdir/font/luafont.c b/source/texk/web2c/luatexdir/font/luafont.c
index e64aaffc1..5831e33a8 100644
--- a/source/texk/web2c/luatexdir/font/luafont.c
+++ b/source/texk/web2c/luatexdir/font/luafont.c
@@ -221,12 +221,16 @@ static void font_char_to_lua(lua_State * L, internal_font_number f, charinfo * c
             lua_push_string_by_name(L,horiz_variants);
             lua_newtable(L);
             while (h != NULL) {
-                lua_createtable(L, 0, 5);
-                dump_intfield(L, glyph, h->glyph);
-                dump_intfield(L, extender, h->extender);
-                dump_intfield(L, start, h->start_overlap);
-                dump_intfield(L, end, h->end_overlap);
-                dump_intfield(L, advance, h->advance);
+                if (h->glyph < 0) {
+                    lua_rawgeti(L, LUA_REGISTRYINDEX, -h->glyph);
+                } else {
+                    lua_createtable(L, 0, 5);
+                    dump_intfield(L, glyph, h->glyph);
+                    dump_intfield(L, extender, h->extender);
+                    dump_intfield(L, start, h->start_overlap);
+                    dump_intfield(L, end, h->end_overlap);
+                    dump_intfield(L, advance, h->advance);
+                }
                 lua_rawseti(L, -2, i);
                 i++;
                 h = h->next;
@@ -239,12 +243,16 @@ static void font_char_to_lua(lua_State * L, internal_font_number f, charinfo * c
             lua_push_string_by_name(L,vert_variants);
             lua_newtable(L);
             while (h != NULL) {
-                lua_createtable(L, 0, 5);
-                dump_intfield(L, glyph, h->glyph);
-                dump_intfield(L, extender, h->extender);
-                dump_intfield(L, start, h->start_overlap);
-                dump_intfield(L, end, h->end_overlap);
-                dump_intfield(L, advance, h->advance);
+                if (h->glyph < 0) {
+                    lua_rawgeti(L, LUA_REGISTRYINDEX, -h->glyph);
+                } else {
+                    lua_createtable(L, 0, 5);
+                    dump_intfield(L, glyph, h->glyph);
+                    dump_intfield(L, extender, h->extender);
+                    dump_intfield(L, start, h->start_overlap);
+                    dump_intfield(L, end, h->end_overlap);
+                    dump_intfield(L, advance, h->advance);
+                }
                 lua_rawseti(L, -2, i);
                 i++;
                 h = h->next;
@@ -1239,6 +1247,9 @@ static void font_char_from_lua(lua_State * L, internal_font_number f, int i, int
                         h = new_variant(glyph, startconnect, endconnect, advance, extender);
                         add_charinfo_hor_variant(co, h);
                         lua_pop(L, 1);
+                    } else if (lua_isfunction(L, -1)) {
+                        h = new_variant(-luaL_ref(L, LUA_REGISTRYINDEX), 0, 0, 0, 0);
+                        add_charinfo_hor_variant(co, h);
                     } else {
                         lua_pop(L, 1);
                         break;
@@ -1263,6 +1274,9 @@ static void font_char_from_lua(lua_State * L, internal_font_number f, int i, int
                         h = new_variant(glyph, startconnect, endconnect, advance, extender);
                         add_charinfo_vert_variant(co, h);
                         lua_pop(L, 1);
+                    } else if (lua_isfunction(L, -1)) {
+                        h = new_variant(-luaL_ref(L, LUA_REGISTRYINDEX), 0, 0, 0, 0);
+                        add_charinfo_vert_variant(co, h);
                     } else {
                         lua_pop(L, 1);
                         break;
diff --git a/source/texk/web2c/luatexdir/font/texfont.c b/source/texk/web2c/luatexdir/font/texfont.c
index 332a8a344..a3f0a8f31 100644
--- a/source/texk/web2c/luatexdir/font/texfont.c
+++ b/source/texk/web2c/luatexdir/font/texfont.c
@@ -387,7 +387,7 @@ extinfo *new_variant(int glyph, int startconnect, int endconnect, int advance, i
     ext = xmalloc(sizeof(extinfo));
     ext->next = NULL;
     ext->glyph = glyph;
-    ext->start_overlap = startconnect;
+    ext->start_overlap = glyph < 0 ? 1 : startconnect;
     ext->end_overlap = endconnect;
     ext->advance = advance;
     ext->extender = repeater;
@@ -397,6 +397,10 @@ extinfo *new_variant(int glyph, int startconnect, int endconnect, int advance, i
 static extinfo *copy_variant(extinfo * old)
 {
     extinfo *ext;
+    if (old->glyph < 0) {
+      old->start_overlap += 1;
+      return old;
+    }
     ext = xmalloc(sizeof(extinfo));
     ext->next = NULL;
     ext->glyph = old->glyph;
@@ -616,7 +620,14 @@ void set_charinfo_vert_variants(charinfo * ci, extinfo * ext)
         lst = ci->vert_variants;
         while (lst != NULL) {
             c = lst->next;
-            free(lst);
+            if (lst->glyph < 0) {
+                if (--lst->start_overlap == 0) {
+                    luaL_unref(Luas, LUA_REGISTRYINDEX, -lst->glyph);
+                    free(lst);
+                }
+            } else {
+                free(lst);
+            }
             lst = c;
         }
     }
@@ -630,7 +641,14 @@ void set_charinfo_hor_variants(charinfo * ci, extinfo * ext)
         lst = ci->hor_variants;
         while (lst != NULL) {
             c = lst->next;
-            free(lst);
+            if (lst->glyph < 0) {
+                if (--lst->start_overlap == 0) {
+                    luaL_unref(Luas, LUA_REGISTRYINDEX, -lst->glyph);
+                    free(lst);
+                }
+            } else {
+                free(lst);
+            }
             lst = c;
         }
     }
diff --git a/source/texk/web2c/luatexdir/tex/mlist.c b/source/texk/web2c/luatexdir/tex/mlist.c
index 16fdf1250..887d6e988 100644
--- a/source/texk/web2c/luatexdir/tex/mlist.c
+++ b/source/texk/web2c/luatexdir/tex/mlist.c
@@ -1247,6 +1247,8 @@ int cur_size;
 static pointer get_delim_box(pointer q, extinfo * ext, internal_font_number f, scaled v,
     pointer att, int cur_style, int boxtype)
 {
+    /*tex is this box drawn by lua? */
+    int lua_box = 0;
     /*tex new box */
     pointer b;
     /*tex natural (maximum) size of the stack */
@@ -1271,6 +1273,10 @@ static pointer get_delim_box(pointer q, extinfo * ext, internal_font_number f, s
     num_normal = 0;
     cur = ext;
     while (cur != NULL) {
+        if (cur->glyph < 0) {
+            lua_box = 1;
+            break;
+        }
         if (!char_exists(f, cur->glyph)) {
             const char *hlp[] = {
                 "Each glyph part in an extensible item should exist in the font.",
@@ -1303,6 +1309,51 @@ static pointer get_delim_box(pointer q, extinfo * ext, internal_font_number f, s
         }
         cur = cur->next;
     }
+    if (lua_box != 0) {
+        int sfix, i;
+        if (num_normal != 0 || num_extenders != 0 || cur->next != NULL) {
+            const char *hlp[] = {
+                "A extensible recipe containing a Lua function should not have any",
+                "other elements. I will ignore everything except for the first",
+                "function. Fix your font!",
+                NULL
+            };
+            tex_error("Lua-Extensible recipe has additional elements.", hlp);
+        }
+        if (boxtype == vlist_node)
+            height(b) = v;
+        else
+            width(b) = v;
+        sfix = lua_gettop(Luas);
+        lua_rawgeti(Luas, LUA_REGISTRYINDEX, -cur->glyph);
+        if (lua_type(Luas, -1) != LUA_TFUNCTION) {
+            lua_settop(Luas, sfix);
+            const char *hlp[] = {
+                "A extensible recipe references a non-existant Lua function. I will",
+                "give up trying to build the delimiter for now. Ask a wizard!",
+                NULL
+            };
+            tex_error("Invalid Lua recipe.", hlp);
+            width(b) = null_delimiter_space_par;
+            return b;
+        }
+        lua_pushinteger(Luas, v);
+        lua_push_math_style_name(Luas, cur_style);
+        lua_nodelib_push_fast(Luas, att);
+        lua_pushinteger(Luas, boxtype);
+        lua_pushinteger(Luas, f);
+        if ((i=lua_pcall(Luas, 5, 1, 0)) != 0) {
+            formatted_warning("get_delim_box","error: %s",lua_tostring(Luas, -1));
+            lua_settop(Luas, sfix);
+            luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
+            width(b) = null_delimiter_space_par;
+            return b;
+        }
+        flush_node(b);
+        b = nodelist_from_lua(Luas, -1);
+        lua_settop(Luas, sfix);
+        return b;
+    }
     if (num_normal == 0) {
         const char *hlp[] = {
             "Each extensible recipe should have at least one non-repeatable part.",
-- 
2.18.0

