Skip to content

Commit

Permalink
Move away from Objective-C runtime. (johnno1962#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
johnno1962 authored Mar 13, 2023
1 parent f042532 commit aa460a6
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 11 deletions.
11 changes: 7 additions & 4 deletions Sources/HotReloading/SwiftEval.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by John Holdsworth on 02/11/2017.
// Copyright © 2017 John Holdsworth. All rights reserved.
//
// $Id: //depot/HotReloading/Sources/HotReloading/SwiftEval.swift#168 $
// $Id: //depot/HotReloading/Sources/HotReloading/SwiftEval.swift#171 $
//
// Basic implementation of a Swift "eval()" including the
// mechanics of recompiling a class and loading the new
Expand Down Expand Up @@ -398,10 +398,10 @@ public class SwiftEval: NSObject {

guard var (compileCommand, sourceFile) = try
compileByClass[classNameOrFile] ??
(SwiftEval.longTermCache[classNameOrFile] as? String)
.flatMap({ ($0, classNameOrFile) }) ??
findCompileCommand(logsDir: logsDir,
classNameOrFile: classNameOrFile, tmpfile: tmpfile) ??
SwiftEval.longTermCache[classNameOrFile].flatMap({
($0 as! String, classNameOrFile) }) else {
classNameOrFile: classNameOrFile, tmpfile: tmpfile) else {
throw evalError("""
Could not locate compile command for \(classNameOrFile).
This could be due to one of the following:
Expand Down Expand Up @@ -492,6 +492,9 @@ public class SwiftEval: NSObject {
\(compileCommand) >\"\(logfile)\" 2>&1)
""") || isBazelCompile else {
compileByClass.removeValue(forKey: classNameOrFile)
SwiftEval.longTermCache.removeObject(forKey: classNameOrFile)
SwiftEval.longTermCache.write(toFile: SwiftEval.buildCacheFile,
atomically: false)
throw scriptError("Re-compilation")
}

Expand Down
32 changes: 27 additions & 5 deletions Sources/HotReloading/SwiftInjection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by John Holdsworth on 05/11/2017.
// Copyright © 2017 John Holdsworth. All rights reserved.
//
// $Id: //depot/HotReloading/Sources/HotReloading/SwiftInjection.swift#189 $
// $Id: //depot/HotReloading/Sources/HotReloading/SwiftInjection.swift#195 $
//
// Cut-down version of code injection in Swift. Uses code
// from SwiftEval.swift to recompile and reload class.
Expand Down Expand Up @@ -217,8 +217,16 @@ public class SwiftInjection: NSObject {

// First, the old way for non-generics
for var newClass: AnyClass in newClasses {
let oldClasses = versions(of: newClass)
var oldClasses = versions(of: newClass)
injectedGenerics.remove(_typeName(newClass))
if oldClasses.isEmpty {
var info = Dl_info()
if dladdr(autoBitCast(newClass), &info) != 0,
let symbol = info.dli_sname,
let oldClass = dlsym(SwiftMeta.RTLD_MAIN_ONLY, symbol) {
oldClasses.append(autoBitCast(oldClass))
}
}
sweepClasses += oldClasses

for var oldClass: AnyClass in oldClasses {
Expand Down Expand Up @@ -288,7 +296,7 @@ public class SwiftInjection: NSObject {
}

if let XCTestCase = objc_getClass("XCTestCase") as? AnyClass,
newClass.isSubclass(of: XCTestCase) {
isSubclass(newClass, of: XCTestCase) {
testClasses.append(newClass)
}

Expand Down Expand Up @@ -333,13 +341,27 @@ public class SwiftInjection: NSObject {
}
}

open class func isSubclass(_ subClass: AnyClass, of aClass: AnyClass) -> Bool {
var subClass: AnyClass? = subClass
repeat {
if subClass == aClass {
return true
}
subClass = class_getSuperclass(subClass)
} while subClass != nil
return false
}

open class func inheritedGeneric(anyType: Any.Type) -> Bool {
var inheritedGeneric: Any.Type? = anyType
var inheritedGeneric: AnyClass? = anyType as? AnyClass
if class_getSuperclass(inheritedGeneric) == nil {
return true
}
while let parent = inheritedGeneric {
if _typeName(parent).hasSuffix(">") {
return true
}
inheritedGeneric = (parent as? AnyClass)?.superclass()
inheritedGeneric = class_getSuperclass(parent)
}
return false
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/HotReloading/SwiftSweeper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// instance of classes that have been injected in order
// to be able to send them the @objc injected message.
//
// $Id: //depot/HotReloading/Sources/HotReloading/SwiftSweeper.swift#15 $
// $Id: //depot/HotReloading/Sources/HotReloading/SwiftSweeper.swift#16 $
//

import Foundation
Expand Down Expand Up @@ -81,7 +81,7 @@ extension SwiftInjection {
SwiftSweeper(instanceTask: {
(instance: AnyObject) in
if let instanceClass = object_getClass(instance),
injectedClasses.contains(where: { $0 === instanceClass }) ||
injectedClasses.contains(where: { $0 == instanceClass }) ||
!injectedGenerics.isEmpty &&
patchGenerics(oldClass: instanceClass, tmpfile: tmpfile,
injectedGenerics: injectedGenerics, patched: &patched) {
Expand Down

0 comments on commit aa460a6

Please sign in to comment.