diff --git a/lib/libesp32/Berry/src/be_class.c b/lib/libesp32/Berry/src/be_class.c
index 280e3e6d0..ffb196372 100644
--- a/lib/libesp32/Berry/src/be_class.c
+++ b/lib/libesp32/Berry/src/be_class.c
@@ -165,6 +165,7 @@ static binstance* newobjself(bvm *vm, bclass *c)
while (v < end) { var_setnil(v); ++v; }
obj->_class = c;
obj->super = NULL;
+ obj->sub = NULL;
}
return obj;
}
@@ -178,6 +179,7 @@ static binstance* newobject(bvm *vm, bclass *c)
be_incrtop(vm); /* protect new objects from GC */
for (c = c->super; c; c = c->super) {
prev->super = newobjself(vm, c);
+ prev->super->sub = prev;
prev = prev->super;
}
be_stackpop(vm, 1);
diff --git a/lib/libesp32/Berry/src/be_class.h b/lib/libesp32/Berry/src/be_class.h
index 148f1b57a..3b9458013 100644
--- a/lib/libesp32/Berry/src/be_class.h
+++ b/lib/libesp32/Berry/src/be_class.h
@@ -18,11 +18,13 @@
#define be_class_members(cl) ((cl)->members)
#define be_class_super(cl) ((cl)->super)
#define be_class_setsuper(self, sup) ((self)->super = (sup))
+#define be_class_setsub(self, sub) ((self)->sub = (sub))
#define be_instance_name(obj) ((obj)->_class->name)
#define be_instance_class(obj) ((obj)->_class)
#define be_instance_members(obj) ((obj)->members)
#define be_instance_member_count(obj) ((obj)->_class->nvar)
#define be_instance_super(obj) ((obj)->super)
+#define be_instance_sub(obj) ((obj)->sub)
struct bclass {
bcommon_header;
@@ -41,6 +43,7 @@ struct bclass {
struct binstance {
bcommon_header;
struct binstance *super;
+ struct binstance *sub;
bclass *_class;
bgcobject *gray; /* for gc gray list */
bvalue members[1]; /* members variable data field */
diff --git a/lib/libesp32/Berry/src/be_func.c b/lib/libesp32/Berry/src/be_func.c
index a4e210271..d49229954 100644
--- a/lib/libesp32/Berry/src/be_func.c
+++ b/lib/libesp32/Berry/src/be_func.c
@@ -54,17 +54,22 @@ void be_initupvals(bvm *vm, bclosure *cl)
void be_upvals_close(bvm *vm, bvalue *level)
{
bupval *node = vm->upvalist, *next;
- while (node && node->value >= level) {
+ bupval **prev = &vm->upvalist;
+ while (node) {
next = node->u.next;
- if (!node->refcnt) {
- be_free(vm, node, sizeof(bupval));
+ if (node->value >= level) {
+ if (!node->refcnt) {
+ be_free(vm, node, sizeof(bupval));
+ } else {
+ node->u.value = *node->value; /* move value to upvalue slot */
+ node->value = &node->u.value;
+ }
+ *prev = next; /* remove from linked list */
} else {
- node->u.value = *node->value; /* move value to upvalue slot */
- node->value = &node->u.value;
+ prev = &node->u.next;
}
node = next;
}
- vm->upvalist = node;
}
void be_release_upvalues(bvm *vm, bclosure *cl)
diff --git a/lib/libesp32/Berry/src/be_vm.c b/lib/libesp32/Berry/src/be_vm.c
index b58da91d9..97fee645c 100644
--- a/lib/libesp32/Berry/src/be_vm.c
+++ b/lib/libesp32/Berry/src/be_vm.c
@@ -779,6 +779,11 @@ newframe: /* a new call frame */
int type = obj_attribute(vm, b, c, a);
reg = vm->reg;
if (basetype(type) == BE_FUNCTION) {
+ /* check if the object is a superinstance, if so get the lowest possible subclass */
+ while (obj->sub) {
+ obj = obj->sub;
+ }
+ var_setobj(&self, var_type(&self), obj); /* replace superinstance by lowest subinstance */
a[1] = self;
} else {
vm_error(vm, "attribute_error",
diff --git a/lib/libesp32/Berry/tests/closure.be b/lib/libesp32/Berry/tests/closure.be
new file mode 100644
index 000000000..2474fede9
--- /dev/null
+++ b/lib/libesp32/Berry/tests/closure.be
@@ -0,0 +1,13 @@
+#- test for issue #105 -#
+
+l=[]
+def tick()
+ var start=100
+ for i : 1..3
+ l.push(def () return [i, start] end)
+ end
+end
+tick()
+assert(l[0]() == [1, 100])
+assert(l[1]() == [2, 100])
+assert(l[2]() == [3, 100])
diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino
index e92650fe9..31ef3cef3 100644
--- a/tasmota/xdrv_01_webserver.ino
+++ b/tasmota/xdrv_01_webserver.ino
@@ -1017,7 +1017,9 @@ void WebSliderColdWarm(void)
void HandleRoot(void)
{
+#ifndef NO_CAPTIVE_PORTAL
if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the page.
+#endif // NO_CAPTIVE_PORTAL
if (Webserver->hasArg(F("rst"))) {
WebRestart(0);
@@ -2941,8 +2943,9 @@ void HandleConsoleRefresh(void)
void HandleNotFound(void)
{
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Not found (%s)"), Webserver->uri().c_str());
-
+#ifndef NO_CAPTIVE_PORTAL
if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the error page.
+#endif // NO_CAPTIVE_PORTAL
#ifdef USE_EMULATION
#ifdef USE_EMULATION_HUE
@@ -2962,6 +2965,7 @@ void HandleNotFound(void)
}
}
+#ifndef NO_CAPTIVE_PORTAL
/* Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */
bool CaptivePortal(void)
{
@@ -2976,6 +2980,7 @@ bool CaptivePortal(void)
}
return false;
}
+#endif // NO_CAPTIVE_PORTAL
/*********************************************************************************************/
diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino
index 9a791c751..d453efbaf 100644
--- a/tasmota/xdrv_04_light.ino
+++ b/tasmota/xdrv_04_light.ino
@@ -2497,11 +2497,18 @@ void CmndSupportColor(void)
else {
#endif // USE_LIGHT_PALETTE
uint32_t old_bri = light_state.getBri();
+ uint32_t old_bri_rgb = light_state.getBriRGB();
// change all channels to specified values
light_controller.changeChannels(Light.entry_color);
if (2 == XdrvMailbox.index) {
// If Color2, set back old brightness
- LightSetBriScaled(old_bri);
+ if (light_controller.isCTRGBLinked()) {
+ // RGB and white are linked, adjust brightness of all channels
+ LightSetBriScaled(old_bri);
+ } else {
+ // RGB and white are unlinked, adjust brightness only of RGB channels
+ LightSetBri(Light.device, old_bri_rgb);
+ }
}
#ifdef USE_LIGHT_PALETTE
}
diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino
index a58044431..4840f7a54 100644
--- a/tasmota/xdrv_52_9_berry.ino
+++ b/tasmota/xdrv_52_9_berry.ino
@@ -593,7 +593,7 @@ const char HTTP_BERRY_FORM_CMND[] PROGMEM =
"
"
"