refactor(core): update dependency and improve unset handling for native types

- Update swoole/phpx from ~2.7.0 to ~2.8.0 in composer.json
- Add proper button styling for macOS 11+ with automatic button styles
- Fix control nil check in macos_bridge.mm to prevent crashes
- Use title property for NSButton updates on macOS to handle system-style buttons
- Refactor unset handling in PropertyAccessTrait to use type-specific defaults
- Replace hardcoded default values with Type::getDefaultValueExpression calls
- Add
master
韩天峰 1 month ago
parent d1136cfca0
commit 10fbfff4ea
  1. 2
      composer.json
  2. 18
      examples/objective-c-macos/objc-src/macos_bridge.mm
  3. 24
      src/Parser/PropertyAccessTrait.php
  4. 13
      src/Resolver/PropertyAssignTypeInfo.php
  5. 19
      src/Type.php

@ -21,7 +21,7 @@
"marcj/topsort": "^2.0",
"symfony/var-dumper": "^8.0",
"symfony/yaml": "^8.0",
"swoole/phpx": "~2.7.0",
"swoole/phpx": "~2.8.0",
"ajaxray/ansikit": "^0.3",
"ext-dom": "*"
},

@ -147,7 +147,10 @@ php::Int php_ui_add_button(
static_cast<CGFloat>(y),
static_cast<CGFloat>(width),
static_cast<CGFloat>(height));
button.bezelStyle = NSBezelStyleRounded;
// macOS 11+: keep the automatic button style. Forcing the legacy
// NSBezelStyleRounded disables the accent fill that the primary button
// needs behind its white title. The automatic style also makes
// bezelColor render as a proper filled button.
button.controlSize = NSControlSizeLarge;
button.font = [NSFont systemFontOfSize:14 weight:NSFontWeightSemibold];
if (style == 1) {
@ -165,8 +168,17 @@ void php_ui_set_control_text(php::Int controlId, php::Str text)
{
@autoreleasepool {
NSControl *control = bridge.controls[@(static_cast<NSInteger>(controlId))];
if (control != nil) {
control.stringValue = to_ns_string(text);
if (control == nil) {
return;
}
NSString *value = to_ns_string(text);
if ([control isKindOfClass:NSButton.class]) {
// Update the title through the NSButton property. System-style
// buttons (macOS 11+) draw from their attributed title; assigning
// only the raw cell stringValue can leave the button blank.
((NSButton *)control).title = value;
} else {
control.stringValue = value;
}
}
}

@ -1090,19 +1090,23 @@ trait PropertyAccessTrait
if ($this->isNativeObjectVar($name)) {
$this->forgetNativeObjectNonNull($name);
$lines[] = "{$name} = nullptr;";
} elseif ($this->isNativeType($type)) {
$this->warning($var, "Variable of native type `\${$name}` cannot be unset");
} elseif ($type === Type::STR || $type === Type::ARRAY) {
// String and Array reset to Zend's immutable empty
// singletons. This releases the previous value without
// allocating a replacement that will usually stay empty.
$lines[] = "{$name}.unset();";
} elseif (($defaultValue = Type::getDefaultValueExpression($type)) !== null) {
// A fixed value type must preserve its storage invariant.
// unset() releases the previous value and restores the
// type's initial state instead of introducing UNDEF.
$lines[] = "{$name} = {$defaultValue};";
} elseif ($type === Type::OBJECT) {
// A PHP local read after unset() evaluates to null (and may
// emit an undefined-variable warning). Keep the Object
// wrapper so later object assignments remain valid, but
// store NULL rather than IS_UNDEF so strict null checks
// retain PHP value semantics.
//
// Keep the declared class: unset() changes only the value
// state and does not make null or another class assignable.
// Objects have no empty object value. Null is their valid
// initial state; keep the declared class constraint so a
// later assignment must still contain a compatible object.
$lines[] = "{$name} = php::null;";
} else {
// Dynamic storage retains PHP's true undefined state.
$lines[] = "{$name}.unset();";
}
} else {

@ -16,14 +16,11 @@ final class PropertyAssignTypeInfo
{
public function getFixedDefaultValue(PropertyDef $def): ?string
{
return match ($def->type) {
Type::INT => $def->default ?? '0',
Type::FLOAT => $def->default ?? '0.0',
Type::BOOL => $def->default ?? 'false',
Type::STR => $def->default ?? Type::STR . '()',
Type::ARRAY => $def->default ?? Type::ARRAY . '{}',
default => null,
};
$typeDefault = Type::getDefaultValueExpression($def->type);
if ($typeDefault === null) {
return null;
}
return $def->default ?? $typeDefault;
}
public function isFixed(PropertyDef $def): bool

@ -70,4 +70,23 @@ final class Type
default => $type,
};
}
/**
* Return the C++ expression for the initial state of a fixed value type.
*
* Fixed TypePHP storage never becomes UNDEF: unset() releases the current
* value and restores this state instead. Objects are handled separately
* because null is their valid empty state rather than a value-type default.
*/
public static function getDefaultValueExpression(string $type): ?string
{
return match ($type) {
self::INT => '0',
self::FLOAT => '0.0',
self::BOOL => 'false',
self::STR => self::STR . '()',
self::ARRAY => self::ARRAY . '{}',
default => null,
};
}
}

Loading…
Cancel
Save