Я пытаюсь создать PoC super внутри класса. Итак, я могу создавать веб-компоненты:
Это мой код:
Код: Выделить всё
;; MODIFICATION OF define-class MACRO FROM STANDARD LIBRARY
(define (%class-constructor expr parent)
"(%class-constructor expr)
Version of %class-lambda that is used as constructor."
(let ((args (gensym 'args))
(ret (gensym 'ret)))
`(lambda ,args
(let ((,ret (apply ,(cadr expr) (unbind this) ,args)))
(if (and (object? ,parent) (instanceof ,parent ,ret))
,ret
;; we return this to solve issue when constructor
;; return a promise
;; ref: https://stackoverflow.com/a/50885340/387194
this)))))
(define-macro (define-class name parent . body)
"(define-class name parent . body)
Defines a class - JavaScript function constructor with prototype.
parent needs to be class, constructor function, or #null
usage:
(define-class Person Object
(constructor (lambda (self name)
(set-obj! self '_name name)))
(hi (lambda (self)
(display (string-append self._name \" says hi\"))
(newline))))
(define jack (new Person \"Jack\"))
(jack.hi) ; prints \"Jack says hi\""
(let ((g:parent (gensym)))
(let iter ((functions '()) (constructor '()) (lst body))
(if (null? lst)
`(begin
(define ,name ,(if (null? constructor)
`(lambda ())
(%class-constructor constructor parent)))
(set-obj! ,name (Symbol.for "__class__") true)
(let ((,g:parent ,parent ))
(if (not (null? ,g:parent))
(begin
(set-obj! ,name 'prototype (Object.create (. ,g:parent 'prototype)))
(set-obj! (. ,name 'prototype) 'constructor ,name))))
(set-obj! ,name '__name__ ',name)
,@(map (lambda (fn)
`(set-obj! (. ,name 'prototype)
,(%class-method-name (car fn))
,(%class-lambda fn)))
functions))
(let ((item (car lst)))
(if (eq? (car item) 'constructor)
(iter functions item (cdr lst))
(iter (cons item functions) constructor (cdr lst))))))))
;; MAIN CODE
(define-class CurrentDate HTMLElement
(constructor (lambda (self)
(Reflect.construct HTMLElement #() CurrentDate)))
(connectedCallback (lambda (self)
(let ((now (new Date)))
(set! self.textContent (now.toLocaleDateString))))))
(customElements.define "current-date" CurrentDate)
Код Scheme просто использует прототипы ES5 для создания класса. Это всего лишь сопоставление кода JavaScript в схеме 1-1.
Я постоянно получаю сообщение об ошибке:
Uncaught TypeError: Не удалось создать «HTMLElement»: недопустимый конструктор
(Фрагмент стека не показывает правильную ошибку; вам нужно открыть DevTools)
Я тестировал код из: Как в ES5 пишутся классы веб-компонентов?
Код выдает это выражение:
Код: Выделить всё
(apply ,(cadr expr) this ,args)
Код: Выделить всё
(lambda (self) (Reflect.construct HTMLElement #() CurrentDate))
Это выполняется без ошибок:
Код: Выделить всё
function HelloElement() {
console.log('x');
const ret = make();
console.log(ret);
console.log(ret instanceof HTMLElement);
return ret;
}
function make() {
return Reflect.construct(HTMLElement, [], HelloElement);
}
customElements.define('hello-element', HelloElement);Код: Выделить всё
Я также пытался вызвать JavaScript из Scheme, но получил ту же ошибку:
Код: Выделить всё
(define js-eval self.eval)
(define-macro (super class)
`((js-eval "(unbind, constructor) => Reflect.construct(HTMLElement, [], unbind(constructor));")
,unbind ,class))
(define-class CurrentDate HTMLElement
(constructor (lambda (self)
(super CurrentDate))))
Код: Выделить всё
thisМне удалось вызвать ту же ошибку в JavaScript, добавив:
Код: Выделить всё
return Promise.resolve(ret);
Я могу вызвать ту же ошибку, когда вызываю (new CurrentDate) в Scheme и new HelloElement() в примере с JavaScript. Но я не вызываю new в своей схеме? Код запускается с помощью HTML-кода.
Какие еще могут быть проблемы с моим кодом? И возможная основная причина ошибки?
Подробнее здесь: https://stackoverflow.com/questions/798 ... javascript
Мобильная версия