Build modified streamline images

The official image from streamline does not currently work for the arm64
platform. As a temporary measure, the source code and docker build scripts
have been lifted from the official images and are used to build locally.

Some additional modifications are made to reduce overall image size, these
are documented in docker/README.md
This commit is contained in:
2024-03-10 16:17:50 -07:00
parent 2ffc3c408a
commit a424394109
13506 changed files with 1860172 additions and 6 deletions
@@ -0,0 +1,514 @@
<?php
namespace Laravel\SerializableClosure\Serializers;
use Closure;
use DateTimeInterface;
use Laravel\SerializableClosure\Contracts\Serializable;
use Laravel\SerializableClosure\SerializableClosure;
use Laravel\SerializableClosure\Support\ClosureScope;
use Laravel\SerializableClosure\Support\ClosureStream;
use Laravel\SerializableClosure\Support\ReflectionClosure;
use Laravel\SerializableClosure\Support\SelfReference;
use Laravel\SerializableClosure\UnsignedSerializableClosure;
use ReflectionObject;
use UnitEnum;
class Native implements Serializable
{
/**
* Transform the use variables before serialization.
*
* @var \Closure|null
*/
public static $transformUseVariables;
/**
* Resolve the use variables after unserialization.
*
* @var \Closure|null
*/
public static $resolveUseVariables;
/**
* The closure to be serialized/unserialized.
*
* @var \Closure
*/
protected $closure;
/**
* The closure's reflection.
*
* @var \Laravel\SerializableClosure\Support\ReflectionClosure|null
*/
protected $reflector;
/**
* The closure's code.
*
* @var array|null
*/
protected $code;
/**
* The closure's reference.
*
* @var string
*/
protected $reference;
/**
* The closure's scope.
*
* @var \Laravel\SerializableClosure\Support\ClosureScope|null
*/
protected $scope;
/**
* The "key" that marks an array as recursive.
*/
const ARRAY_RECURSIVE_KEY = 'LARAVEL_SERIALIZABLE_RECURSIVE_KEY';
/**
* Creates a new serializable closure instance.
*
* @param \Closure $closure
* @return void
*/
public function __construct(Closure $closure)
{
$this->closure = $closure;
}
/**
* Resolve the closure with the given arguments.
*
* @return mixed
*/
public function __invoke()
{
return call_user_func_array($this->closure, func_get_args());
}
/**
* Gets the closure.
*
* @return \Closure
*/
public function getClosure()
{
return $this->closure;
}
/**
* Get the serializable representation of the closure.
*
* @return array
*/
public function __serialize()
{
if ($this->scope === null) {
$this->scope = new ClosureScope();
$this->scope->toSerialize++;
}
$this->scope->serializations++;
$scope = $object = null;
$reflector = $this->getReflector();
if ($reflector->isBindingRequired()) {
$object = $reflector->getClosureThis();
static::wrapClosures($object, $this->scope);
}
if ($scope = $reflector->getClosureScopeClass()) {
$scope = $scope->name;
}
$this->reference = spl_object_hash($this->closure);
$this->scope[$this->closure] = $this;
$use = $reflector->getUseVariables();
if (static::$transformUseVariables) {
$use = call_user_func(static::$transformUseVariables, $reflector->getUseVariables());
}
$code = $reflector->getCode();
$this->mapByReference($use);
$data = [
'use' => $use,
'function' => $code,
'scope' => $scope,
'this' => $object,
'self' => $this->reference,
];
if (! --$this->scope->serializations && ! --$this->scope->toSerialize) {
$this->scope = null;
}
return $data;
}
/**
* Restore the closure after serialization.
*
* @param array $data
* @return void
*/
public function __unserialize($data)
{
ClosureStream::register();
$this->code = $data;
unset($data);
$this->code['objects'] = [];
if ($this->code['use']) {
$this->scope = new ClosureScope();
if (static::$resolveUseVariables) {
$this->code['use'] = call_user_func(static::$resolveUseVariables, $this->code['use']);
}
$this->mapPointers($this->code['use']);
extract($this->code['use'], EXTR_OVERWRITE | EXTR_REFS);
$this->scope = null;
}
$this->closure = include ClosureStream::STREAM_PROTO.'://'.$this->code['function'];
if ($this->code['this'] === $this) {
$this->code['this'] = null;
}
$this->closure = $this->closure->bindTo($this->code['this'], $this->code['scope']);
if (! empty($this->code['objects'])) {
foreach ($this->code['objects'] as $item) {
$item['property']->setValue($item['instance'], $item['object']->getClosure());
}
}
$this->code = $this->code['function'];
}
/**
* Ensures the given closures are serializable.
*
* @param mixed $data
* @param \Laravel\SerializableClosure\Support\ClosureScope $storage
* @return void
*/
public static function wrapClosures(&$data, $storage)
{
if ($data instanceof Closure) {
$data = new static($data);
} elseif (is_array($data)) {
if (isset($data[self::ARRAY_RECURSIVE_KEY])) {
return;
}
$data[self::ARRAY_RECURSIVE_KEY] = true;
foreach ($data as $key => &$value) {
if ($key === self::ARRAY_RECURSIVE_KEY) {
continue;
}
static::wrapClosures($value, $storage);
}
unset($value);
unset($data[self::ARRAY_RECURSIVE_KEY]);
} elseif ($data instanceof \stdClass) {
if (isset($storage[$data])) {
$data = $storage[$data];
return;
}
$data = $storage[$data] = clone $data;
foreach ($data as &$value) {
static::wrapClosures($value, $storage);
}
unset($value);
} elseif (is_object($data) && ! $data instanceof static && ! $data instanceof UnitEnum) {
if (isset($storage[$data])) {
$data = $storage[$data];
return;
}
$instance = $data;
$reflection = new ReflectionObject($instance);
if (! $reflection->isUserDefined()) {
$storage[$instance] = $data;
return;
}
$storage[$instance] = $data = $reflection->newInstanceWithoutConstructor();
do {
if (! $reflection->isUserDefined()) {
break;
}
foreach ($reflection->getProperties() as $property) {
if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) {
continue;
}
$property->setAccessible(true);
if (PHP_VERSION >= 7.4 && ! $property->isInitialized($instance)) {
continue;
}
$value = $property->getValue($instance);
if (is_array($value) || is_object($value)) {
static::wrapClosures($value, $storage);
}
$property->setValue($data, $value);
}
} while ($reflection = $reflection->getParentClass());
}
}
/**
* Gets the closure's reflector.
*
* @return \Laravel\SerializableClosure\Support\ReflectionClosure
*/
public function getReflector()
{
if ($this->reflector === null) {
$this->code = null;
$this->reflector = new ReflectionClosure($this->closure);
}
return $this->reflector;
}
/**
* Internal method used to map closure pointers.
*
* @param mixed $data
* @return void
*/
protected function mapPointers(&$data)
{
$scope = $this->scope;
if ($data instanceof static) {
$data = &$data->closure;
} elseif (is_array($data)) {
if (isset($data[self::ARRAY_RECURSIVE_KEY])) {
return;
}
$data[self::ARRAY_RECURSIVE_KEY] = true;
foreach ($data as $key => &$value) {
if ($key === self::ARRAY_RECURSIVE_KEY) {
continue;
} elseif ($value instanceof static) {
$data[$key] = &$value->closure;
} elseif ($value instanceof SelfReference && $value->hash === $this->code['self']) {
$data[$key] = &$this->closure;
} else {
$this->mapPointers($value);
}
}
unset($value);
unset($data[self::ARRAY_RECURSIVE_KEY]);
} elseif ($data instanceof \stdClass) {
if (isset($scope[$data])) {
return;
}
$scope[$data] = true;
foreach ($data as $key => &$value) {
if ($value instanceof SelfReference && $value->hash === $this->code['self']) {
$data->{$key} = &$this->closure;
} elseif (is_array($value) || is_object($value)) {
$this->mapPointers($value);
}
}
unset($value);
} elseif (is_object($data) && ! ($data instanceof Closure)) {
if (isset($scope[$data])) {
return;
}
$scope[$data] = true;
$reflection = new ReflectionObject($data);
do {
if (! $reflection->isUserDefined()) {
break;
}
foreach ($reflection->getProperties() as $property) {
if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) {
continue;
}
$property->setAccessible(true);
if (PHP_VERSION >= 7.4 && ! $property->isInitialized($data)) {
continue;
}
$item = $property->getValue($data);
if ($item instanceof SerializableClosure || $item instanceof UnsignedSerializableClosure || ($item instanceof SelfReference && $item->hash === $this->code['self'])) {
$this->code['objects'][] = [
'instance' => $data,
'property' => $property,
'object' => $item instanceof SelfReference ? $this : $item,
];
} elseif (is_array($item) || is_object($item)) {
$this->mapPointers($item);
$property->setValue($data, $item);
}
}
} while ($reflection = $reflection->getParentClass());
}
}
/**
* Internal method used to map closures by reference.
*
* @param mixed $data
* @return void
*/
protected function mapByReference(&$data)
{
if ($data instanceof Closure) {
if ($data === $this->closure) {
$data = new SelfReference($this->reference);
return;
}
if (isset($this->scope[$data])) {
$data = $this->scope[$data];
return;
}
$instance = new static($data);
$instance->scope = $this->scope;
$data = $this->scope[$data] = $instance;
} elseif (is_array($data)) {
if (isset($data[self::ARRAY_RECURSIVE_KEY])) {
return;
}
$data[self::ARRAY_RECURSIVE_KEY] = true;
foreach ($data as $key => &$value) {
if ($key === self::ARRAY_RECURSIVE_KEY) {
continue;
}
$this->mapByReference($value);
}
unset($value);
unset($data[self::ARRAY_RECURSIVE_KEY]);
} elseif ($data instanceof \stdClass) {
if (isset($this->scope[$data])) {
$data = $this->scope[$data];
return;
}
$instance = $data;
$this->scope[$instance] = $data = clone $data;
foreach ($data as &$value) {
$this->mapByReference($value);
}
unset($value);
} elseif (is_object($data) && ! $data instanceof SerializableClosure && ! $data instanceof UnsignedSerializableClosure) {
if (isset($this->scope[$data])) {
$data = $this->scope[$data];
return;
}
$instance = $data;
if ($data instanceof DateTimeInterface) {
$this->scope[$instance] = $data;
return;
}
if ($data instanceof UnitEnum) {
$this->scope[$instance] = $data;
return;
}
$reflection = new ReflectionObject($data);
if (! $reflection->isUserDefined()) {
$this->scope[$instance] = $data;
return;
}
$this->scope[$instance] = $data = $reflection->newInstanceWithoutConstructor();
do {
if (! $reflection->isUserDefined()) {
break;
}
foreach ($reflection->getProperties() as $property) {
if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) {
continue;
}
$property->setAccessible(true);
if (PHP_VERSION >= 7.4 && ! $property->isInitialized($instance)) {
continue;
}
$value = $property->getValue($instance);
if (is_array($value) || is_object($value)) {
$this->mapByReference($value);
}
$property->setValue($data, $value);
}
} while ($reflection = $reflection->getParentClass());
}
}
}
@@ -0,0 +1,91 @@
<?php
namespace Laravel\SerializableClosure\Serializers;
use Laravel\SerializableClosure\Contracts\Serializable;
use Laravel\SerializableClosure\Exceptions\InvalidSignatureException;
use Laravel\SerializableClosure\Exceptions\MissingSecretKeyException;
class Signed implements Serializable
{
/**
* The signer that will sign and verify the closure's signature.
*
* @var \Laravel\SerializableClosure\Contracts\Signer|null
*/
public static $signer;
/**
* The closure to be serialized/unserialized.
*
* @var \Closure
*/
protected $closure;
/**
* Creates a new serializable closure instance.
*
* @param \Closure $closure
* @return void
*/
public function __construct($closure)
{
$this->closure = $closure;
}
/**
* Resolve the closure with the given arguments.
*
* @return mixed
*/
public function __invoke()
{
return call_user_func_array($this->closure, func_get_args());
}
/**
* Gets the closure.
*
* @return \Closure
*/
public function getClosure()
{
return $this->closure;
}
/**
* Get the serializable representation of the closure.
*
* @return array
*/
public function __serialize()
{
if (! static::$signer) {
throw new MissingSecretKeyException();
}
return static::$signer->sign(
serialize(new Native($this->closure))
);
}
/**
* Restore the closure after serialization.
*
* @param array $signature
* @return void
*
* @throws \Laravel\SerializableClosure\Exceptions\InvalidSignatureException
*/
public function __unserialize($signature)
{
if (static::$signer && ! static::$signer->verify($signature)) {
throw new InvalidSignatureException();
}
/** @var \Laravel\SerializableClosure\Contracts\Serializable $serializable */
$serializable = unserialize($signature['serializable']);
$this->closure = $serializable->getClosure();
}
}