diff --git a/src/Peachpie.Library.Scripting/Context.Script.cs b/src/Peachpie.Library.Scripting/Context.Script.cs
index 8b103c7bbf..7ff59c7df3 100644
--- a/src/Peachpie.Library.Scripting/Context.Script.cs
+++ b/src/Peachpie.Library.Scripting/Context.Script.cs
@@ -15,11 +15,23 @@
namespace Peachpie.Library.Scripting
{
+ ///
+ /// Represents a script created by .
+ ///
+ [PhpHidden]
+ public interface IScript : Context.IScript
+ {
+ ///
+ /// Assembly byte content.
+ ///
+ ImmutableArray Image { get; }
+ }
+
///
/// Script representing a compiled submission.
///
[DebuggerDisplay("Script ({AssemblyName.Name})")]
- sealed class Script : Context.IScript
+ sealed class Script : IScript
{
#region Fields & Properties
diff --git a/src/Peachpie.Runtime/Attributes.cs b/src/Peachpie.Runtime/Attributes.cs
index b0f86b133a..179afbe6f0 100644
--- a/src/Peachpie.Runtime/Attributes.cs
+++ b/src/Peachpie.Runtime/Attributes.cs
@@ -171,7 +171,7 @@ public TargetPhpLanguageAttribute(string langVersion, bool shortOpenTag)
///
/// Marks public declarations that won't be visible in the PHP context.
///
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public sealed class PhpHiddenAttribute : Attribute
{
}
diff --git a/src/Tests/Peachpie.App.Tests/CompiledILTest.cs b/src/Tests/Peachpie.App.Tests/CompiledILTest.cs
new file mode 100644
index 0000000000..91c5775fb4
--- /dev/null
+++ b/src/Tests/Peachpie.App.Tests/CompiledILTest.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Pchp.Core;
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.CSharp;
+using ICSharpCode.Decompiler.TypeSystem;
+using ICSharpCode.Decompiler.Metadata;
+using Peachpie.Library.Scripting;
+using System.Reflection.PortableExecutable;
+using System.Reflection.Metadata;
+using ICSharpCode.Decompiler.CSharp.Syntax;
+
+
+namespace Peachpie.App.Tests
+{
+ [TestClass]
+ public class CompiledILTest
+ {
+ static IScript Compile(string code)
+ {
+ using (var ctx = Context.CreateConsole(string.Empty))
+ {
+ return (IScript)Context.DefaultScriptingProvider.CreateScript(new Context.ScriptOptions()
+ {
+ Context = ctx,
+ Location = new Location(Path.Combine(Directory.GetCurrentDirectory(), "fake.php"), 0, 0),
+ EmitDebugInformation = true,
+ IsSubmission = false,
+ AdditionalReferences = new string[] {
+ typeof(CompiledILTest).Assembly.Location,
+ },
+ }, code);
+ }
+ }
+
+ static CSharpDecompiler Decompile(IScript script)
+ {
+ var fileName = "fake.dll";
+ var file = new PEFile(fileName, new PEReader(script.Image));
+
+ var resolver = new UniversalAssemblyResolver(
+ fileName,
+ false,
+ file.DetectTargetFrameworkId(),
+ file.DetectRuntimePack(),
+ PEStreamOptions.PrefetchMetadata,
+ MetadataReaderOptions.None
+ );
+
+ return new CSharpDecompiler(new DecompilerTypeSystem(file, resolver), new DecompilerSettings() { });
+ }
+
+ static bool DecompileFunction(IScript script, string fnname, out IMethod method, out AstNode ast)
+ {
+ var minfo = script.GetGlobalRoutineHandle(fnname).Single();
+
+ var decompiler = Decompile(script);
+ var mainType = decompiler.TypeSystem.FindType(new FullTypeName(minfo.DeclaringType.FullName)).GetDefinition();
+
+ method = mainType.Methods.Single(m => m.Name == minfo.Name);
+ ast = decompiler.Decompile(method.MetadataToken).LastChild;
+
+ return true;
+ }
+
+ [TestMethod]
+ public void TestSimpleFunction()
+ {
+ var script = Compile(@"
+